import type { Meta, StoryObj } from '@storybook/react-vite' import { useState } from 'react' import { userEvent, within, expect } from 'storybook/test' import { DialogField } from './DialogField' import { ButtonWidget } from '../Button/ButtonWidget' import { TextField } from '../TextField/TextField' const meta = { title: 'Components/Dialog', component: DialogField, tags: ['autodocs'], parameters: { layout: 'centered' }, argTypes: { width: { control: 'select', options: ['NARROW', 'MEDIUM', 'MEDIUM_PLUS', 'WIDE', 'FIT'] }, height: { control: 'select', options: ['AUTO', 'FIT', 'SHORT', 'MEDIUM', 'TALL'] }, }, } satisfies Meta export default meta type Story = StoryObj // Shared button classes matching ButtonWidget styles const btnBase = 'inline-flex items-center justify-center font-medium rounded-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 cursor-pointer' const btnSolid = `${btnBase} px-4 py-3 text-base leading-none border border-transparent` const btnOutline = `${btnBase} px-4 py-3 text-base leading-none border` const btnSmOutline = `${btnBase} px-3 py-2 text-sm leading-none border` export const Default: Story = { args: { trigger: ( ), title: 'Welcome to Sailwind', description: 'This is a basic dialog example with customizable width and height.', width: 'MEDIUM', height: 'AUTO', children: (

This dialog demonstrates the basic functionality with a title, description, and content area. The dialog can be closed by clicking the X button, pressing Escape, or clicking outside.

), }, play: async ({ canvasElement }) => { const canvas = within(canvasElement) await userEvent.click(canvas.getByRole('button', { name: /open basic dialog/i })) const body = within(document.body) await expect(body.getByText('Welcome to Sailwind')).toBeVisible() await expect(body.getByText(/basic dialog example/i)).toBeVisible() await userEvent.click(body.getByRole('button', { name: /close dialog/i })) await expect(body.queryByText('Welcome to Sailwind')).not.toBeInTheDocument() }, } export const FormDialog: Story = { args: { children: null, title: 'Edit Profile', }, render: () => { const [open, setOpen] = useState(false) const [name, setName] = useState('John Doe') const [email, setEmail] = useState('john.doe@example.com') return ( Edit Profile } title="Edit Profile" description="Update your profile information below." width="MEDIUM_PLUS" height="FIT" >
setName(value)} required={true} /> setEmail(value)} required={true} />
setOpen(false)} /> setOpen(false)} />
) }, play: async ({ canvasElement }) => { const canvas = within(canvasElement) await userEvent.click(canvas.getByRole('button', { name: /edit profile/i })) const body = within(document.body) await expect(body.getByRole('dialog')).toBeVisible() await expect(body.getByLabelText(/full name/i)).toBeVisible() await expect(body.getByLabelText(/email address/i)).toBeVisible() await userEvent.click(body.getByRole('button', { name: /cancel/i })) await expect(body.queryByRole('dialog')).not.toBeInTheDocument() }, } export const ConfirmationDialog: Story = { args: { children: null, title: 'Confirm Deletion', }, render: () => { const [open, setOpen] = useState(false) return ( Delete Item } title="Confirm Deletion" description="This action cannot be undone." width="NARROW" height="AUTO" closeOnOutsideClick={false} >

Are you sure you want to delete this item? This action is permanent and cannot be reversed.

setOpen(false)} /> setOpen(false)} />
) }, play: async ({ canvasElement }) => { const canvas = within(canvasElement) await userEvent.click(canvas.getByRole('button', { name: /delete item/i })) const body = within(document.body) await expect(body.getByText('Confirm Deletion')).toBeVisible() await expect(body.getByText(/cannot be undone/i)).toBeVisible() await userEvent.click(body.getByRole('button', { name: /^delete$/i })) await expect(body.queryByText('Confirm Deletion')).not.toBeInTheDocument() }, } export const WideDialog: Story = { args: { trigger: ( ), title: 'Wide Dialog', width: 'WIDE', height: 'MEDIUM', children: (

This is a wide dialog with medium height. Perfect for displaying detailed content or complex forms that need more horizontal space.

), }, } export const TallDialog: Story = { args: { trigger: ( ), title: 'Tall Dialog', width: 'MEDIUM', height: 'TALL', children: (

This is a tall dialog with fixed height.

{Array.from({ length: 20 }, (_, i) => (

Content item {i + 1} - This dialog has a fixed tall height with scrollable content.

))}
), }, } export const FullWidthFit: Story = { args: { trigger: ( ), title: 'Full Width Dialog', width: 'FIT', height: 'AUTO', children: (

This dialog uses FIT width to take up most of the screen width while still showing some content underneath.

), }, }