mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-26 11:44:28 +08:00
feat(dialog): enhance Dialog component and add comprehensive Storybook examples
- Updated DialogContent styling to use a rounded border and improved shadow effects for better visual appeal. - Introduced a new Storybook file for the Dialog component, featuring multiple stories that demonstrate various use cases, including default, alert, form, and customizable dialogs. - Enhanced accessibility and usability by providing examples for different dialog configurations and actions.
This commit is contained in:
parent
3cd048868a
commit
1f5abf86a0
@ -46,7 +46,7 @@ function DialogContent({
|
||||
<DialogPrimitive.Content
|
||||
data-slot="dialog-content"
|
||||
className={cn(
|
||||
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg',
|
||||
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xs border border-border p-6 shadow-lg duration-200 sm:max-w-lg',
|
||||
className
|
||||
)}
|
||||
{...props}>
|
||||
|
||||
343
packages/ui/stories/components/primitives/Dialog.stories.tsx
Normal file
343
packages/ui/stories/components/primitives/Dialog.stories.tsx
Normal file
@ -0,0 +1,343 @@
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger
|
||||
} from '@cherrystudio/ui'
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
const meta: Meta<typeof Dialog> = {
|
||||
title: 'Components/Primitives/Dialog',
|
||||
component: Dialog,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'A modal dialog component that interrupts the user with important content and expects a response. Based on Radix UI Dialog primitive.'
|
||||
}
|
||||
}
|
||||
},
|
||||
tags: ['autodocs']
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
// Default
|
||||
export const Default: Story = {
|
||||
render: () => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Open Dialog</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Dialog Title</DialogTitle>
|
||||
<DialogDescription>This is a description of the dialog content.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<p className="text-sm text-muted-foreground">Dialog body content goes here.</p>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancel</Button>
|
||||
</DialogClose>
|
||||
<Button>Confirm</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// Without Close Button
|
||||
export const WithoutCloseButton: Story = {
|
||||
render: () => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Open Dialog</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent showCloseButton={false}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>No Close Button</DialogTitle>
|
||||
<DialogDescription>This dialog does not have a close button in the corner.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<p className="text-sm text-muted-foreground">Users must use the footer buttons to close this dialog.</p>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancel</Button>
|
||||
</DialogClose>
|
||||
<Button>Confirm</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// Simple Alert
|
||||
export const SimpleAlert: Story = {
|
||||
render: () => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="destructive">Delete Item</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Are you sure?</DialogTitle>
|
||||
<DialogDescription>
|
||||
This action cannot be undone. This will permanently delete the item from the database.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancel</Button>
|
||||
</DialogClose>
|
||||
<Button variant="destructive">Delete</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// With Form
|
||||
export const WithForm: Story = {
|
||||
render: () => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button>Edit Profile</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Edit Profile</DialogTitle>
|
||||
<DialogDescription>Make changes to your profile here. Click save when you'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-right text-sm font-medium">
|
||||
Name
|
||||
</label>
|
||||
<input
|
||||
id="name"
|
||||
defaultValue="John Doe"
|
||||
className="col-span-3 h-9 rounded-md border px-3 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<label htmlFor="email" className="text-right text-sm font-medium">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
defaultValue="john@example.com"
|
||||
className="col-span-3 h-9 rounded-md border px-3 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancel</Button>
|
||||
</DialogClose>
|
||||
<Button type="submit">Save Changes</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// Custom Width
|
||||
export const CustomWidth: Story = {
|
||||
render: () => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Wide Dialog</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Wide Dialog</DialogTitle>
|
||||
<DialogDescription>This dialog has a custom max-width of 2xl (672px).</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="py-4">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
You can customize the dialog width by passing a className prop with a max-width utility class.
|
||||
</p>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button>Close</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// Scrollable Content
|
||||
export const ScrollableContent: Story = {
|
||||
render: () => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Terms of Service</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-[80vh] overflow-y-auto sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Terms of Service</DialogTitle>
|
||||
<DialogDescription>Please read the following terms carefully.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4 py-4 text-sm text-muted-foreground">
|
||||
{Array.from({ length: 10 }, (_, i) => (
|
||||
<p key={i}>
|
||||
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>
|
||||
))}
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Decline</Button>
|
||||
</DialogClose>
|
||||
<Button>Accept</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// Header Only
|
||||
export const HeaderOnly: Story = {
|
||||
render: () => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Simple Info</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Information</DialogTitle>
|
||||
<DialogDescription>
|
||||
This is a simple informational dialog with only a header and description.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// Multiple Actions
|
||||
export const MultipleActions: Story = {
|
||||
render: () => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Save Document</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Save Document</DialogTitle>
|
||||
<DialogDescription>Choose how you want to save your document.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter className="flex-col gap-2 sm:flex-row">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" className="w-full sm:w-auto">
|
||||
Don't Save
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button variant="secondary" className="w-full sm:w-auto">
|
||||
Save as Draft
|
||||
</Button>
|
||||
<Button className="w-full sm:w-auto">Publish</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// Real World Examples
|
||||
export const RealWorldExamples: Story = {
|
||||
render: () => (
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{/* Delete Confirmation */}
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="destructive">Delete Account</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delete Account</DialogTitle>
|
||||
<DialogDescription>
|
||||
Are you sure you want to delete your account? All of your data will be permanently removed. This action
|
||||
cannot be undone.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancel</Button>
|
||||
</DialogClose>
|
||||
<Button variant="destructive">Delete Account</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* Settings Dialog */}
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Settings</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Settings</DialogTitle>
|
||||
<DialogDescription>Manage your application preferences.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4 py-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium">Dark Mode</p>
|
||||
<p className="text-xs text-muted-foreground">Enable dark theme</p>
|
||||
</div>
|
||||
<input type="checkbox" className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium">Notifications</p>
|
||||
<p className="text-xs text-muted-foreground">Receive email notifications</p>
|
||||
</div>
|
||||
<input type="checkbox" className="h-4 w-4" defaultChecked />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button>Save Settings</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* Share Dialog */}
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button>Share</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Share Link</DialogTitle>
|
||||
<DialogDescription>Anyone with this link can view this document.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex items-center gap-2 py-4">
|
||||
<input
|
||||
readOnly
|
||||
value="https://example.com/share/abc123"
|
||||
className="h-9 flex-1 rounded-md border px-3 text-sm"
|
||||
/>
|
||||
<Button size="sm">Copy</Button>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Close</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user