90 lines
2.8 KiB
TypeScript
90 lines
2.8 KiB
TypeScript
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
import { ref } from 'vue'
|
|
import Button from 'primevue/button'
|
|
import AppDialog from '@/components-v2/shared/AppDialog.vue'
|
|
|
|
/**
|
|
* AppDialog stories. PrimeVue Dialog is `modal` + teleports to <body>,
|
|
* so each story binds `v-model:open` to a ref seeded from `args.open`
|
|
* and renders the dialog open by default for autodocs visibility.
|
|
*/
|
|
const meta: Meta<typeof AppDialog> = {
|
|
title: 'v2 Shell/AppDialog',
|
|
component: AppDialog,
|
|
tags: ['autodocs'],
|
|
argTypes: {
|
|
open: { control: 'boolean' },
|
|
title: { control: 'text' },
|
|
sub: { control: 'text' },
|
|
width: { control: 'text' },
|
|
},
|
|
}
|
|
|
|
export default meta
|
|
type Story = StoryObj<typeof 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<string, unknown> = {},
|
|
): Story['render'] {
|
|
return args => ({
|
|
components: { AppDialog, ...extra },
|
|
setup() {
|
|
const open = ref(args.open)
|
|
|
|
return { args, open }
|
|
},
|
|
template: `
|
|
<AppDialog v-model:open="open" :title="args.title" :sub="args.sub" :width="args.width">
|
|
${inner}
|
|
</AppDialog>
|
|
`,
|
|
})
|
|
}
|
|
|
|
export const Default: Story = {
|
|
args: { open: true, title: 'Edit shift' },
|
|
render: dialogStory('<p class="text-sm">Dialog body content goes here.</p>'),
|
|
}
|
|
|
|
export const WithSubtitle: Story = {
|
|
args: { open: true, title: 'Edit shift', sub: 'Saturday — Main Stage' },
|
|
render: dialogStory('<p class="text-sm">Dialog body with a subtitle in the header.</p>'),
|
|
}
|
|
|
|
export const WithFooter: Story = {
|
|
args: { open: true, title: 'Confirm action' },
|
|
render: dialogStory(
|
|
`<p class="text-sm">Are you sure you want to continue?</p>
|
|
<template #footer>
|
|
<Button label="Cancel" severity="secondary" @click="open = false" />
|
|
<Button label="Confirm" @click="open = false" />
|
|
</template>`,
|
|
{ Button },
|
|
),
|
|
}
|
|
|
|
export const WithTabs: Story = {
|
|
args: { open: true, title: 'Settings' },
|
|
render: dialogStory(
|
|
`<template #tabs>
|
|
<div class="flex gap-4 px-6 py-2 border-b border-[var(--p-content-border-color)] text-[13px]">
|
|
<span class="font-semibold text-[var(--p-primary-color)]">General</span>
|
|
<span class="text-[var(--p-text-muted-color)]">Advanced</span>
|
|
</div>
|
|
</template>
|
|
<p class="text-sm">Tab strip rendered between header and body.</p>`,
|
|
),
|
|
}
|
|
|
|
export const Wide: Story = {
|
|
args: { open: true, title: 'Wide dialog', width: '960px' },
|
|
render: dialogStory('<p class="text-sm">This dialog uses an explicit width of 960px.</p>'),
|
|
}
|