Skip to content

Commit 61ab980

Browse files
authored
Improve modal and toast stories (#2398)
1 parent 4eed722 commit 61ab980

File tree

14 files changed

+237
-39
lines changed

14 files changed

+237
-39
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.base {
2+
width: 100vw;
3+
height: 100vh;
4+
}
5+
6+
:global(.docs-story) .base {
7+
width: auto;
8+
height: auto;
9+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Copyright 2019, SumUp Ltd.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
import type { ReactNode } from 'react';
17+
18+
import classes from './FullViewport.module.css';
19+
20+
interface FullViewportProps {
21+
children: ReactNode;
22+
}
23+
24+
export default function FullViewport({ children }: FullViewportProps) {
25+
return <div className={classes.base}>{children}</div>;
26+
}

.storybook/components/index.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,17 @@ export { Props };
2121

2222
export { Meta, IconGallery, IconItem, Typeset } from '@storybook/addon-docs';
2323

24-
export { default as DocsContainer } from './DocsContainer';
25-
export { default as Status } from './Statuses';
26-
export { default as Preview } from './Preview';
27-
export { default as Story } from './Story';
28-
export { default as Icons } from './Icons';
29-
export { default as Intro } from './Intro';
30-
export { default as Teaser } from './Teaser';
31-
export { default as Link } from './Link';
32-
export { default as Image } from './Image';
33-
export { default as Stack } from './Stack';
24+
export { default as DocsContainer } from './DocsContainer.js';
25+
export { default as Status } from './Statuses.js';
26+
export { default as Preview } from './Preview.js';
27+
export { default as Story } from './Story.js';
28+
export { default as Icons } from './Icons.js';
29+
export { default as Intro } from './Intro.js';
30+
export { default as Teaser } from './Teaser.js';
31+
export { default as Link } from './Link.js';
32+
export { default as Image } from './Image.js';
33+
export { default as Stack } from './Stack.js';
34+
export { default as FullViewport } from './FullViewport.js';
3435

3536
export {
3637
CustomPropertiesTable,
@@ -43,4 +44,4 @@ export {
4344
FontWeight,
4445
Transition,
4546
MediaQueriesTable,
46-
} from './Theme';
47+
} from './Theme.js';

.storybook/modes.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const viewports = {
2+
smallMobile: {
3+
viewport: 'smallMobile',
4+
},
5+
largeMobile: {
6+
viewport: 'largeMobile',
7+
},
8+
tablet: {
9+
viewport: 'tablet',
10+
},
11+
desktop: {
12+
viewport: 'desktop',
13+
},
14+
};
15+
16+
export const modes = {
17+
...viewports,
18+
};

.storybook/preview.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,26 @@ export const parameters = {
1616
{ name: 'v5', url: 'https://circuit-v5.sumup-vercel.app' },
1717
],
1818
},
19+
viewport: {
20+
viewports: {
21+
smallMobile: {
22+
name: 'Small mobile',
23+
styles: { width: '320px', height: '568px' },
24+
},
25+
largeMobile: {
26+
name: 'Large mobile',
27+
styles: { width: '414px', height: '896px' },
28+
},
29+
tablet: {
30+
name: 'Tablet',
31+
styles: { width: '834px', height: '1112px' },
32+
},
33+
desktop: {
34+
name: 'Desktop',
35+
styles: { width: '1280px', height: '1000px' },
36+
},
37+
},
38+
},
1939
previewTabs: { 'storybook/docs/panel': { index: -1 } },
2040
actions: { argTypesRegex: '^on.*' },
2141
controls: { expanded: true },

package-lock.json

Lines changed: 30 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"@vitest/coverage-c8": "^0.30.1",
6262
"@vitest/coverage-v8": "^0.34.6",
6363
"audit-ci": "^6.6.1",
64+
"chromatic": "^10.3.1",
6465
"eslint-import-resolver-typescript": "^3.6.1",
6566
"eslint-plugin-prettier": "^4.2.1",
6667
"eslint-plugin-storybook": "^0.6.15",

packages/circuit-ui/components/ButtonGroup/ButtonGroup.stories.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import { action } from '@storybook/addon-actions';
1717

1818
import { Stack } from '../../../../.storybook/components/index.js';
19+
import { modes } from '../../../../.storybook/modes.js';
1920

2021
import { ButtonGroup, ButtonGroupProps } from './ButtonGroup.js';
2122

@@ -25,7 +26,12 @@ export default {
2526
parameters: {
2627
// we don't want to center this story to be able to see the effects of the `align` prop
2728
layout: 'padded',
28-
chromatic: { viewports: [320, 1280] },
29+
chromatic: {
30+
modes: {
31+
mobile: modes.smallMobile,
32+
desktop: modes.desktop,
33+
},
34+
},
2935
},
3036
};
3137

packages/circuit-ui/components/Modal/Modal.stories.tsx

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@
1313
* limitations under the License.
1414
*/
1515

16+
import type { Decorator } from '@storybook/react';
1617
import { Fragment } from 'react';
18+
import { screen, userEvent, within } from '@storybook/testing-library';
1719

18-
import { Stack } from '../../../../.storybook/components/index.js';
20+
import {
21+
FullViewport,
22+
Stack,
23+
} from '../../../../.storybook/components/index.js';
24+
import { modes } from '../../../../.storybook/modes.js';
1925
import Button from '../Button/index.js';
2026
import Headline from '../Headline/index.js';
2127
import Body from '../Body/index.js';
@@ -28,6 +34,21 @@ export default {
2834
title: 'Components/Modal',
2935
component: Modal,
3036
subcomponents: { ModalProvider },
37+
parameters: {
38+
chromatic: {
39+
modes: {
40+
mobile: modes.smallMobile,
41+
desktop: modes.desktop,
42+
},
43+
},
44+
},
45+
decorators: [
46+
(Story) => (
47+
<FullViewport>
48+
<Story />
49+
</FullViewport>
50+
),
51+
] as Decorator[],
3152
};
3253

3354
const defaultModalChildren = () => (
@@ -39,6 +60,20 @@ const defaultModalChildren = () => (
3960
</Fragment>
4061
);
4162

63+
const openModal = async ({
64+
canvasElement,
65+
}: {
66+
canvasElement: HTMLCanvasElement;
67+
}) => {
68+
const canvas = within(canvasElement);
69+
const button = canvas.getByRole('button', {
70+
name: 'Open modal',
71+
});
72+
73+
await userEvent.click(button);
74+
await screen.findByRole('dialog');
75+
};
76+
4277
export const Base = (modal: ModalProps): JSX.Element => {
4378
const ComponentWithModal = () => {
4479
const { setModal } = useModal();
@@ -61,6 +96,7 @@ Base.args = {
6196
variant: 'contextual',
6297
closeButtonLabel: 'Close modal',
6398
};
99+
Base.play = openModal;
64100

65101
export const Variants = (modal: ModalProps): JSX.Element => {
66102
const ComponentWithModal = ({ variant }: Pick<ModalProps, 'variant'>) => {
@@ -86,6 +122,9 @@ Variants.args = {
86122
children: defaultModalChildren,
87123
closeButtonLabel: 'Close modal',
88124
};
125+
Variants.parameters = {
126+
chromatic: { disableSnapshot: true },
127+
};
89128

90129
export const PreventClose = (modal: ModalProps): JSX.Element => {
91130
const ComponentWithModal = () => {
@@ -123,6 +162,7 @@ PreventClose.args = {
123162
variant: 'immersive',
124163
preventClose: true,
125164
};
165+
PreventClose.play = openModal;
126166

127167
export const InitiallyOpen = (modal: ModalProps): JSX.Element => {
128168
const initialModal = { id: 'initial', component: Modal, ...modal };
@@ -171,11 +211,13 @@ CustomStyles.args = {
171211
Custom styles
172212
</Headline>
173213
<Body style={{ margin: '1rem' }}>
174-
Custom styles can be applied using the <code>css</code> prop.
214+
Custom styles can be applied using the <code>className</code> or{' '}
215+
<code>style</code> props.
175216
</Body>
176217
</Fragment>
177218
),
178219
style: { padding: '0' },
179220
variant: 'contextual',
180221
closeButtonLabel: 'Close modal',
181222
};
223+
CustomStyles.play = openModal;

packages/circuit-ui/components/NotificationModal/NotificationModal.stories.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
* limitations under the License.
1414
*/
1515

16+
import type { Decorator } from '@storybook/react';
1617
import { action } from '@storybook/addon-actions';
18+
import { screen, userEvent, within } from '@storybook/testing-library';
1719

20+
import { FullViewport } from '../../../../.storybook/components/index.js';
1821
import { ModalProvider } from '../ModalContext/index.js';
1922
import Button from '../Button/index.js';
2023

@@ -27,6 +30,16 @@ import { useNotificationModal } from './useNotificationModal.js';
2730
export default {
2831
title: 'Notification/NotificationModal',
2932
component: NotificationModal,
33+
parameters: {
34+
layout: 'padded',
35+
},
36+
decorators: [
37+
(Story) => (
38+
<FullViewport>
39+
<Story />
40+
</FullViewport>
41+
),
42+
] as Decorator[],
3043
};
3144

3245
export const Base = (modal: NotificationModalProps): JSX.Element => {
@@ -61,3 +74,12 @@ Base.args = {
6174
},
6275
closeButtonLabel: 'Close',
6376
};
77+
Base.play = async ({ canvasElement }: { canvasElement: HTMLCanvasElement }) => {
78+
const canvas = within(canvasElement);
79+
const button = canvas.getByRole('button', {
80+
name: 'Open modal',
81+
});
82+
83+
await userEvent.click(button);
84+
await screen.findByRole('dialog');
85+
};

0 commit comments

Comments
 (0)