on master help sign in
ux: Master Key Download animations
6015de2tomholford
src/components/copiable/CopyButton.js+1−1
@@ -10,7 +10,7 @@ export default function CopyButton({
10 as: As = LinkButton,
10 as: As = LinkButton,
11 text,
11 text,
12 children = renderDefaultCopyText,
12 children = renderDefaultCopyText,
13− className,
13+ className = '',
14 ...rest
14 ...rest
15}) {
15}) {
16 const [doCopy, didCopy] = useCopiable(text);
16 const [doCopy, didCopy] = useCopiable(text);
src/lib/useCopiable.js → src/lib/useCopiable.tsrenamed+5−5
@@ -3,19 +3,19 @@ import copy from 'copy-to-clipboard';
3
3
4const COPY_DELAY = 2 * 1000; // ms
4const COPY_DELAY = 2 * 1000; // ms
5
5
6−export default function useCopiable(text) {
6+export default function useCopiable(text: string): [doCopy: VoidFunction, didCopy: boolean] {
7− const [didCopy, setDidCopy] = useState(false);
7+ const [didCopy, setDidCopy] = useState<boolean>(false);
8
8
9 // what we really want here is a useDebouncedCallback from use-debounced
9 // what we really want here is a useDebouncedCallback from use-debounced
10 // but that's a relatively large dep for a single simple usage so ¯\_(ツ)_/¯
10 // but that's a relatively large dep for a single simple usage so ¯\_(ツ)_/¯
11− const listener = useRef(); // <NodeJS.Listener>
11+ const listener = useRef<ReturnType<typeof window.setTimeout>>(); // <NodeJS.Listener>
12− useEffect(() => () => clearTimeout(listener.current), []);
12+ useEffect(() => () => clearTimeout(Number(listener.current)), []);
13
13
14 const doCopy = useCallback(() => {
14 const doCopy = useCallback(() => {
15 copy(text);
15 copy(text);
16 setDidCopy(true);
16 setDidCopy(true);
17
17
18− clearTimeout(listener.current);
18+ clearTimeout(Number(listener.current));
19 listener.current = setTimeout(() => setDidCopy(false), COPY_DELAY);
19 listener.current = setTimeout(() => setDidCopy(false), COPY_DELAY);
20 }, [text]);
20 }, [text]);
21
21
src/views/Activate/ActivateHeader.tsx+1−1
@@ -14,7 +14,7 @@ const ActivateHeader = ({ copy }: ActivateHeaderProps) => {
14 display="block"
14 display="block"
15 fontFamily="Inter"
15 fontFamily="Inter"
16 fontSize={3}
16 fontSize={3}
17− fontWeight="medium"
17+ fontWeight={600}
18 mx={3}
18 mx={3}
19 my={3}
19 my={3}
20 textAlign="center">
20 textAlign="center">
src/views/Activate/ActivateParagraph.tsx+2
@@ -18,6 +18,8 @@ const ActivateParagraph = ({ copy }: ActivateParagraphProps) => {
18 display="block"
18 display="block"
19 fontFamily="Inter"
19 fontFamily="Inter"
20 fontSize={2}
20 fontSize={2}
21+ lineHeight={'20px'}
22+ color={'rgba(0,0,0,0.6)'}
21 mx={3}
23 mx={3}
22 my={3}
24 my={3}
23 textAlign="center"
25 textAlign="center"
src/views/Activate/DangerBox.tsxnew file+25
@@ -0,0 +1,25 @@
1+import { Box, Text } from '@tlon/indigo-react';
2+import React from 'react';
3+import withFadeable from './withFadeable';
4+
5+interface DangerBoxProps {
6+ children: React.ReactNode | string;
7+}
8+
9+const DangerBox = ({ children }: DangerBoxProps) => {
10+ return (
11+ <Box
12+ background={'rgb(246,200,196)'}
13+ border={'solid 1px rgb(236,81,66)'}
14+ padding={'15px 45px'}
15+ borderRadius={'5px'}>
16+ <Text color={'black'} fontSize={'16px'} fontFamily="Inter">
17+ {children}
18+ </Text>
19+ </Box>
20+ );
21+};
22+
23+export default DangerBox;
24+
25+export const FadeableDangerBox = withFadeable(DangerBox);
src/views/Activate/MasterKeyCopy.tsxnew file+35
@@ -0,0 +1,35 @@
1+import { Box, Icon, Text } from '@tlon/indigo-react';
2+import useCopiable from '../../lib/useCopiable';
3+import withFadeable from './withFadeable';
4+
5+interface MasterKeyCopyProps {
6+ text: string;
7+}
8+
9+const MasterKeyCopy = ({ text }: MasterKeyCopyProps) => {
10+ const [doCopy, didCopy] = useCopiable(text);
11+ const { color, label, icon } = didCopy
12+ ? { color: 'rgb(70,156,106)', label: 'Copied', icon: 'Checkmark' }
13+ : { color: 'rgb(89,167,248)', label: 'Copy', icon: 'Copy' };
14+
15+ return (
16+ <Box onClick={() => doCopy()}>
17+ <Box
18+ display={'flex'}
19+ flexDirection={'row'}
20+ flexWrap={'nowrap'}
21+ alignItems={'center'}
22+ cursor={'pointer'}
23+ padding={'10px 15px'}>
24+ <Icon color={color} icon={icon} size="18px" mx="2px" />
25+ <Text color={color} fontSize={'18px'} mx="2px" fontFamily={'Inter'}>
26+ {label}
27+ </Text>
28+ </Box>
29+ </Box>
30+ );
31+};
32+
33+export default MasterKeyCopy;
34+
35+export const FadeableMasterKeyCopy = withFadeable(MasterKeyCopy);
src/views/Activate/MasterKeyDownload.tsx+13−17
@@ -1,13 +1,15 @@
1import React, { useCallback, useEffect, useMemo, useState } from 'react';
1import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
2
3−import ActivateView from './ActivateView';
4−import { FadeableActivateHeader as ActivateHeader } from './ActivateHeader';
5−import { Box } from '@tlon/indigo-react';
6−import ActivateParagraph from './ActivateParagraph';
7import { ActivateSteps } from './ActivateSteps';
3import { ActivateSteps } from './ActivateSteps';
8−import { FadeableMasterKeyPresenter as MasterKeyPresenter } from './MasterKeyPresenter';
4+import { Box } from '@tlon/indigo-react';
9import { FadeableActivateButton as ActivateButton } from './ActivateButton';
5import { FadeableActivateButton as ActivateButton } from './ActivateButton';
6+import { FadeableActivateHeader as ActivateHeader } from './ActivateHeader';
7+import { FadeableActivateParagraph as ActivateParagraph } from './ActivateParagraph';
8+import { FadeableDangerBox as DangerBox } from './DangerBox';
9+import { FadeableMasterKeyCopy as MasterKeyCopy } from './MasterKeyCopy';
10+import { FadeableMasterKeyPresenter as MasterKeyPresenter } from './MasterKeyPresenter';
10import { useActivateFlow } from './ActivateFlow';
11import { useActivateFlow } from './ActivateFlow';
12+import ActivateView from './ActivateView';
11
13
12const MasterKeyDownload = () => {
14const MasterKeyDownload = () => {
13 const { setIsIn } = useActivateFlow();
15 const { setIsIn } = useActivateFlow();
@@ -58,18 +60,12 @@ const MasterKeyDownload = () => {
58 flexDirection={'column'}
60 flexDirection={'column'}
59 flexWrap={'nowrap'}
61 flexWrap={'nowrap'}
60 height={'100%'}
62 height={'100%'}
61− justifyContent={'center'}>
63+ justifyContent={'space-evenly'}>
62− {/* AlertBox */}
64+ {triggerAnimation && (
63− <Box
65+ <DangerBox>Do not share this with anyone else!</DangerBox>
64− display={'flex'}
66+ )}
65− flexDirection={'row'}
66− flexWrap={'nowrap'}
67− width={'80%'}
68− height={'min-content'}
69− justifyContent={'center'}>
70− <MasterKeyPresenter fadeIn={true} />
67+ <MasterKeyPresenter fadeIn={true} />
71− </Box>
68+ {triggerAnimation && <MasterKeyCopy text={'test'} />}
72− {/* <CopyButton text={'test'} /> */}
73 </Box>
69 </Box>
74 </ActivateView>
70 </ActivateView>
75 <ActivateSteps currentStep={1} totalSteps={4} />
71 <ActivateSteps currentStep={1} totalSteps={4} />
src/views/Activate/MasterKeyPresenter.tsx+32−20
@@ -23,28 +23,40 @@ const MasterKeyPresenter = ({ className }: MasterKeyPresenterArgs) => {
23 flexWrap={'nowrap'}
23 flexWrap={'nowrap'}
24 width={'80%'}
24 width={'80%'}
25 height={'min-content'}
25 height={'min-content'}
26− justifyContent={'space-evenly'}
26+ justifyContent={'center'}>
27+ <Box
28+ display={'flex'}
29+ flexDirection={'row'}
30+ flexWrap={'nowrap'}
31+ width={'80%'}
32+ height={'min-content'}
33+ justifyContent={'space-evenly'}
27− className={className}>
34+ className={className}>
28− {ticketSegments &&
35+ {ticketSegments &&
29− ticketSegments.map((segment: string, i: number) => {
36+ ticketSegments.map((segment: string, i: number) => {
30− return (
37+ return (
31− <>
32 <Box
38 <Box
39+ key={i}
40+ display={'flex'}
41+ flexDirection={'row'}
42+ flexWrap={'nowrap'}>
43+ <Box
33− background={'rgba(0,0,0,0.05)'}
44+ background={'rgba(0,0,0,0.05)'}
34− padding={'12px 10px'}
45+ padding={'12px 10px'}
35− fontFamily={'Source Code Pro'}
46+ fontFamily={'Source Code Pro'}
36− borderRadius={'5px'}
47+ borderRadius={'5px'}
37− border={'solid 1px gray'}>
48+ border={'solid 1px gray'}>
38− {segment}
49+ {segment}
50+ </Box>
51+ {i < ticketSegments.length - 1 ? (
52+ <Text key={i} alignSelf="center" color="gray" mx={1}>
53+ —
54+ </Text>
55+ ) : null}
39 </Box>
56 </Box>
40− {i < ticketSegments.length - 1 ? (
57+ );
41− <Text key={i} alignSelf="center" color="gray" mx={1}>
42− —
43− </Text>
44− ) : null}
45− </>
46− );
47− })}
58+ })}
59+ </Box>
48 </Box>
60 </Box>
49 );
61 );
50};
62};