1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-03 01:18:43 +02:00

feat: add demo guide welcome dialog (#3574)

https://linear.app/unleash/issue/2-923/add-initial-getting-started-dialog

Adds the welcome dialog with the static QR code pointing to our demo
website. Also changes how the run logic works a bit, so that we have
better control over it (only start demo steps once we click the start
button, etc).

Relates to [roadmap](https://github.com/orgs/Unleash/projects/10) item:
#3537


![image](https://user-images.githubusercontent.com/14320932/233395897-133edc18-371f-424f-a276-9ca0c9ec5b49.png)
This commit is contained in:
Nuno Góis 2023-04-20 16:32:26 +01:00 committed by GitHub
parent 23487f143d
commit 2cf6e689ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 165 additions and 19 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -5,10 +5,12 @@ import { DemoSteps } from './DemoSteps/DemoSteps';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { createLocalStorage } from 'utils/createLocalStorage';
import { TOPICS } from './demo-topics';
import { DemoDialogWelcome } from './DemoDialog/DemoDialogWelcome/DemoDialogWelcome';
const defaultProgress = {
welcomeOpen: true,
expanded: true,
run: false,
active: false,
topic: 0,
steps: [0],
};
@ -18,34 +20,47 @@ const { value: storedProgress, setValue: setStoredProgress } =
export const Demo = () => {
const { uiConfig } = useUiConfig();
const [loaded, setLoaded] = useState(false);
const [welcomeOpen, setWelcomeOpen] = useState(
storedProgress.welcomeOpen ?? true
);
const [active, setActive] = useState(false);
const [expanded, setExpanded] = useState(storedProgress.expanded ?? true);
const [run, setRun] = useState(false);
const [topic, setTopic] = useState(storedProgress.topic ?? 0);
const [steps, setSteps] = useState(storedProgress.steps ?? [0]);
useEffect(() => {
setTimeout(() => {
setLoaded(true);
if (storedProgress.run) {
setRun(true);
}
}, 1000);
if (storedProgress.active) {
setTimeout(() => {
setActive(true);
}, 1000);
}
}, []);
useEffect(() => {
setStoredProgress({
welcomeOpen,
expanded,
run,
active,
topic,
steps,
});
}, [expanded, run, topic, steps]);
}, [welcomeOpen, expanded, active, topic, steps]);
if (!uiConfig.flags.demo) return null;
return (
<>
<DemoDialogWelcome
open={welcomeOpen}
onClose={() => {
setWelcomeOpen(false);
setExpanded(false);
}}
onStart={() => {
setWelcomeOpen(false);
setActive(true);
}}
/>
<DemoTopics
expanded={expanded}
setExpanded={setExpanded}
@ -60,13 +75,12 @@ export const Demo = () => {
});
}}
topics={TOPICS}
onShowWelcome={() => setWelcomeOpen(true)}
/>
<ConditionallyRender
condition={loaded}
condition={active}
show={
<DemoSteps
run={run}
setRun={setRun}
setExpanded={setExpanded}
steps={steps}
setSteps={setSteps}

View File

@ -0,0 +1,40 @@
import { Dialog, IconButton, Typography, styled } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
const StyledDialog = styled(Dialog)(({ theme }) => ({
'& .MuiDialog-paper': {
borderRadius: theme.shape.borderRadiusExtraLarge,
maxWidth: theme.spacing(90),
padding: theme.spacing(7.5),
textAlign: 'center',
},
}));
const StyledCloseButton = styled(IconButton)(({ theme }) => ({
position: 'absolute',
right: theme.spacing(2),
top: theme.spacing(2),
color: theme.palette.neutral.main,
}));
const StyledHeader = styled(Typography)(({ theme }) => ({
fontSize: theme.fontSizes.largeHeader,
fontWeight: theme.fontWeight.bold,
}));
interface IDemoDialogProps {
open: boolean;
onClose: () => void;
children: React.ReactNode;
}
export const DemoDialog = ({ open, onClose, children }: IDemoDialogProps) => (
<StyledDialog open={open} onClose={onClose}>
<StyledCloseButton aria-label="close" onClick={onClose}>
<CloseIcon />
</StyledCloseButton>
{children}
</StyledDialog>
);
DemoDialog.Header = StyledHeader;

View File

@ -0,0 +1,93 @@
import { Button, Divider, Typography, styled } from '@mui/material';
import qrImage from 'assets/img/demo_qr.png';
import { formatAssetPath } from 'utils/formatPath';
import { Launch } from '@mui/icons-material';
import { DemoDialog } from '../DemoDialog';
const StyledDemoPane = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
backgroundColor: theme.palette.neutral.light,
borderRadius: theme.shape.borderRadiusLarge,
padding: theme.spacing(4),
margin: theme.spacing(4, 0),
}));
const StyledScanMessage = styled(Typography)(({ theme }) => ({
fontSize: theme.fontSizes.mainHeader,
fontWeight: theme.fontWeight.bold,
marginBottom: theme.spacing(2),
}));
const StyledQRCode = styled('img')(({ theme }) => ({
width: theme.spacing(20),
height: theme.spacing(20),
}));
const StyledDivider = styled(Divider)(({ theme }) => ({
margin: theme.spacing(4, 0),
padding: theme.spacing(0, 4),
width: '100%',
color: theme.palette.text.secondary,
}));
const StyledLink = styled('a')(({ theme }) => ({
display: 'inline-flex',
alignItems: 'center',
gap: theme.spacing(0.5),
'& > svg': {
fontSize: theme.fontSizes.bodySize,
},
}));
const StyledStartButton = styled(Button)(({ theme }) => ({
height: theme.spacing(7),
}));
interface IDemoDialogWelcomeProps {
open: boolean;
onClose: () => void;
onStart: () => void;
}
export const DemoDialogWelcome = ({
open,
onClose,
onStart,
}: IDemoDialogWelcomeProps) => (
<DemoDialog open={open} onClose={onClose}>
<DemoDialog.Header>Explore Unleash</DemoDialog.Header>
<Typography color="textSecondary" sx={{ mt: 2 }}>
You can explore Unleash on your own, however for the best experience
it's recommended you follow our interactive tutorial. To get
started, you will need to open the demo website below.
</Typography>
<StyledDemoPane>
<StyledScanMessage>
Scan the QR code with your phone
</StyledScanMessage>
<StyledQRCode src={formatAssetPath(qrImage)} alt="Demo QR Code" />
<StyledDivider>OR</StyledDivider>
<Typography>
Open demo website in another tab:{' '}
<StyledLink
href="https://demo.unleash-hosted.com/"
target="_blank"
>
demo.unleash-hosted.com <Launch />
</StyledLink>
</Typography>
<Typography color="textSecondary">
(we recommend you keep the pages open side by side)
</Typography>
</StyledDemoPane>
<StyledStartButton
variant="contained"
color="primary"
onClick={onStart}
>
Start Unleash tutorial
</StyledStartButton>
</DemoDialog>
);

View File

@ -44,8 +44,6 @@ const StyledTooltipPrimaryActions = styled('div')(({ theme }) => ({
}));
interface IDemoStepsProps {
run: boolean;
setRun: React.Dispatch<React.SetStateAction<boolean>>;
setExpanded: React.Dispatch<React.SetStateAction<boolean>>;
steps: number[];
setSteps: React.Dispatch<React.SetStateAction<number[]>>;
@ -55,8 +53,6 @@ interface IDemoStepsProps {
}
export const DemoSteps = ({
run,
setRun,
setExpanded,
steps,
setSteps,
@ -67,6 +63,7 @@ export const DemoSteps = ({
const theme = useTheme();
const navigate = useNavigate();
const location = useLocation();
const [run, setRun] = useState(false);
const [flow, setFlow] = useState<'next' | 'back'>('next');
const abortController = new AbortController();

View File

@ -138,6 +138,7 @@ interface IDemoTopicsProps {
currentTopic: number;
setCurrentTopic: (topic: number) => void;
topics: ITutorialTopic[];
onShowWelcome: () => void;
}
export const DemoTopics = ({
@ -147,6 +148,7 @@ export const DemoTopics = ({
currentTopic,
setCurrentTopic,
topics,
onShowWelcome,
}: IDemoTopicsProps) => {
const completedSteps = steps.reduce((acc, step) => acc + (step || 0), 0);
const totalSteps = topics.flatMap(({ steps }) => steps).length;
@ -201,7 +203,7 @@ export const DemoTopics = ({
</StyledStep>
);
})}
<StyledButton variant="outlined">
<StyledButton variant="outlined" onClick={onShowWelcome}>
View demo link again
</StyledButton>
</AccordionDetails>