First two pages of register flow

Co-authored-by: William Oldham <github@binaryoverload.co.uk>
This commit is contained in:
Jip Fr 2023-11-17 14:45:13 +01:00
parent 7f474af657
commit a25b3dee54
7 changed files with 195 additions and 51 deletions

View File

@ -50,6 +50,7 @@ export enum Icons {
IOS_FILES = "ios_files",
WAND = "wand",
COPY = "copy",
USER = "user",
}
export interface IconProps {
@ -107,6 +108,7 @@ const iconList: Record<Icons, string> = {
ios_files: `<svg width="1em" height="1em" viewBox="0 0 24 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.22405 20H21.024C22.9178 20 24 18.8772 24 16.7018V5.33333C24 3.1462 22.9065 2.03509 20.776 2.03509H10.5063C9.72851 2.03509 9.30014 1.85965 8.74777 1.36842L8.12776 0.818713C7.41757 0.187135 6.91029 0 5.85063 0H2.81822C1.01456 0 0 1.04094 0 3.1462V16.7018C0 18.8889 1.0822 20 3.22405 20ZM1.47675 3.22807C1.47675 2.08187 2.04039 1.50877 3.11132 1.50877H5.47863C6.23391 1.50877 6.65101 1.68421 7.21466 2.19883L7.84594 2.74854C8.52231 3.35673 9.06341 3.55556 10.1343 3.55556H20.7534C21.8807 3.55556 22.5233 4.18713 22.5233 5.4152V6.17544H1.47675V3.22807ZM3.24659 18.4795C2.09676 18.4795 1.47675 17.848 1.47675 16.6199V7.61403H22.5233V16.6316C22.5233 17.848 21.8807 18.4795 20.7534 18.4795H3.24659Z" fill="white"/></svg>`,
wand: `<svg width="1em" height="1em" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.33437 4.33438L8.15625 4.775C8.0625 4.80937 8 4.9 8 5C8 5.1 8.0625 5.19062 8.15625 5.225L9.33437 5.66563L9.775 6.84375C9.80938 6.9375 9.9 7 10 7C10.1 7 10.1906 6.9375 10.225 6.84375L10.6656 5.66563L11.8438 5.225C11.9375 5.19062 12 5.1 12 5C12 4.9 11.9375 4.80937 11.8438 4.775L10.6656 4.33438L10.225 3.15625C10.1906 3.0625 10.1 3 10 3C9.9 3 9.80938 3.0625 9.775 3.15625L9.33437 4.33438ZM3.44062 15.3562C2.85625 15.9406 2.85625 16.8906 3.44062 17.4781L4.52187 18.5594C5.10625 19.1437 6.05625 19.1437 6.64375 18.5594L18.5594 6.64062C19.1438 6.05625 19.1438 5.10625 18.5594 4.51875L17.4781 3.44063C16.8937 2.85625 15.9437 2.85625 15.3562 3.44063L3.44062 15.3562ZM17.1438 5.58125L13.8625 8.8625L13.1344 8.13438L16.4156 4.85312L17.1438 5.58125ZM2.23438 6.6625C2.09375 6.71562 2 6.85 2 7C2 7.15 2.09375 7.28438 2.23438 7.3375L4 8L4.6625 9.76562C4.71562 9.90625 4.85 10 5 10C5.15 10 5.28438 9.90625 5.3375 9.76562L6 8L7.76562 7.3375C7.90625 7.28438 8 7.15 8 7C8 6.85 7.90625 6.71562 7.76562 6.6625L6 6L5.3375 4.23438C5.28438 4.09375 5.15 4 5 4C4.85 4 4.71562 4.09375 4.6625 4.23438L4 6L2.23438 6.6625ZM13.2344 14.6625C13.0938 14.7156 13 14.85 13 15C13 15.15 13.0938 15.2844 13.2344 15.3375L15 16L15.6625 17.7656C15.7156 17.9062 15.85 18 16 18C16.15 18 16.2844 17.9062 16.3375 17.7656L17 16L18.7656 15.3375C18.9062 15.2844 19 15.15 19 15C19 14.85 18.9062 14.7156 18.7656 14.6625L17 14L16.3375 12.2344C16.2844 12.0938 16.15 12 16 12C15.85 12 15.7156 12.0938 15.6625 12.2344L15 14L13.2344 14.6625Z" fill="currentColor"/></svg>`,
copy: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-copy"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>`,
user: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>`,
};
function ChromeCastButton() {

View File

@ -0,0 +1,50 @@
import { useRef, useState } from "react";
import { useCopyToClipboard } from "react-use";
import { Icon, Icons } from "./Icon";
export function PassphaseDisplay(props: { mnemonic: string }) {
const individualWords = props.mnemonic.split(" ");
const [_, copy] = useCopyToClipboard();
const [hasCopied, setHasCopied] = useState(false);
const timeout = useRef<ReturnType<typeof setTimeout>>();
function copyMnemonic() {
copy(props.mnemonic);
setHasCopied(true);
if (timeout.current) clearTimeout(timeout.current);
timeout.current = setTimeout(() => setHasCopied(false), 500);
}
return (
<div className="rounded-lg border border-authentication-border/50 ">
<div className="px-4 py-2 flex justify-between border-b border-authentication-border/50">
<p className="font-bold text-sm text-white">Passphase</p>
<button
type="button"
className="text-authentication-copyText hover:text-authentication-copyTextHover transition-colors flex gap-2 items-center cursor-pointer"
onClick={() => copyMnemonic()}
>
<Icon
icon={hasCopied ? Icons.CHECKMARK : Icons.COPY}
className={hasCopied ? "text-xs" : ""}
/>
<span className="text-sm">Copy</span>
</button>
</div>
<div className="px-4 py-4 flex flex-wrap gap-x-2 gap-y-4">
{individualWords.map((word) => (
<div
className="px-4 rounded-md py-2 bg-authentication-wordBackground text-white font-medium"
key={word}
>
{word}
</div>
))}
</div>
</div>
);
}

View File

@ -0,0 +1,37 @@
export function LargeCard(props: { children: React.ReactNode }) {
return (
<div className="rounded-xl bg-largeCard-background bg-opacity-50 max-w-[600px] mx-auto p-[3rem]">
{props.children}
</div>
);
}
export function LargeCardText(props: {
title: string;
children?: React.ReactNode;
icon?: React.ReactNode;
}) {
return (
<div className="flex flex-col items-center text-center mb-8">
<div className="flex flex-col items-center text-center max-w-[318px]">
{props.icon ? (
<div className="text-2xl mb-4 text-largeCard-icon">{props.icon}</div>
) : null}
<h2 className="text-xl text-white font-bold">{props.title}</h2>
{props.children ? (
<div className="text-type-text mt-4">{props.children}</div>
) : null}
</div>
</div>
);
}
export function LargeCardButtons(props: { children: React.ReactNode }) {
return (
<div className="flex justify-center mt-8">
<div className="mx-auto inline-grid grid-cols-1 gap-3 justify-center items-center">
{props.children}
</div>
</div>
);
}

View File

@ -36,7 +36,7 @@ export function SubPageLayout(props: { children: React.ReactNode }) {
{/* Main page */}
<FooterView>
<Navigation doBackground noLightbar />
<div className="mt-40">{props.children}</div>
<div className="mt-40 relative">{props.children}</div>
</FooterView>
</div>
);

View File

@ -2,6 +2,13 @@ import { useMemo } from "react";
import { genMnemonic } from "@/backend/accounts/crypto";
import { Button } from "@/components/Button";
import { Icon, Icons } from "@/components/Icon";
import {
LargeCard,
LargeCardButtons,
LargeCardText,
} from "@/components/layout/LargeCard";
import { PassphaseDisplay } from "@/components/PassphraseDisplay";
interface PassphraseGeneratePartProps {
onNext?: (mnemonic: string) => void;
@ -11,10 +18,18 @@ export function PassphraseGeneratePart(props: PassphraseGeneratePartProps) {
const mnemonic = useMemo(() => genMnemonic(), []);
return (
<div>
<p>Remeber the following passphrase:</p>
<p className="border rounded-xl p-2">{mnemonic}</p>
<Button onClick={() => props.onNext?.(mnemonic)}>Next</Button>
</div>
<LargeCard>
<LargeCardText title="Your passphrase" icon={<Icon icon={Icons.USER} />}>
If you lose this, you&apos;re a silly goose and will be posted on the
wall of shame
</LargeCardText>
<PassphaseDisplay mnemonic={mnemonic} />
<LargeCardButtons>
<Button theme="purple" onClick={() => props.onNext?.(mnemonic)}>
NEXT!
</Button>
</LargeCardButtons>
</LargeCard>
);
}

View File

@ -2,6 +2,12 @@ import { useAsync } from "react-use";
import { MetaResponse, getBackendMeta } from "@/backend/accounts/meta";
import { Button } from "@/components/Button";
import { Icon, Icons } from "@/components/Icon";
import {
LargeCard,
LargeCardButtons,
LargeCardText,
} from "@/components/layout/LargeCard";
import { conf } from "@/setup/config";
interface TrustBackendPartProps {
@ -23,18 +29,37 @@ export function TrustBackendPart(props: TrustBackendPartProps) {
return <p>Failed to talk to backend, did you configure it correctly?</p>;
return (
<div>
<p>
do you trust{" "}
<span className="text-white font-bold">{result.value.domain}</span>
</p>
<div className="border rounded-xl p-4">
<p className="text-white font-bold">{result.value.data.name}</p>
<LargeCard>
<LargeCardText
title="Do you trust this host?"
icon={<Icon icon={Icons.CIRCLE_EXCLAMATION} />}
>
Do you trust <span className="text-white">{result.value.domain}</span>?
</LargeCardText>
<div className="border border-authentication-border rounded-xl px-4 py-8 flex flex-col items-center space-y-2 my-8">
<h3 className="text-white font-bold text-lg">
{result.value.data.name}
</h3>
{result.value.data.description ? (
<p>{result.value.data.description}</p>
) : null}
</div>
<Button onClick={() => props.onNext?.(result.value.data)}>Next</Button>
</div>
<LargeCardButtons>
<Button
theme="purple"
onClick={() => props.onNext?.(result.value.data)}
>
I pledge my life to the United States
</Button>
<Button
theme="secondary"
// eslint-disable-next-line no-return-assign, no-restricted-globals
onClick={() => (location.href = "https://youtu.be/of0O-lS-OqQ")}
>
I WILL NEVER SUCCUMB!
</Button>
</LargeCardButtons>
</LargeCard>
);
}

View File

@ -26,23 +26,23 @@ module.exports = {
"ash-400": "#3D394D",
"ash-300": "#2C293A",
"ash-200": "#2B2836",
"ash-100": "#1E1C26"
"ash-100": "#1E1C26",
},
/* fonts */
fontFamily: {
"open-sans": "'Open Sans'"
"open-sans": "'Open Sans'",
},
/* animations */
keyframes: {
"loading-pin": {
"0%, 40%, 100%": { height: "0.5em", "background-color": "#282336" },
"20%": { height: "1em", "background-color": "white" }
}
"20%": { height: "1em", "background-color": "white" },
},
},
animation: { "loading-pin": "loading-pin 1.8s ease-in-out infinite" }
}
animation: { "loading-pin": "loading-pin 1.8s ease-in-out infinite" },
},
},
plugins: [
require("tailwind-scrollbar"),
@ -52,18 +52,18 @@ module.exports = {
colors: {
// Branding
pill: {
background: "#1C1C36"
background: "#1C1C36",
},
// meta data for the theme itself
global: {
accentA: "#505DBD",
accentB: "#3440A1"
accentB: "#3440A1",
},
// light bar
lightBar: {
light: "#2A2A71"
light: "#2A2A71",
},
// Buttons
@ -71,14 +71,14 @@ module.exports = {
toggle: "#8D44D6",
toggleDisabled: "#202836",
danger: "#792131",
dangerHover: "#8a293b"
dangerHover: "#8a293b",
},
// only used for body colors/textures
background: {
main: "#0A0A10",
accentA: "#6E3B80",
accentB: "#1F1F50"
accentB: "#1F1F50",
},
// typography
@ -87,7 +87,7 @@ module.exports = {
text: "#73739D",
dimmed: "#926CAD",
divider: "#262632",
secondary: "#64647B"
secondary: "#64647B",
},
// search bar
@ -96,7 +96,7 @@ module.exports = {
focused: "#24243C",
placeholder: "#4A4A71",
icon: "#545476",
text: "#FFFFFF"
text: "#FFFFFF",
},
// media cards
@ -108,9 +108,24 @@ module.exports = {
barColor: "#4B4B63",
barFillColor: "#BA7FD6",
badge: "#151522",
badgeText: "#5F5F7A"
badgeText: "#5F5F7A",
},
// Large card
largeCard: {
background: "#171728",
icon: "#6741A5",
},
// Passphrase
authentication: {
border: "#393954",
wordBackground: "#171728",
copyText: "#58587A",
copyTextHover: "#8888AA",
},
// Settings page
settings: {
sidebar: {
activeLink: "#171728",
@ -120,19 +135,19 @@ module.exports = {
inactive: "#8D68A9",
icon: "#926CAD",
iconActivated: "#6942A8",
activated: "#CBA1E8"
}
activated: "#CBA1E8",
},
},
card: {
border: "#2A243E",
background: "#29243D",
altBackground: "#29243D"
}
altBackground: "#29243D",
},
},
utils: {
divider: "#353549"
divider: "#353549",
},
// Error page
@ -141,20 +156,20 @@ module.exports = {
border: "#252534",
type: {
secondary: "#62627D"
}
secondary: "#62627D",
},
},
// About page
about: {
circle: "#262632",
circleText: "#9A9AC3"
circleText: "#9A9AC3",
},
progress: {
background: "#8787A8",
preloaded: "#8787A8",
filled: "#A75FC9"
filled: "#A75FC9",
},
// video player
@ -166,11 +181,11 @@ module.exports = {
error: "#E44F4F",
success: "#40B44B",
loading: "#B759D8",
noresult: "#64647B"
noresult: "#64647B",
},
audio: {
set: "#A75FC9"
set: "#A75FC9",
},
buttons: {
@ -183,7 +198,7 @@ module.exports = {
purple: "#6b298a",
purpleHover: "#7f35a1",
cancel: "#252533",
cancelHover: "#3C3C4A"
cancelHover: "#3C3C4A",
},
context: {
@ -203,19 +218,19 @@ module.exports = {
buttons: {
list: "#161C26",
active: "#0D1317"
active: "#0D1317",
},
type: {
main: "#617A8A",
secondary: "#374A56",
accent: "#A570FA"
}
}
}
}
}
}
})
]
accent: "#A570FA",
},
},
},
},
},
},
}),
],
};