|
1 | 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; |
2 | 2 | import { useState } from 'react'; |
3 | 3 | import classNames from 'classnames'; |
4 | | -import { expect, userEvent, within } from 'storybook/test'; |
5 | 4 | import DsDrawer from './ds-drawer'; |
6 | 5 | import { DsButton } from '../ds-button'; |
7 | 6 | import { DsTextInput } from '../ds-text-input'; |
8 | 7 | import { DsIcon } from '../ds-icon'; |
9 | 8 | import { DsStatusBadge } from '../ds-status-badge'; |
10 | 9 | import styles from './ds-drawer.stories.module.scss'; |
11 | 10 | import { DsTypography } from '../ds-typography'; |
12 | | -import type { DsDrawerProps } from './ds-drawer.types'; |
| 11 | +import type { DsDrawerColumns, DsDrawerProps } from './ds-drawer.types'; |
| 12 | +import type { ResponsiveValue } from '../../utils/responsive'; |
13 | 13 |
|
14 | 14 | const meta: Meta<typeof DsDrawer> = { |
15 | 15 | title: 'Design System/Drawer', |
@@ -136,20 +136,6 @@ export const Default: Story = { |
136 | 136 | </> |
137 | 137 | ), |
138 | 138 | }, |
139 | | - play: async ({ canvasElement }) => { |
140 | | - const canvas = within(canvasElement); |
141 | | - |
142 | | - const openButton = canvas.getByRole('button', { name: /open drawer/i }); |
143 | | - await userEvent.click(openButton); |
144 | | - |
145 | | - const drawer = await canvas.findByRole('dialog'); |
146 | | - await expect(drawer).toHaveAttribute('data-state', 'open'); |
147 | | - |
148 | | - const closeButton = canvas.getByRole('button', { name: /close/i }); |
149 | | - await userEvent.click(closeButton); |
150 | | - |
151 | | - await expect(drawer).toHaveAttribute('data-state', 'closed'); |
152 | | - }, |
153 | 139 | }; |
154 | 140 |
|
155 | 141 | const Tabs = ({ total = 4 }: { total?: number }) => { |
@@ -253,19 +239,6 @@ export const WithBackdropAndScroll: Story = { |
253 | 239 | </> |
254 | 240 | ), |
255 | 241 | }, |
256 | | - play: async ({ canvasElement }) => { |
257 | | - const canvas = within(canvasElement); |
258 | | - |
259 | | - const openButton = canvas.getByRole('button', { name: /open drawer/i }); |
260 | | - await userEvent.click(openButton); |
261 | | - |
262 | | - const drawer = await canvas.findByRole('dialog'); |
263 | | - await expect(drawer).toHaveAttribute('data-state', 'open'); |
264 | | - |
265 | | - const backdrop = canvasElement.querySelector('[data-part="backdrop"]'); |
266 | | - await expect(backdrop).toBeInTheDocument(); |
267 | | - await expect(backdrop).toHaveAttribute('data-state', 'open'); |
268 | | - }, |
269 | 242 | }; |
270 | 243 |
|
271 | 244 | export const DockToStart: Story = { |
@@ -345,6 +318,71 @@ export const WithGridContent: Story = { |
345 | 318 | }, |
346 | 319 | }; |
347 | 320 |
|
| 321 | +/** |
| 322 | + * Right drawer responsiveness: the columns prop accepts a responsive value `{ lg, md }`. |
| 323 | + * On screens < 1440px the drawer automatically switches to the `md` column count. |
| 324 | + * |
| 325 | + * Recommended responsive mappings for end-positioned drawers: |
| 326 | + * - 3 cols → `{ lg: 3, md: 4 }` |
| 327 | + * - 4–5 cols → `{ lg: 4, md: 6 }` / `{ lg: 5, md: 6 }` |
| 328 | + * - 6+ cols → `{ lg: 6, md: 10 }` (up to 10) |
| 329 | + */ |
| 330 | +export const Responsive: Story = { |
| 331 | + render: function Render() { |
| 332 | + const [openDrawer, setOpenDrawer] = useState<string | null>(null); |
| 333 | + |
| 334 | + const close = () => setOpenDrawer(null); |
| 335 | + |
| 336 | + const variants = [ |
| 337 | + { label: '3 cols → 4 on md', columns: { lg: 3, md: 4 } }, |
| 338 | + { label: '4 cols → 6 on md', columns: { lg: 4, md: 6 } }, |
| 339 | + { label: '5 cols → 6 on md', columns: { lg: 5, md: 6 } }, |
| 340 | + { label: '6 cols → 10 on md', columns: { lg: 6, md: 10 } }, |
| 341 | + { label: '8 cols → 10 on md', columns: { lg: 8, md: 10 } }, |
| 342 | + ] satisfies Array<{ label: string; columns: ResponsiveValue<DsDrawerColumns> }>; |
| 343 | + |
| 344 | + return ( |
| 345 | + <div className={styles.storyWrapper}> |
| 346 | + <DsTypography variant="body-md-semi-bold"> |
| 347 | + Resize the window below 1440 px to see the responsive column change. |
| 348 | + </DsTypography> |
| 349 | + |
| 350 | + <div className={styles.responsiveButtons}> |
| 351 | + {variants.map(({ label }) => ( |
| 352 | + <DsButton key={label} onClick={() => setOpenDrawer(label)}> |
| 353 | + {label} |
| 354 | + </DsButton> |
| 355 | + ))} |
| 356 | + </div> |
| 357 | + |
| 358 | + {variants.map(({ label, columns }) => ( |
| 359 | + <DsDrawer |
| 360 | + key={label} |
| 361 | + open={openDrawer === label} |
| 362 | + onOpenChange={(open) => !open && close()} |
| 363 | + columns={columns} |
| 364 | + > |
| 365 | + <DsDrawer.Header> |
| 366 | + <DsDrawer.Title>{label}</DsDrawer.Title> |
| 367 | + <DsDrawer.CloseTrigger /> |
| 368 | + </DsDrawer.Header> |
| 369 | + <DsDrawer.Body className={styles.body}> |
| 370 | + <div className={styles.section}> |
| 371 | + <DsTypography className={styles.sectionHeader} variant="body-md-semi-bold"> |
| 372 | + lg: {columns.lg} columns · md: {columns.md} columns |
| 373 | + </DsTypography> |
| 374 | + <DsTypography variant="heading2" className={styles.sectionContent}> |
| 375 | + Drawer content |
| 376 | + </DsTypography> |
| 377 | + </div> |
| 378 | + </DsDrawer.Body> |
| 379 | + </DsDrawer> |
| 380 | + ))} |
| 381 | + </div> |
| 382 | + ); |
| 383 | + }, |
| 384 | +}; |
| 385 | + |
348 | 386 | export const ToggleFullSize: Story = { |
349 | 387 | args: { |
350 | 388 | columns: 4, |
|
0 commit comments