import type { Meta, StoryObj } from '@storybook/vue3-vite' import { useToast } from 'primevue/usetoast' import { ref } from 'vue' import CpToast from '@/components/CpToast.vue' import { CpToastTypes } from '@/constants/CpToastTypes' type CpToastPosition = | 'bottom-center' | 'bottom-left' | 'bottom-right' | 'center' | 'top-center' | 'top-left' | 'top-right' /** `CpToast` has no `defineProps`; layout props are passed through to PrimeVue `Toast`. */ type CpToastStoryArgs = { group?: string position?: CpToastPosition } const toastPositions = [ 'center', 'top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right', ] as const const meta = { title: 'Molecules/CpToast', component: CpToast, argTypes: { position: { control: { type: 'select' }, options: toastPositions, description: 'Where to anchor the toast stack on the screen', }, }, args: { position: 'top-right', group: undefined, }, } satisfies Meta export default meta type Story = StoryObj /** * Trigger toasts of every severity using the `useToast()` composable. * Buttons in the canvas call `toast.add()` with a different `severity`. */ export const Severities: Story = { render: (args) => ({ components: { CpToast }, setup() { const toast = useToast() const baseOptions = { severity: CpToastTypes.SECONDARY, summary: "Hello i'm a cpToast!", detail: 'This is a cpToast description.', } const notify = (severity: string) => toast.add({ ...baseOptions, severity }) return { args, notify } }, template: `

Toasts are triggered via useToast().

`, }), } /** * Toasts with a `life` (auto-close) duration can optionally render a * countdown bar via the `showTimer` option. */ export const WithTimer: Story = { render: (args) => ({ components: { CpToast }, setup() { const toast = useToast() const showTimer = ref(false) const notifyWithTimer = () => { toast.add({ severity: CpToastTypes.INFO, summary: "Hello i'm a cpToast with a timer!", detail: 'This is a cpToast description.', life: 2500, showTimer: showTimer.value, } as never) } return { args, notifyWithTimer, showTimer } }, template: `
Show toast with timer
`, }), } /** * Pass `primaryAction` / `secondaryAction` to render buttons inside the * toast. Each action exposes a label, optional icons and an `onClick` * callback. */ export const WithActions: Story = { render: (args) => ({ components: { CpToast }, setup() { const toast = useToast() const notifyWithActions = () => { toast.add({ severity: CpToastTypes.INFO, summary: "Hello i'm a cpToast with actions!", detail: 'This is a cpToast description.', primaryAction: { label: 'Primary action', leadingIcon: 'user', onClick: () => console.log('Primary action clicked'), }, secondaryAction: { label: 'Secondary action', trailingIcon: 'arrow-right', onClick: () => console.log('Secondary action clicked'), }, } as never) } return { args, notifyWithActions } }, template: `
Show toast with actions
`, }), } /** * The toast stack is positioned via the `position` prop on the * `` mount point. Update the control to try every anchor. */ export const Positions: Story = { render: (args) => ({ components: { CpToast }, setup() { const toast = useToast() const notify = () => { toast.add({ severity: CpToastTypes.INFO, summary: "Hello i'm a cpToast!", detail: 'This is a cpToast description.', }) } return { args, notify } }, template: `
Show toast
`, }), }