Skip to content

Commit 019959d

Browse files
committed
SD-92: Add modal story
1 parent 1cc8111 commit 019959d

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { faker } from '@faker-js/faker';
2+
import type { Meta, StoryObj } from '@storybook/react';
3+
import { ComponentProps, useEffect, useState } from 'react';
4+
import styled from 'styled-components';
5+
6+
import Button from 'src/domains/misc/components/Button';
7+
import Modal, { ModalProvider, useModal, useModalControls } from 'src/domains/misc/components/ModalNew';
8+
import { typography } from 'src/domains/styling/utils/tokens.ts';
9+
10+
faker.seed(0);
11+
12+
const MAX_PAGES = 10;
13+
14+
const LOREM_SENTENCES = Array.from({ length: MAX_PAGES }, () => faker.lorem.lines(4));
15+
const LOREM_TITLES = Array.from({ length: MAX_PAGES }, () => faker.lorem.words({ min: 2, max: 5 }));
16+
17+
const meta = {
18+
decorators: [
19+
Story => (
20+
<ModalProvider>
21+
<Story />
22+
</ModalProvider>
23+
),
24+
],
25+
} satisfies Meta<typeof Modal>;
26+
27+
export default meta;
28+
29+
type Story = StoryObj<ComponentProps<typeof Modal> & {
30+
pageCount: number,
31+
}>;
32+
33+
export const Basic: Story = {
34+
parameters: {
35+
chromatic: { disableSnapshot: true },
36+
},
37+
render: () => <Preview pageCount={2} />,
38+
};
39+
40+
export const Controllable: Story = {
41+
argTypes: {
42+
pageCount: {
43+
control: { type: 'range', min: 1, max: MAX_PAGES, step: 1 },
44+
description: 'Number of modal pages to show',
45+
},
46+
},
47+
parameters: {
48+
chromatic: { disableSnapshot: true },
49+
},
50+
args: {
51+
pageCount: 1,
52+
nonDismissible: false,
53+
},
54+
render: args => <Preview key={JSON.stringify(args)} {...args} />,
55+
};
56+
57+
type ModalProps = { pageCount: number } & Partial<ComponentProps<typeof Modal>>;
58+
59+
const Preview = (props: ModalProps) => {
60+
const { open, close } = useModal(<Component {...props} />);
61+
62+
useEffect(() => {
63+
return () => void close();
64+
}, [close]);
65+
66+
return (
67+
<Button onClick={open} variant="primary">
68+
Open modal
69+
</Button>
70+
);
71+
};
72+
73+
const Component = ({ pageCount, ...props }: ModalProps) => {
74+
const [page, setPage] = useState(0);
75+
76+
const config = Array.from({ length: pageCount }, (_, i) => ({
77+
title: LOREM_TITLES[i],
78+
content: (
79+
<Content
80+
page={i}
81+
pageCount={pageCount}
82+
onContinue={() => void setPage(curr => curr + 1)}
83+
/>
84+
),
85+
}));
86+
87+
return <Modal page={page} config={config} {...props} />;
88+
};
89+
90+
const Content = ({
91+
onContinue,
92+
page,
93+
pageCount,
94+
}: {
95+
onContinue?: () => void,
96+
page: number,
97+
pageCount: number,
98+
}) => {
99+
const { close } = useModalControls();
100+
const isLastPage = page === pageCount - 1;
101+
return (
102+
<Wrapper>
103+
<p>{LOREM_SENTENCES[page]}</p>
104+
<ButtonWrapper>
105+
<Button variant="primary" onClick={isLastPage ? close : onContinue}>
106+
{isLastPage ? 'Close' : 'Continue'}
107+
</Button>
108+
<p>{page + 1}/{pageCount}</p>
109+
</ButtonWrapper>
110+
</Wrapper>
111+
);
112+
};
113+
114+
const Wrapper = styled.div`
115+
display: flex;
116+
flex-direction: column;
117+
gap: 20px;
118+
${typography.web.body1};
119+
`;
120+
121+
const ButtonWrapper = styled.div`
122+
display: flex;
123+
align-items: center;
124+
justify-content: space-between;
125+
gap: 8px
126+
`;

0 commit comments

Comments
 (0)