Skip to content

Commit

Permalink
Add page to generate/preview banner snippets
Browse files Browse the repository at this point in the history
  • Loading branch information
cairomassimo committed Jan 11, 2022
1 parent c729b04 commit ec9169d
Show file tree
Hide file tree
Showing 7 changed files with 363 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/announcement-banner/banner-color-scheme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface BannerColorScheme {
foreground: string;
background: string;
name: string;
}
203 changes: 203 additions & 0 deletions src/announcement-banner/banner-self-service.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import { BannerSnippet } from "announcement-banner/banner-snippet";
import { BannerPreviewPage } from "announcement-banner/example-page-content";
import { textLight } from "layout/colors";
import { quincyRegularFontFamily } from "layout/fonts";
import { css } from "linaria";
import React, { useLayoutEffect, useRef, useState } from "react";
import { renderToString } from "react-dom/server";
import { BannerColorScheme } from "./banner-color-scheme";

const colorSchemes: BannerColorScheme[] = [
{ background: "#001413", foreground: "#D08E39", name: `Dark` },
{ background: "#FAF8F1", foreground: "#002522", name: `Light` },
{ background: "#1C53A6", foreground: "#FFFFFF", name: `Blue` },
];

export function BannerSnippetSelfService() {
const [colorSchemeIndex, setColorSchemeIndex] = useState(0);
const colorScheme = colorSchemes[colorSchemeIndex];

const [inline, setInline] = useState(false);

const frameRef = useRef<HTMLIFrameElement>(null);
const textAreaRef = useRef<HTMLTextAreaElement>(null);

const load = () => {
const frame = frameRef.current;
if (!frame || !frame.contentWindow) return;
frame.srcdoc = examplePageSource;
};

const fixTextAreaHeight = () => {
const textArea = textAreaRef.current;
if (!textArea) return;
textArea.style.height = ``;
textArea.style.height = `${textArea.scrollHeight + 2}px`;
};

useLayoutEffect(load);
useLayoutEffect(fixTextAreaHeight);

useLayoutEffect(() => {
window.addEventListener("resize", fixTextAreaHeight);
return () => {
window.removeEventListener("resize", fixTextAreaHeight);
};
});

const bannerSource =
`<!-- TALLY BANNER -->` +
renderToString(<BannerSnippet colorScheme={colorScheme} inline={inline} />)
.replace(/<!-- -->/g, ``)
.replace(/ data-reactroot=""/g, ``)
.replace(/attr-/g, ``) +
`<!-- END TALLY BANNER -->`;

const examplePageSource = renderToString(
<BannerPreviewPage inline={inline} />
).replace(`%BANNER%`, bannerSource);

return (
<>
<div
className={css`
display: flex;
flex-flow: column;
padding: 8rem 0 2rem;
`}
>
<div
className={css`
display: flex;
flex-flow: column;
align-items: center;
width: 100%;
max-width: 75rem;
margin: 0 auto;
`}
>
<h1
className={css`
margin: 2rem 0;
padding: 0 2rem;
font-family: ${quincyRegularFontFamily};
font-size: min(64px, 8vw);
font-weight: normal;
line-height: 110%;
color: ${textLight};
`}
>
Add Tally banner to your site
</h1>
</div>
</div>

<div
className={css`
color: white;
max-width: 72rem;
margin: 0 auto;
padding: 2rem;
label {
display: block;
margin: 1rem 0;
}
`}
>
<label>
Color scheme:{" "}
<select
onChange={(event) => {
setColorSchemeIndex(
Number.parseInt(event.currentTarget.value, 10)
);
}}
>
{colorSchemes.map((scheme, i) => (
<option value={i}>{scheme.name}</option>
))}
</select>
</label>

<label>
Code placement:{" "}
<select
defaultValue="head"
onChange={(event) => {
setInline(event.currentTarget.value === "inline");
}}
>
<option value="head">Anywhere in {`<head>`} element</option>
<option value="inline">Manual placement in {`<body>`}</option>
</select>
</label>

<div
className={css`
display: flex;
flex-flow: row wrap;
gap: 2rem;
align-items: flex-start;
justify-content: stretch;
`}
>
<textarea
className={css`
flex: 1;
min-width: 32rem;
resize: none;
padding: 1.5rem;
border: 1px solid rgb(0 0 0 / 60%);
border-radius: 1rem;
color: white;
background-color: rgb(0 0 0);
font-family: monospace;
`}
readOnly
onFocus={(event) => {
event.currentTarget.select();
}}
onChange={(event) => {
event.preventDefault();
}}
value={bannerSource}
ref={textAreaRef}
/>
<div
className={css`
flex: 1;
display: flex;
flex-flow: column;
`}
>
<iframe
className={css`
min-width: 32rem;
height: 20rem;
border: none;
background-color: white;
`}
ref={frameRef}
/>
<div>
<button
className={css`
appearance: none;
border: none;
background: none;
color: white;
text-decoration: underline;
cursor: pointer;
`}
onClick={load}
>
Reload
</button>
</div>
</div>
</div>
</div>
</>
);
}
38 changes: 38 additions & 0 deletions src/announcement-banner/banner-snippet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Banner } from "announcement-banner/banner";
import { BannerColorScheme } from "announcement-banner/banner-color-scheme";
import React from "react";

export function BannerSnippet({
colorScheme,
inline,
}: {
colorScheme: BannerColorScheme;
inline: boolean;
}) {
return inline ? (
<Banner colorScheme={colorScheme} />
) : (
<BannerSnippetHead colorScheme={colorScheme} />
);
}

function BannerSnippetHead({
colorScheme,
}: {
colorScheme: BannerColorScheme;
}) {
return (
<>
<template id="tally-banner-template">
<Banner colorScheme={colorScheme} />
</template>
<script
dangerouslySetInnerHTML={{
__html: loadScript,
}}
></script>
</>
);
}

const loadScript = `window.addEventListener('load',()=>{var d=document;d.body.prepend(d.importNode(d.getElementById('tally-banner-template').content,true))})`;
48 changes: 48 additions & 0 deletions src/announcement-banner/banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { BannerColorScheme } from "announcement-banner/banner-color-scheme";
import React from "react";

export function Banner({ colorScheme }: { colorScheme: BannerColorScheme }) {
return (
<div
style={{
padding: `1rem 2rem`,
backgroundColor: colorScheme.background,
color: colorScheme.foreground,
textAlign: `center`,
overflow: `hidden`,
fontSize: `0.875rem`,
fontFamily: `Helvetica,sans-serif`,
}}
>
<div
style={{
float: `right`,
padding: `1rem`,
margin: `-1rem 0`,
marginRight: `-2rem`,
background: `none`,
cursor: `pointer`,
}}
attr-onclick="this.parentElement.remove()"
>
&times;
</div>
<img
style={{ margin: `-0.5rem -0.5rem -2.5rem` }}
src={`${
process.env.NODE_ENV === "development"
? `http://localhost:8000`
: `https://tally.cash`
}/banner-icon.svg`}
/>
Tally is live.{" "}
<a
style={{ color: colorScheme.foreground }}
target="_blank"
href="https://tally.cash/community-edition"
>
Try it here!
</a>
</div>
);
}
16 changes: 16 additions & 0 deletions src/announcement-banner/example-page-content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";

export function BannerPreviewPage({ inline }: { inline: boolean }) {
return (
<html style={{ backgroundColor: `#CCCCCC` }}>
<head>{!inline && `%BANNER%`}</head>
<body style={{ margin: `0` }}>
{inline && `%BANNER%`}
<div style={{ padding: `1rem` }}>
<h1>Your page content</h1>
<p>{new Array(30).join(` lorem ipsum dolor sit amet`)}</p>
</div>
</body>
</html>
);
}
13 changes: 13 additions & 0 deletions src/pages/add-tally-banner-to-your-site.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { BannerSnippetSelfService } from "announcement-banner/banner-self-service";
import { Layout } from "layout/layout";
import React from "react";

const Page = () => {
return (
<Layout title="Snippet">
<BannerSnippetSelfService />
</Layout>
);
};

export default Page;
40 changes: 40 additions & 0 deletions static/banner-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ec9169d

Please sign in to comment.