diff --git a/apps/app/src/stories/v2/AppDialog.stories.ts b/apps/app/src/stories/v2/AppDialog.stories.ts index 009a6830..ad464564 100644 --- a/apps/app/src/stories/v2/AppDialog.stories.ts +++ b/apps/app/src/stories/v2/AppDialog.stories.ts @@ -23,10 +23,18 @@ const meta: Meta = { export default meta type Story = StoryObj -export const Default: Story = { - args: { open: true, title: 'Edit shift' }, - render: args => ({ - components: { AppDialog }, +/** + * Shared render: only the inner markup (default body + optional + * #footer / #tabs slots) varies between stories, so the v-model:open + * scaffold lives here once. `extra` registers any extra components the + * inner markup references (e.g. Button for the footer story). + */ +function dialogStory( + inner: string, + extra: Record = {}, +): Story['render'] { + return args => ({ + components: { AppDialog, ...extra }, setup() { const open = ref(args.open) @@ -34,86 +42,48 @@ export const Default: Story = { }, template: ` -

Dialog body content goes here.

+ ${inner}
`, - }), + }) +} + +export const Default: Story = { + args: { open: true, title: 'Edit shift' }, + render: dialogStory('

Dialog body content goes here.

'), } export const WithSubtitle: Story = { args: { open: true, title: 'Edit shift', sub: 'Saturday — Main Stage' }, - render: args => ({ - components: { AppDialog }, - setup() { - const open = ref(args.open) - - return { args, open } - }, - template: ` - -

Dialog body with a subtitle in the header.

-
- `, - }), + render: dialogStory('

Dialog body with a subtitle in the header.

'), } export const WithFooter: Story = { args: { open: true, title: 'Confirm action' }, - render: args => ({ - components: { AppDialog, Button }, - setup() { - const open = ref(args.open) - - return { args, open } - }, - template: ` - -

Are you sure you want to continue?

- -
- `, - }), + render: dialogStory( + `

Are you sure you want to continue?

+ `, + { Button }, + ), } export const WithTabs: Story = { args: { open: true, title: 'Settings' }, - render: args => ({ - components: { AppDialog }, - setup() { - const open = ref(args.open) - - return { args, open } - }, - template: ` - - -

Tab strip rendered between header and body.

-
- `, - }), + render: dialogStory( + ` +

Tab strip rendered between header and body.

`, + ), } export const Wide: Story = { args: { open: true, title: 'Wide dialog', width: '960px' }, - render: args => ({ - components: { AppDialog }, - setup() { - const open = ref(args.open) - - return { args, open } - }, - template: ` - -

This dialog uses an explicit width of 960px.

-
- `, - }), + render: dialogStory('

This dialog uses an explicit width of 960px.

'), } diff --git a/apps/app/src/stories/v2/AppTopbar.stories.ts b/apps/app/src/stories/v2/AppTopbar.stories.ts index c38e7e70..0f1b5b89 100644 --- a/apps/app/src/stories/v2/AppTopbar.stories.ts +++ b/apps/app/src/stories/v2/AppTopbar.stories.ts @@ -1,5 +1,4 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite' -import { onUnmounted } from 'vue' import { orgA, userFixture, withPinia } from './_helpers' import AppTopbar from '@/components-v2/layout/AppTopbar.vue' import { useAuthStore } from '@/stores/useAuthStore' @@ -10,24 +9,17 @@ import { useShellUiStore } from '@/stores/useShellUiStore' * currentOrganisation) and useBreadcrumb (route-driven — router is global * in preview.ts). Each story seeds both stores on a fresh Pinia. */ +function seedAuth(): void { + const auth = useAuthStore() + + auth.user = userFixture + auth.organisations = [orgA] +} + const meta: Meta = { title: 'v2 Shell/AppTopbar', component: AppTopbar, tags: ['autodocs'], -} - -export default meta -type Story = StoryObj - -export const Default: Story = { - decorators: [ - withPinia(() => { - const auth = useAuthStore() - - auth.user = userFixture - auth.organisations = [orgA] - }), - ], render: () => ({ components: { AppTopbar }, template: ` @@ -38,29 +30,30 @@ export const Default: Story = { }), } +export default meta +type Story = StoryObj + +export const Default: Story = { + decorators: [withPinia(seedAuth)], +} + +/** + * Dark mode is scoped to the story's own subtree via a `.dark` wrapper + * (Aura darkModeSelector is the `.dark` class — see plugins/primevue). + * Mutating instead would leak into every other story stacked on + * the same autodocs page. + */ export const DarkTheme: Story = { decorators: [ withPinia(() => { - const auth = useAuthStore() - - auth.user = userFixture - auth.organisations = [orgA] - - const shellUi = useShellUiStore() - - shellUi.setTheme('dark') + seedAuth() + useShellUiStore().setTheme('dark') }), ], render: () => ({ components: { AppTopbar }, - setup() { - document.documentElement.classList.add('dark') - onUnmounted(() => { - document.documentElement.classList.remove('dark') - }) - }, template: ` -
+
`, @@ -70,22 +63,8 @@ export const DarkTheme: Story = { export const CompactDensity: Story = { decorators: [ withPinia(() => { - const auth = useAuthStore() - - auth.user = userFixture - auth.organisations = [orgA] - - const shellUi = useShellUiStore() - - shellUi.setDensity('compact') + seedAuth() + useShellUiStore().setDensity('compact') }), ], - render: () => ({ - components: { AppTopbar }, - template: ` -
- -
- `, - }), } diff --git a/apps/app/src/stories/v2/WorkspaceSwitcher.stories.ts b/apps/app/src/stories/v2/WorkspaceSwitcher.stories.ts index ab96f29d..a351da4a 100644 --- a/apps/app/src/stories/v2/WorkspaceSwitcher.stories.ts +++ b/apps/app/src/stories/v2/WorkspaceSwitcher.stories.ts @@ -15,6 +15,19 @@ const meta: Meta = { argTypes: { collapsed: { control: 'boolean' }, }, + render: args => ({ + components: { WorkspaceSwitcher }, + setup() { + return { args } + }, + + // Rail width tracks collapsed so both states read correctly. + template: ` +
+ +
+ `, + }), } export default meta @@ -29,17 +42,6 @@ export const SingleOrg: Story = { auth.organisations = [orgA] }), ], - render: args => ({ - components: { WorkspaceSwitcher }, - setup() { - return { args } - }, - template: ` -
- -
- `, - }), } export const MultiOrg: Story = { @@ -51,17 +53,6 @@ export const MultiOrg: Story = { auth.organisations = [orgA, orgB, orgC] }), ], - render: args => ({ - components: { WorkspaceSwitcher }, - setup() { - return { args } - }, - template: ` -
- -
- `, - }), } export const Collapsed: Story = { @@ -74,15 +65,4 @@ export const Collapsed: Story = { auth.organisations = [orgA, orgB, orgC] }), ], - render: args => ({ - components: { WorkspaceSwitcher }, - setup() { - return { args } - }, - template: ` -
- -
- `, - }), }