veza/apps/web/src/components/ui/Dialog.stories.tsx
senke 8a3da49fbd style(ui): elevate Dialog to SaaS Premium
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-07 15:08:52 +01:00

132 lines
4 KiB
TypeScript

import type { Meta, StoryObj } from '@storybook/react';
import { useState } from 'react';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogBody,
DialogSkeleton,
} from './dialog';
import { Button } from './button';
const meta = {
title: 'UI/Dialog',
component: Dialog,
tags: ['autodocs'],
argTypes: {
variant: {
control: 'select',
options: ['default', 'alert', 'confirm', 'info'],
},
size: {
control: 'select',
options: ['sm', 'md', 'lg', 'xl'],
},
title: { control: 'text' },
open: { control: 'boolean' },
},
} satisfies Meta<typeof Dialog>;
export default meta;
type Story = StoryObj<typeof Dialog>;
export const Default: Story = {
render: (args) => {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open Dialog</Button>
<Dialog
{...args}
open={open}
onClose={() => setOpen(false)}
title="Edit Profile"
>
<div className="py-4">
<p className="text-sm text-muted-foreground">
Make changes to your profile here. Click save when you're done.
</p>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
<Button onClick={() => setOpen(false)}>Save changes</Button>
</DialogFooter>
</Dialog>
</>
);
},
args: {
variant: 'default',
size: 'md',
}
};
export const Alert: Story = {
render: (args) => {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="destructive" onClick={() => setOpen(true)}>Delete Account</Button>
<Dialog
{...args}
open={open}
onClose={() => setOpen(false)}
variant="alert"
title="Are you absolutely sure?"
onConfirm={() => setOpen(false)}
confirmLabel="Delete Account"
>
<p className="text-sm text-muted-foreground">
This action cannot be undone. This will permanently delete your account and remove your data from our servers.
</p>
</Dialog>
</>
);
},
};
export const Composition: Story = {
render: () => {
const [open, setOpen] = useState(false);
return (
<div className="flex flex-col items-center gap-4">
<Button onClick={() => setOpen(true)}>Open Composed Dialog</Button>
{open && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm">
<div className="bg-card border border-border rounded-xl max-w-md w-full">
<DialogHeader>
<DialogTitle>Composed Dialog</DialogTitle>
<DialogDescription>
Built using sub-components.
</DialogDescription>
</DialogHeader>
<DialogBody>Main content goes here.</DialogBody>
<DialogFooter>
<Button onClick={() => setOpen(false)}>Close</Button>
</DialogFooter>
</div>
</div>
)}
</div>
);
},
};
export const Loading: Story = {
name: 'Chargement',
render: () => (
<div className="min-h-layout-story w-full flex items-center justify-center p-4">
<DialogSkeleton className="max-w-md w-full" />
</div>
),
parameters: {
docs: {
description: {
story: 'Skeleton lorsque le contenu du dialogue est en chargement.',
},
},
},
};