diff --git a/.specs/drawer.md b/.specs/drawer.md index 7392bd45b..f7cd084a5 100644 --- a/.specs/drawer.md +++ b/.specs/drawer.md @@ -4,9 +4,9 @@ category: overlay structure: composition status: implemented spec_version: 1 -checksum: f236ede5538b80ceac858f16528e77b92cd84a979dee3ab640435575e0f426ba +checksum: 380c8b7121907e3ac77be9b9ed690401b7bd0b22654667bee8ac6085948b5381 created: 2026-05-22 -last_updated: 2026-05-22 +last_updated: 2026-05-29 --- # Drawer — Component Spec @@ -84,6 +84,8 @@ _none_ ## Stories (Storybook) - Default +- Sizes +- ScrollContent — long `PanelContent` scrolls inside `ScrollArea`; header and footer stay in the panel flex layout (not sticky). ## Constraints — DO NOT diff --git a/.specs/panel.md b/.specs/panel.md index f812540e5..fd9ea814d 100644 --- a/.specs/panel.md +++ b/.specs/panel.md @@ -4,9 +4,9 @@ category: overlay structure: composition status: implemented spec_version: 1 -checksum: 45b27b09631c3ef06a0ac19b2a264aedbf06dc86dda5be9181d9eff32014280b +checksum: 015f8188bde283cbb6e84bdd8639c3b1bea1ea95339d06bc1c518b42c7325f5f created: 2026-05-22 -last_updated: 2026-05-22 +last_updated: 2026-05-29 --- # Panel — Component Spec diff --git a/apps/storybook/src/stories/webkit/overlay/Dialog.stories.js b/apps/storybook/src/stories/webkit/overlay/Dialog.stories.js index 78ec17faf..c9277a819 100644 --- a/apps/storybook/src/stories/webkit/overlay/Dialog.stories.js +++ b/apps/storybook/src/stories/webkit/overlay/Dialog.stories.js @@ -1,5 +1,3 @@ -import { ref } from 'vue' - import Button from '@aziontech/webkit/button' import Dialog from '@aziontech/webkit/overlay/dialog' import DialogClose from '@aziontech/webkit/overlay/dialog-close' @@ -12,10 +10,27 @@ import DialogTrigger from '@aziontech/webkit/overlay/dialog-trigger' import PanelContent from '@aziontech/webkit/overlay/panel-content' import PanelFooter from '@aziontech/webkit/overlay/panel-footer' import PanelHeader from '@aziontech/webkit/overlay/panel-header' +import { ref } from 'vue' const sizes = ['small', 'medium', 'large'] -export default { +const dialogStoryComponents = { + Dialog, + DialogTrigger, + DialogPortal, + DialogOverlay, + DialogContent, + DialogTitle, + DialogDescription, + DialogClose, + PanelHeader, + PanelContent, + PanelFooter, + Button +} + +/** @type {import('@storybook/vue3').Meta} */ +const meta = { title: 'Webkit/Overlay/Dialog', component: Dialog, subcomponents: { @@ -34,7 +49,6 @@ export default { parameters: { layout: 'fullscreen', backgrounds: { default: 'dark' }, - actions: { argTypesRegex: '^on[A-Z].*' }, a11y: { config: { rules: [{ id: 'color-contrast', enabled: true }] @@ -42,8 +56,55 @@ export default { }, docs: { description: { - component: - 'Modal dialog built on the shared Panel shell. Figma Webkit Panel (node 482:935). Supports overlay backdrop, closeable behavior, and theme motion tokens (panel scale 0.98 → 1 + opacity fade, overlay fade).' + component: [ + 'Modal dialog built on the shared Panel shell. Supports overlay backdrop, closeable behavior, and theme motion tokens (panel scale + opacity fade, overlay fade).', + '', + '## Usage', + '', + '```vue', + '', + '', + '', + '```' + ].join('\n') } } }, @@ -83,63 +144,43 @@ export default { } } -const alertDialogTemplate = ` +export default meta + +const dialogTemplate = ` - ` +/** @type {import('@storybook/vue3').StoryObj} */ export const Default = { - args: { - defaultOpen: false, - closeable: true, - size: 'small' - }, render: (args) => ({ - components: { - Dialog, - DialogTrigger, - DialogPortal, - DialogOverlay, - DialogContent, - DialogTitle, - DialogDescription, - DialogClose, - PanelContent, - Button - }, + components: dialogStoryComponents, setup() { const open = ref(args.defaultOpen) + return { args, open } }, - template: alertDialogTemplate + template: dialogTemplate }) } diff --git a/apps/storybook/src/stories/webkit/overlay/Drawer.stories.js b/apps/storybook/src/stories/webkit/overlay/Drawer.stories.js index abcb60c63..7bd94f838 100644 --- a/apps/storybook/src/stories/webkit/overlay/Drawer.stories.js +++ b/apps/storybook/src/stories/webkit/overlay/Drawer.stories.js @@ -1,5 +1,3 @@ -import { ref } from 'vue' - import Button from '@aziontech/webkit/button' import Drawer from '@aziontech/webkit/overlay/drawer' import DrawerClose from '@aziontech/webkit/overlay/drawer-close' @@ -12,10 +10,37 @@ import DrawerTrigger from '@aziontech/webkit/overlay/drawer-trigger' import PanelContent from '@aziontech/webkit/overlay/panel-content' import PanelFooter from '@aziontech/webkit/overlay/panel-footer' import PanelHeader from '@aziontech/webkit/overlay/panel-header' +import { reactive, ref, watch } from 'vue' const sizes = ['small', 'medium', 'large'] const sides = ['left', 'right'] +const sizeLabels = { + small: 'Small (384px)', + medium: 'Medium (672px)', + large: 'Large (1024px)' +} + +const scrollSections = Array.from({ length: 12 }, (_, index) => ({ + title: `Section ${index + 1}`, + body: `Scrollable drawer body copy for section ${index + 1}. Only PanelContent scrolls; header and footer stay in the panel layout.` +})) + +const drawerStoryComponents = { + Drawer, + DrawerTrigger, + DrawerPortal, + DrawerOverlay, + DrawerContent, + DrawerTitle, + DrawerDescription, + DrawerClose, + PanelHeader, + PanelContent, + PanelFooter, + Button +} + export default { title: 'Webkit/Overlay/Drawer', component: Drawer, @@ -35,7 +60,6 @@ export default { parameters: { layout: 'fullscreen', backgrounds: { default: 'dark' }, - actions: { argTypesRegex: '^on[A-Z].*' }, a11y: { config: { rules: [{ id: 'color-contrast', enabled: true }] @@ -43,8 +67,55 @@ export default { }, docs: { description: { - component: - 'Edge drawer using the shared Panel shell. Panel and backdrop use CSS transitions from theme animate presets (`moderate-*` durations, `productive-*` curves).' + component: [ + 'Edge drawer using the shared Panel shell. Long body content scrolls inside `PanelContent` via `ScrollArea`; header and footer stay in the panel flex layout.', + '', + '## Usage', + '', + '```vue', + '', + '', + '', + '```' + ].join('\n') } } }, @@ -120,20 +191,7 @@ const drawerTemplate = ` export const Default = { render: (args) => ({ - components: { - Drawer, - DrawerTrigger, - DrawerPortal, - DrawerOverlay, - DrawerContent, - DrawerTitle, - DrawerDescription, - DrawerClose, - PanelHeader, - PanelContent, - PanelFooter, - Button - }, + components: drawerStoryComponents, setup() { const open = ref(args.defaultOpen) return { args, open } @@ -141,3 +199,140 @@ export const Default = { template: drawerTemplate }) } + +export const Sizes = { + parameters: { + viewport: { + defaultViewport: 'desktop' + }, + docs: { + description: { + story: 'Small (384px), medium (672px), and large (1024px) max-width presets side by side.' + } + } + }, + render: () => ({ + components: drawerStoryComponents, + setup() { + const openBySize = reactive({ + small: false, + medium: false, + large: false + }) + + watch( + openBySize, + () => { + const openKey = sizes.find((key) => openBySize[key]) + + if (!openKey) return + + sizes.forEach((key) => { + if (key !== openKey) { + openBySize[key] = false + } + }) + }, + { deep: true } + ) + + return { sizes, sizeLabels, openBySize } + }, + template: ` +
+ + +
+ ` + }) +} + +export const ScrollContent = { + parameters: { + viewport: { + defaultViewport: 'desktop' + }, + docs: { + description: { + story: + 'Long content in `PanelContent` scrolls inside `ScrollArea`. Header and footer stay in the panel flex layout at the top and bottom; only the body scrolls.' + } + } + }, + render: () => ({ + components: drawerStoryComponents, + setup() { + const open = ref(false) + + return { open, scrollSections } + }, + template: ` + + +