Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
276 changes: 276 additions & 0 deletions src/components/ui/Dialog.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import type { Meta, StoryObj } from "@storybook/react";
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
DialogClose,
Button,
Input,
Label,
} from "./index";

function DialogDemo() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Edit Profile
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you&apos;re done.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="name" className="text-end">
Name
</Label>
<Input
id="name"
defaultValue="Pedro Duarte"
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="username" className="text-end">
Username
</Label>
<Input
id="username"
defaultValue="@peduarte"
className="col-span-3"
/>
</div>
</div>
<DialogFooter>
<DialogClose render={<Button variant="outline" />}>
Cancel
</DialogClose>
<Button type="submit">Save changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}

function DialogCustomCloseDemo() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Custom Close Button
</DialogTrigger>
<DialogContent showCloseButton={false}>
<DialogHeader>
<DialogTitle>Custom Close</DialogTitle>
<DialogDescription>
This dialog uses a custom close button in the footer instead of the
default X button.
</DialogDescription>
</DialogHeader>
<div className="py-4">
<p className="text-sm text-muted-foreground">
You can customize the close behavior by using the DialogClose
component anywhere inside the dialog.
</p>
</div>
<DialogFooter>
<DialogClose render={<Button variant="outline" />}>
Close
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}

function DialogNoCloseButtonDemo() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
No Close Button
</DialogTrigger>
<DialogContent showCloseButton={false}>
<DialogHeader>
<DialogTitle>No Close Button</DialogTitle>
<DialogDescription>
This dialog has no close button. Click outside or press Escape to
close it.
</DialogDescription>
</DialogHeader>
<div className="py-4">
<p className="text-sm text-muted-foreground">
Use <code className="text-foreground">showCloseButton=&#123;false&#125;</code> to
hide the default close button.
</p>
</div>
</DialogContent>
</Dialog>
);
}

function DialogScrollableDemo() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Scrollable Content
</DialogTrigger>
<DialogContent className="max-h-[80vh] overflow-hidden flex flex-col">
<DialogHeader>
<DialogTitle>Terms of Service</DialogTitle>
<DialogDescription>
Please read the following terms carefully.
</DialogDescription>
</DialogHeader>
<div className="overflow-y-auto flex-1 py-4 pe-2">
<div className="space-y-4 text-sm text-muted-foreground">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat.
</p>
<p>
Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
</p>
<p>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae vitae
dicta sunt explicabo.
</p>
<p>
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit
aut fugit, sed quia consequuntur magni dolores eos qui ratione
voluptatem sequi nesciunt.
</p>
<p>
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet,
consectetur, adipisci velit, sed quia non numquam eius modi tempora
incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
</p>
<p>
Ut enim ad minima veniam, quis nostrum exercitationem ullam
corporis suscipit laboriosam, nisi ut aliquid ex ea commodi
consequatur? Quis autem vel eum iure reprehenderit qui in ea
voluptate velit esse quam nihil molestiae consequatur.
</p>
<p>
At vero eos et accusamus et iusto odio dignissimos ducimus qui
blanditiis praesentium voluptatum deleniti atque corrupti quos
dolores et quas molestias excepturi sint occaecati cupiditate non
provident.
</p>
<p>
Similique sunt in culpa qui officia deserunt mollitia animi, id est
laborum et dolorum fuga. Et harum quidem rerum facilis est et
expedita distinctio.
</p>
</div>
</div>
<DialogFooter>
<DialogClose render={<Button variant="outline" />}>
Decline
</DialogClose>
<Button>Accept</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}

function DialogStickyFooterDemo() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Sticky Footer
</DialogTrigger>
<DialogContent className="max-h-[80vh] overflow-hidden flex flex-col gap-0 p-0">
<DialogHeader className="p-6 pb-4">
<DialogTitle>Edit Settings</DialogTitle>
<DialogDescription>
Configure your application settings below. The footer stays fixed at
the bottom.
</DialogDescription>
</DialogHeader>
<div className="overflow-y-auto flex-1 px-6 py-4">
<div className="space-y-6">
<div className="space-y-2">
<Label htmlFor="app-name">Application Name</Label>
<Input id="app-name" defaultValue="My Application" />
</div>
<div className="space-y-2">
<Label htmlFor="app-url">Application URL</Label>
<Input id="app-url" defaultValue="https://example.com" />
</div>
<div className="space-y-2">
<Label htmlFor="api-key">API Key</Label>
<Input id="api-key" defaultValue="sk-xxxxxxxxxxxx" />
</div>
<div className="space-y-2">
<Label htmlFor="webhook">Webhook URL</Label>
<Input id="webhook" defaultValue="https://example.com/webhook" />
</div>
<div className="space-y-2">
<Label htmlFor="callback">Callback URL</Label>
<Input id="callback" defaultValue="https://example.com/callback" />
</div>
<div className="space-y-2">
<Label htmlFor="redirect">Redirect URL</Label>
<Input id="redirect" defaultValue="https://example.com/redirect" />
</div>
<div className="space-y-2">
<Label htmlFor="description">Description</Label>
<Input id="description" defaultValue="A sample application" />
</div>
</div>
</div>
<DialogFooter className="border-t border-border p-6 pt-4">
<DialogClose render={<Button variant="outline" />}>
Cancel
</DialogClose>
<Button>Save changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}

const meta = {
title: "UI/Dialog",
component: Dialog,
parameters: { layout: "centered" },
tags: ["autodocs"],
} satisfies Meta<typeof Dialog>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
render: () => <DialogDemo />,
};

export const CustomCloseButton: Story = {
render: () => <DialogCustomCloseDemo />,
};

export const NoCloseButton: Story = {
render: () => <DialogNoCloseButtonDemo />,
};

export const ScrollableContent: Story = {
render: () => <DialogScrollableDemo />,
};

export const StickyFooter: Story = {
render: () => <DialogStickyFooterDemo />,
};
Loading
Loading