create-auto-app 1.34.0 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/templates/typical/.gitignore +1 -1
- package/templates/typical/auto.config.ts +85 -80
- package/templates/typical/client/.gitignore +0 -4
- package/templates/typical/client/.storybook/main.ts +0 -66
- package/templates/typical/client/.storybook/manager-head.html +0 -154
- package/templates/typical/client/.storybook/manager.ts +0 -164
- package/templates/typical/client/.storybook/preview-head.html +0 -31
- package/templates/typical/client/.storybook/preview.tsx +0 -120
- package/templates/typical/client/codegen.ts +0 -17
- package/templates/typical/client/components.json +0 -29
- package/templates/typical/client/index.html +0 -12
- package/templates/typical/client/package.json +0 -69
- package/templates/typical/client/pnpm-lock.yaml +0 -7868
- package/templates/typical/client/public/blank.svg +0 -1
- package/templates/typical/client/public/mockServiceWorker.js +0 -336
- package/templates/typical/client/src/App.tsx +0 -29
- package/templates/typical/client/src/components/.gitkeep +0 -0
- package/templates/typical/client/src/components/ui/Accordion.stories.tsx +0 -49
- package/templates/typical/client/src/components/ui/Accordion.tsx +0 -55
- package/templates/typical/client/src/components/ui/Alert.stories.tsx +0 -29
- package/templates/typical/client/src/components/ui/Alert.tsx +0 -56
- package/templates/typical/client/src/components/ui/AlertDialog.stories.tsx +0 -67
- package/templates/typical/client/src/components/ui/AlertDialog.tsx +0 -178
- package/templates/typical/client/src/components/ui/AspectRatio.stories.tsx +0 -35
- package/templates/typical/client/src/components/ui/AspectRatio.tsx +0 -13
- package/templates/typical/client/src/components/ui/Avatar.stories.tsx +0 -45
- package/templates/typical/client/src/components/ui/Avatar.tsx +0 -98
- package/templates/typical/client/src/components/ui/Badge.stories.tsx +0 -41
- package/templates/typical/client/src/components/ui/Badge.tsx +0 -45
- package/templates/typical/client/src/components/ui/Breadcrumb.stories.tsx +0 -54
- package/templates/typical/client/src/components/ui/Breadcrumb.tsx +0 -104
- package/templates/typical/client/src/components/ui/Button.stories.tsx +0 -102
- package/templates/typical/client/src/components/ui/Button.tsx +0 -67
- package/templates/typical/client/src/components/ui/ButtonGroup.stories.tsx +0 -32
- package/templates/typical/client/src/components/ui/ButtonGroup.tsx +0 -81
- package/templates/typical/client/src/components/ui/Calendar.stories.tsx +0 -40
- package/templates/typical/client/src/components/ui/Calendar.tsx +0 -165
- package/templates/typical/client/src/components/ui/Card.stories.tsx +0 -44
- package/templates/typical/client/src/components/ui/Card.tsx +0 -66
- package/templates/typical/client/src/components/ui/Carousel.stories.tsx +0 -56
- package/templates/typical/client/src/components/ui/Carousel.tsx +0 -225
- package/templates/typical/client/src/components/ui/Chart.stories.tsx +0 -39
- package/templates/typical/client/src/components/ui/Chart.tsx +0 -305
- package/templates/typical/client/src/components/ui/Checkbox.stories.tsx +0 -35
- package/templates/typical/client/src/components/ui/Checkbox.tsx +0 -30
- package/templates/typical/client/src/components/ui/Collapsible.stories.tsx +0 -58
- package/templates/typical/client/src/components/ui/Collapsible.tsx +0 -18
- package/templates/typical/client/src/components/ui/Combobox.stories.tsx +0 -75
- package/templates/typical/client/src/components/ui/Combobox.tsx +0 -296
- package/templates/typical/client/src/components/ui/Command.stories.tsx +0 -71
- package/templates/typical/client/src/components/ui/Command.tsx +0 -157
- package/templates/typical/client/src/components/ui/ContextMenu.stories.tsx +0 -68
- package/templates/typical/client/src/components/ui/ContextMenu.tsx +0 -231
- package/templates/typical/client/src/components/ui/DesignSystem-Colors.mdx +0 -68
- package/templates/typical/client/src/components/ui/DesignSystem-Colors.stories.tsx +0 -117
- package/templates/typical/client/src/components/ui/DesignSystem-Layout.mdx +0 -64
- package/templates/typical/client/src/components/ui/DesignSystem-Layout.stories.tsx +0 -167
- package/templates/typical/client/src/components/ui/DesignSystem-Overview.stories.tsx +0 -748
- package/templates/typical/client/src/components/ui/DesignSystem-Typography.mdx +0 -31
- package/templates/typical/client/src/components/ui/DesignSystem-Typography.stories.tsx +0 -80
- package/templates/typical/client/src/components/ui/Dialog.stories.tsx +0 -74
- package/templates/typical/client/src/components/ui/Dialog.tsx +0 -154
- package/templates/typical/client/src/components/ui/Direction.stories.tsx +0 -38
- package/templates/typical/client/src/components/ui/Direction.tsx +0 -24
- package/templates/typical/client/src/components/ui/Drawer.stories.tsx +0 -70
- package/templates/typical/client/src/components/ui/Drawer.tsx +0 -124
- package/templates/typical/client/src/components/ui/DropdownMenu.stories.tsx +0 -74
- package/templates/typical/client/src/components/ui/DropdownMenu.tsx +0 -239
- package/templates/typical/client/src/components/ui/Empty.stories.tsx +0 -37
- package/templates/typical/client/src/components/ui/Empty.tsx +0 -98
- package/templates/typical/client/src/components/ui/Field.stories.tsx +0 -50
- package/templates/typical/client/src/components/ui/Field.tsx +0 -251
- package/templates/typical/client/src/components/ui/Form.stories.tsx +0 -45
- package/templates/typical/client/src/components/ui/Form.tsx +0 -148
- package/templates/typical/client/src/components/ui/HoverCard.stories.tsx +0 -49
- package/templates/typical/client/src/components/ui/HoverCard.tsx +0 -39
- package/templates/typical/client/src/components/ui/Input.stories.tsx +0 -42
- package/templates/typical/client/src/components/ui/Input.tsx +0 -22
- package/templates/typical/client/src/components/ui/InputGroup.stories.tsx +0 -53
- package/templates/typical/client/src/components/ui/InputGroup.tsx +0 -153
- package/templates/typical/client/src/components/ui/InputOTP.stories.tsx +0 -42
- package/templates/typical/client/src/components/ui/InputOTP.tsx +0 -72
- package/templates/typical/client/src/components/ui/Item.stories.tsx +0 -64
- package/templates/typical/client/src/components/ui/Item.tsx +0 -168
- package/templates/typical/client/src/components/ui/Kbd.stories.tsx +0 -59
- package/templates/typical/client/src/components/ui/Kbd.tsx +0 -22
- package/templates/typical/client/src/components/ui/Label.stories.tsx +0 -90
- package/templates/typical/client/src/components/ui/Label.tsx +0 -44
- package/templates/typical/client/src/components/ui/Menubar.stories.tsx +0 -78
- package/templates/typical/client/src/components/ui/Menubar.tsx +0 -251
- package/templates/typical/client/src/components/ui/NativeSelect.stories.tsx +0 -45
- package/templates/typical/client/src/components/ui/NativeSelect.tsx +0 -50
- package/templates/typical/client/src/components/ui/NavigationMenu.stories.tsx +0 -80
- package/templates/typical/client/src/components/ui/NavigationMenu.tsx +0 -152
- package/templates/typical/client/src/components/ui/Pagination.stories.tsx +0 -77
- package/templates/typical/client/src/components/ui/Pagination.tsx +0 -108
- package/templates/typical/client/src/components/ui/Popover.stories.tsx +0 -53
- package/templates/typical/client/src/components/ui/Popover.tsx +0 -57
- package/templates/typical/client/src/components/ui/Progress.stories.tsx +0 -32
- package/templates/typical/client/src/components/ui/Progress.tsx +0 -25
- package/templates/typical/client/src/components/ui/RadioGroup.stories.tsx +0 -50
- package/templates/typical/client/src/components/ui/RadioGroup.tsx +0 -36
- package/templates/typical/client/src/components/ui/Resizable.stories.tsx +0 -72
- package/templates/typical/client/src/components/ui/Resizable.tsx +0 -54
- package/templates/typical/client/src/components/ui/ScrollArea.stories.tsx +0 -45
- package/templates/typical/client/src/components/ui/ScrollArea.tsx +0 -51
- package/templates/typical/client/src/components/ui/Select.stories.tsx +0 -59
- package/templates/typical/client/src/components/ui/Select.tsx +0 -171
- package/templates/typical/client/src/components/ui/Separator.stories.tsx +0 -42
- package/templates/typical/client/src/components/ui/Separator.tsx +0 -27
- package/templates/typical/client/src/components/ui/Sheet.stories.tsx +0 -68
- package/templates/typical/client/src/components/ui/Sheet.tsx +0 -115
- package/templates/typical/client/src/components/ui/Sidebar.stories.tsx +0 -96
- package/templates/typical/client/src/components/ui/Sidebar.tsx +0 -695
- package/templates/typical/client/src/components/ui/Skeleton.stories.tsx +0 -40
- package/templates/typical/client/src/components/ui/Skeleton.tsx +0 -11
- package/templates/typical/client/src/components/ui/Slider.stories.tsx +0 -24
- package/templates/typical/client/src/components/ui/Slider.tsx +0 -55
- package/templates/typical/client/src/components/ui/Sonner.stories.tsx +0 -45
- package/templates/typical/client/src/components/ui/Sonner.tsx +0 -38
- package/templates/typical/client/src/components/ui/Spinner.stories.tsx +0 -26
- package/templates/typical/client/src/components/ui/Spinner.tsx +0 -13
- package/templates/typical/client/src/components/ui/Switch.stories.tsx +0 -39
- package/templates/typical/client/src/components/ui/Switch.tsx +0 -35
- package/templates/typical/client/src/components/ui/Table.stories.tsx +0 -67
- package/templates/typical/client/src/components/ui/Table.tsx +0 -86
- package/templates/typical/client/src/components/ui/Tabs.stories.tsx +0 -53
- package/templates/typical/client/src/components/ui/Tabs.tsx +0 -75
- package/templates/typical/client/src/components/ui/Textarea.stories.tsx +0 -27
- package/templates/typical/client/src/components/ui/Textarea.tsx +0 -22
- package/templates/typical/client/src/components/ui/Toast.stories.tsx +0 -116
- package/templates/typical/client/src/components/ui/Toast.tsx +0 -123
- package/templates/typical/client/src/components/ui/Toaster.tsx +0 -32
- package/templates/typical/client/src/components/ui/Toggle.stories.tsx +0 -44
- package/templates/typical/client/src/components/ui/Toggle.tsx +0 -42
- package/templates/typical/client/src/components/ui/ToggleGroup.stories.tsx +0 -61
- package/templates/typical/client/src/components/ui/ToggleGroup.tsx +0 -83
- package/templates/typical/client/src/components/ui/Tooltip.stories.tsx +0 -42
- package/templates/typical/client/src/components/ui/Tooltip.tsx +0 -48
- package/templates/typical/client/src/gql/execute.ts +0 -11
- package/templates/typical/client/src/gql/fragment-masking.ts +0 -83
- package/templates/typical/client/src/gql/gql.ts +0 -9
- package/templates/typical/client/src/gql/graphql.ts +0 -182
- package/templates/typical/client/src/gql/index.ts +0 -2
- package/templates/typical/client/src/graphql/mutations.ts +0 -0
- package/templates/typical/client/src/graphql/queries.ts +0 -0
- package/templates/typical/client/src/hooks/.gitkeep +0 -0
- package/templates/typical/client/src/hooks/use-mobile.ts +0 -19
- package/templates/typical/client/src/hooks/use-toast.ts +0 -186
- package/templates/typical/client/src/index.css +0 -121
- package/templates/typical/client/src/lib/utils.ts +0 -6
- package/templates/typical/client/src/main.tsx +0 -5
- package/templates/typical/client/tsconfig.app.json +0 -26
- package/templates/typical/client/tsconfig.json +0 -10
- package/templates/typical/client/vite.config.ts +0 -50
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Meta, Stories } from '@storybook/addon-docs/blocks';
|
|
2
|
-
|
|
3
|
-
<Meta title="Design System/Typography" />
|
|
4
|
-
|
|
5
|
-
# Typography
|
|
6
|
-
|
|
7
|
-
Typography classes used across the design system. All styles are composed from
|
|
8
|
-
Tailwind CSS utility classes -- no custom font-size tokens are needed.
|
|
9
|
-
|
|
10
|
-
## Reference
|
|
11
|
-
|
|
12
|
-
| Element | Tailwind Classes | Usage |
|
|
13
|
-
| --- | --- | --- |
|
|
14
|
-
| **H1** | `text-5xl font-extrabold tracking-tight` | Hero or display headings |
|
|
15
|
-
| **H2** | `text-4xl font-bold tracking-tight` | Page-level headings |
|
|
16
|
-
| **H3** | `text-3xl font-bold` | Section headings |
|
|
17
|
-
| **H4** | `text-2xl font-semibold` | Subsection headings |
|
|
18
|
-
| **H5** | `text-xl font-semibold` | Card or widget headings |
|
|
19
|
-
| **Body (lead)** | `text-base leading-relaxed` | Long-form paragraphs where extra line-height aids readability |
|
|
20
|
-
| **Body** | `text-base` | Default body text, UI labels |
|
|
21
|
-
| **Muted** | `text-sm text-muted-foreground` | Descriptions, help text, secondary information |
|
|
22
|
-
| **Small / Caption** | `text-xs text-muted-foreground` | Captions, timestamps, metadata |
|
|
23
|
-
|
|
24
|
-
## Guidelines
|
|
25
|
-
|
|
26
|
-
- Prefer semantic heading order (`H1` > `H2` > `H3` ...) for accessibility.
|
|
27
|
-
- Use **lead body** (`leading-relaxed`) only for multi-line content blocks; single-line labels should use the plain **body** style.
|
|
28
|
-
- `text-muted-foreground` maps to the theme's muted colour and automatically adapts between light and dark modes.
|
|
29
|
-
- Avoid mixing heading classes with body classes on the same element.
|
|
30
|
-
|
|
31
|
-
<Stories />
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
|
|
3
|
-
interface TypographyRowProps {
|
|
4
|
-
label: string;
|
|
5
|
-
className: string;
|
|
6
|
-
sample?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function TypographyRow({ label, className, sample }: TypographyRowProps) {
|
|
10
|
-
return (
|
|
11
|
-
<div className="flex flex-col gap-1 border-b border-border pb-4">
|
|
12
|
-
<div className="flex items-baseline gap-3">
|
|
13
|
-
<span className="text-xs font-mono text-muted-foreground min-w-[120px] shrink-0">{label}</span>
|
|
14
|
-
<code className="text-xs bg-muted px-1.5 py-0.5 rounded font-mono">{className}</code>
|
|
15
|
-
</div>
|
|
16
|
-
<div className={className}>{sample ?? 'The quick brown fox jumps over the lazy dog'}</div>
|
|
17
|
-
</div>
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function TypographyScale() {
|
|
22
|
-
return (
|
|
23
|
-
<div className="flex flex-col gap-6 max-w-3xl">
|
|
24
|
-
<div className="flex flex-col gap-1 pb-4">
|
|
25
|
-
<h2 className="text-2xl font-semibold">Typography Scale</h2>
|
|
26
|
-
<p className="text-sm text-muted-foreground">
|
|
27
|
-
Visual reference for typography classes used throughout the design system.
|
|
28
|
-
</p>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<div className="flex flex-col gap-6">
|
|
32
|
-
<h3 className="text-lg font-semibold text-muted-foreground uppercase tracking-wide">Headings</h3>
|
|
33
|
-
<TypographyRow label="H1" className="text-5xl font-extrabold tracking-tight" sample="Display Heading" />
|
|
34
|
-
<TypographyRow label="H2" className="text-4xl font-bold tracking-tight" sample="Page Heading" />
|
|
35
|
-
<TypographyRow label="H3" className="text-3xl font-bold" sample="Section Heading" />
|
|
36
|
-
<TypographyRow label="H4" className="text-2xl font-semibold" sample="Subsection Heading" />
|
|
37
|
-
<TypographyRow label="H5" className="text-xl font-semibold" sample="Card Heading" />
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
<div className="flex flex-col gap-6 mt-4">
|
|
41
|
-
<h3 className="text-lg font-semibold text-muted-foreground uppercase tracking-wide">Body</h3>
|
|
42
|
-
<TypographyRow
|
|
43
|
-
label="Body (lead)"
|
|
44
|
-
className="text-base leading-relaxed"
|
|
45
|
-
sample="Body text with relaxed leading for longer paragraphs. This style improves readability for multi-line content blocks."
|
|
46
|
-
/>
|
|
47
|
-
<TypographyRow
|
|
48
|
-
label="Body"
|
|
49
|
-
className="text-base"
|
|
50
|
-
sample="Default body text used for general content and UI labels."
|
|
51
|
-
/>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<div className="flex flex-col gap-6 mt-4">
|
|
55
|
-
<h3 className="text-lg font-semibold text-muted-foreground uppercase tracking-wide">Muted & Small</h3>
|
|
56
|
-
<TypographyRow
|
|
57
|
-
label="Muted"
|
|
58
|
-
className="text-sm text-muted-foreground"
|
|
59
|
-
sample="Secondary text for descriptions, help text, and supplementary information."
|
|
60
|
-
/>
|
|
61
|
-
<TypographyRow
|
|
62
|
-
label="Small / Caption"
|
|
63
|
-
className="text-xs text-muted-foreground"
|
|
64
|
-
sample="Captions, timestamps, and fine-print details."
|
|
65
|
-
/>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const meta: Meta = {
|
|
72
|
-
title: 'Design System/Typography',
|
|
73
|
-
tags: ['!autodocs', '!manifest'],
|
|
74
|
-
};
|
|
75
|
-
export default meta;
|
|
76
|
-
type Story = StoryObj;
|
|
77
|
-
|
|
78
|
-
export const TypeScale: Story = {
|
|
79
|
-
render: () => <TypographyScale />,
|
|
80
|
-
};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import {
|
|
3
|
-
Dialog,
|
|
4
|
-
DialogContent,
|
|
5
|
-
DialogDescription,
|
|
6
|
-
DialogFooter,
|
|
7
|
-
DialogHeader,
|
|
8
|
-
DialogTitle,
|
|
9
|
-
DialogTrigger,
|
|
10
|
-
} from '@/components/ui/Dialog';
|
|
11
|
-
import { Button } from '@/components/ui/Button';
|
|
12
|
-
import { Input } from '@/components/ui/Input';
|
|
13
|
-
import { Label } from '@/components/ui/Label';
|
|
14
|
-
|
|
15
|
-
const meta: Meta<typeof Dialog> = {
|
|
16
|
-
title: 'UI Components/Dialog',
|
|
17
|
-
component: Dialog,
|
|
18
|
-
};
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof Dialog>;
|
|
21
|
-
|
|
22
|
-
/** Shows a dialog with a form for editing profile information. */
|
|
23
|
-
export const Default: Story = {
|
|
24
|
-
render: () => (
|
|
25
|
-
<Dialog>
|
|
26
|
-
<DialogTrigger asChild>
|
|
27
|
-
<Button variant="outline">Edit Profile</Button>
|
|
28
|
-
</DialogTrigger>
|
|
29
|
-
<DialogContent className="sm:max-w-[425px]">
|
|
30
|
-
<DialogHeader>
|
|
31
|
-
<DialogTitle>Edit profile</DialogTitle>
|
|
32
|
-
<DialogDescription>Make changes to your profile here. Click save when you are done.</DialogDescription>
|
|
33
|
-
</DialogHeader>
|
|
34
|
-
<div className="grid gap-4 py-4">
|
|
35
|
-
<div className="grid grid-cols-4 items-center gap-4">
|
|
36
|
-
<Label htmlFor="name" className="text-right">
|
|
37
|
-
Name
|
|
38
|
-
</Label>
|
|
39
|
-
<Input id="name" defaultValue="John Doe" className="col-span-3" />
|
|
40
|
-
</div>
|
|
41
|
-
<div className="grid grid-cols-4 items-center gap-4">
|
|
42
|
-
<Label htmlFor="username" className="text-right">
|
|
43
|
-
Username
|
|
44
|
-
</Label>
|
|
45
|
-
<Input id="username" defaultValue="@johndoe" className="col-span-3" />
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
<DialogFooter>
|
|
49
|
-
<Button type="submit">Save changes</Button>
|
|
50
|
-
</DialogFooter>
|
|
51
|
-
</DialogContent>
|
|
52
|
-
</Dialog>
|
|
53
|
-
),
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/** Shows a confirmation dialog with a footer close button and a destructive action. */
|
|
57
|
-
export const WithCloseButton: Story = {
|
|
58
|
-
render: () => (
|
|
59
|
-
<Dialog>
|
|
60
|
-
<DialogTrigger asChild>
|
|
61
|
-
<Button variant="outline">Open Dialog</Button>
|
|
62
|
-
</DialogTrigger>
|
|
63
|
-
<DialogContent>
|
|
64
|
-
<DialogHeader>
|
|
65
|
-
<DialogTitle>Confirm Action</DialogTitle>
|
|
66
|
-
<DialogDescription>Are you sure you want to proceed? This action cannot be undone.</DialogDescription>
|
|
67
|
-
</DialogHeader>
|
|
68
|
-
<DialogFooter showCloseButton>
|
|
69
|
-
<Button variant="destructive">Confirm</Button>
|
|
70
|
-
</DialogFooter>
|
|
71
|
-
</DialogContent>
|
|
72
|
-
</Dialog>
|
|
73
|
-
),
|
|
74
|
-
};
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { XIcon } from 'lucide-react';
|
|
3
|
-
import { Dialog as DialogPrimitive } from 'radix-ui';
|
|
4
|
-
|
|
5
|
-
import { cn } from '@/lib/utils';
|
|
6
|
-
import { Button } from '@/components/ui/Button';
|
|
7
|
-
|
|
8
|
-
/** A modal overlay with focus trapping and scroll locking. Click outside or press Escape to close. */
|
|
9
|
-
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
10
|
-
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/** Button or element that opens the dialog when clicked. */
|
|
14
|
-
function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
15
|
-
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/** Renders dialog content into a React portal. */
|
|
19
|
-
function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
20
|
-
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** Programmatic close trigger for the dialog. */
|
|
24
|
-
function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
25
|
-
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Semi-transparent backdrop behind the dialog that dims the page content. */
|
|
29
|
-
function DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
30
|
-
return (
|
|
31
|
-
<DialogPrimitive.Overlay
|
|
32
|
-
data-slot="dialog-overlay"
|
|
33
|
-
className={cn(
|
|
34
|
-
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
|
|
35
|
-
className,
|
|
36
|
-
)}
|
|
37
|
-
{...props}
|
|
38
|
-
/>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* The main dialog panel centered on screen with overlay backdrop.
|
|
44
|
-
* Set showCloseButton={false} to hide the top-right X button.
|
|
45
|
-
*/
|
|
46
|
-
function DialogContent({
|
|
47
|
-
className,
|
|
48
|
-
children,
|
|
49
|
-
/** Whether to render the close (X) button in the top-right corner. */
|
|
50
|
-
showCloseButton = true,
|
|
51
|
-
...props
|
|
52
|
-
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
53
|
-
showCloseButton?: boolean;
|
|
54
|
-
}) {
|
|
55
|
-
return (
|
|
56
|
-
<DialogPortal data-slot="dialog-portal">
|
|
57
|
-
<DialogOverlay />
|
|
58
|
-
<DialogPrimitive.Content
|
|
59
|
-
data-slot="dialog-content"
|
|
60
|
-
className={cn(
|
|
61
|
-
'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 outline-none sm:max-w-lg',
|
|
62
|
-
className,
|
|
63
|
-
)}
|
|
64
|
-
{...props}
|
|
65
|
-
>
|
|
66
|
-
{children}
|
|
67
|
-
{showCloseButton && (
|
|
68
|
-
<DialogPrimitive.Close
|
|
69
|
-
data-slot="dialog-close"
|
|
70
|
-
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
|
71
|
-
>
|
|
72
|
-
<XIcon />
|
|
73
|
-
<span className="sr-only">Close</span>
|
|
74
|
-
</DialogPrimitive.Close>
|
|
75
|
-
)}
|
|
76
|
-
</DialogPrimitive.Content>
|
|
77
|
-
</DialogPortal>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Container for DialogTitle and DialogDescription at the top of the dialog. */
|
|
82
|
-
function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
83
|
-
return (
|
|
84
|
-
<div
|
|
85
|
-
data-slot="dialog-header"
|
|
86
|
-
className={cn('flex flex-col gap-2 text-center sm:text-left', className)}
|
|
87
|
-
{...props}
|
|
88
|
-
/>
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Container for action buttons at the bottom of the dialog.
|
|
94
|
-
* Set showCloseButton to add an automatic "Close" button.
|
|
95
|
-
*/
|
|
96
|
-
function DialogFooter({
|
|
97
|
-
className,
|
|
98
|
-
/** Whether to append a "Close" button that dismisses the dialog. */
|
|
99
|
-
showCloseButton = false,
|
|
100
|
-
children,
|
|
101
|
-
...props
|
|
102
|
-
}: React.ComponentProps<'div'> & {
|
|
103
|
-
showCloseButton?: boolean;
|
|
104
|
-
}) {
|
|
105
|
-
return (
|
|
106
|
-
<div
|
|
107
|
-
data-slot="dialog-footer"
|
|
108
|
-
className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
|
|
109
|
-
{...props}
|
|
110
|
-
>
|
|
111
|
-
{children}
|
|
112
|
-
{showCloseButton && (
|
|
113
|
-
<DialogPrimitive.Close asChild>
|
|
114
|
-
<Button variant="outline">Close</Button>
|
|
115
|
-
</DialogPrimitive.Close>
|
|
116
|
-
)}
|
|
117
|
-
</div>
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Accessible title for the dialog. Required for screen reader support. */
|
|
122
|
-
function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
123
|
-
return (
|
|
124
|
-
<DialogPrimitive.Title
|
|
125
|
-
data-slot="dialog-title"
|
|
126
|
-
className={cn('text-lg leading-none font-semibold', className)}
|
|
127
|
-
{...props}
|
|
128
|
-
/>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** Accessible description text for the dialog, displayed below the title. */
|
|
133
|
-
function DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
134
|
-
return (
|
|
135
|
-
<DialogPrimitive.Description
|
|
136
|
-
data-slot="dialog-description"
|
|
137
|
-
className={cn('text-muted-foreground text-sm', className)}
|
|
138
|
-
{...props}
|
|
139
|
-
/>
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export {
|
|
144
|
-
Dialog,
|
|
145
|
-
DialogClose,
|
|
146
|
-
DialogContent,
|
|
147
|
-
DialogDescription,
|
|
148
|
-
DialogFooter,
|
|
149
|
-
DialogHeader,
|
|
150
|
-
DialogOverlay,
|
|
151
|
-
DialogPortal,
|
|
152
|
-
DialogTitle,
|
|
153
|
-
DialogTrigger,
|
|
154
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { DirectionProvider, useDirection } from '@/components/ui/Direction';
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof DirectionProvider> = {
|
|
5
|
-
title: 'UI Components/Direction',
|
|
6
|
-
component: DirectionProvider,
|
|
7
|
-
};
|
|
8
|
-
export default meta;
|
|
9
|
-
type Story = StoryObj<typeof DirectionProvider>;
|
|
10
|
-
|
|
11
|
-
function DirectionDisplay() {
|
|
12
|
-
const direction = useDirection();
|
|
13
|
-
return <p className="text-sm text-muted-foreground">Current direction: {direction ?? 'not set'}</p>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** Shows the DirectionProvider in left-to-right mode. */
|
|
17
|
-
export const LTR: Story = {
|
|
18
|
-
render: () => (
|
|
19
|
-
<DirectionProvider dir="ltr">
|
|
20
|
-
<div className="space-y-2">
|
|
21
|
-
<DirectionDisplay />
|
|
22
|
-
<p>This content is rendered in a left-to-right context.</p>
|
|
23
|
-
</div>
|
|
24
|
-
</DirectionProvider>
|
|
25
|
-
),
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/** Shows the DirectionProvider in right-to-left mode for internationalization support. */
|
|
29
|
-
export const RTL: Story = {
|
|
30
|
-
render: () => (
|
|
31
|
-
<DirectionProvider dir="rtl">
|
|
32
|
-
<div className="space-y-2" dir="rtl">
|
|
33
|
-
<DirectionDisplay />
|
|
34
|
-
<p>This content is rendered in a right-to-left context.</p>
|
|
35
|
-
</div>
|
|
36
|
-
</DirectionProvider>
|
|
37
|
-
),
|
|
38
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
import { Direction } from 'radix-ui';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Provides text direction (LTR/RTL) context to all descendant Radix UI components.
|
|
8
|
-
* Accepts either `dir` or `direction` prop for convenience.
|
|
9
|
-
*/
|
|
10
|
-
function DirectionProvider({
|
|
11
|
-
dir,
|
|
12
|
-
/** Alias for `dir`. If both are provided, `direction` takes precedence. */
|
|
13
|
-
direction,
|
|
14
|
-
children,
|
|
15
|
-
}: React.ComponentProps<typeof Direction.DirectionProvider> & {
|
|
16
|
-
direction?: React.ComponentProps<typeof Direction.DirectionProvider>['dir'];
|
|
17
|
-
}) {
|
|
18
|
-
return <Direction.DirectionProvider dir={direction ?? dir}>{children}</Direction.DirectionProvider>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Hook to read the current text direction from the nearest DirectionProvider. */
|
|
22
|
-
const useDirection = Direction.useDirection;
|
|
23
|
-
|
|
24
|
-
export { DirectionProvider, useDirection };
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import {
|
|
3
|
-
Drawer,
|
|
4
|
-
DrawerTrigger,
|
|
5
|
-
DrawerContent,
|
|
6
|
-
DrawerHeader,
|
|
7
|
-
DrawerFooter,
|
|
8
|
-
DrawerTitle,
|
|
9
|
-
DrawerDescription,
|
|
10
|
-
DrawerClose,
|
|
11
|
-
} from '@/components/ui/Drawer';
|
|
12
|
-
import { Button } from '@/components/ui/Button';
|
|
13
|
-
|
|
14
|
-
const meta: Meta<typeof Drawer> = {
|
|
15
|
-
title: 'UI Components/Drawer',
|
|
16
|
-
component: Drawer,
|
|
17
|
-
};
|
|
18
|
-
export default meta;
|
|
19
|
-
type Story = StoryObj<typeof Drawer>;
|
|
20
|
-
|
|
21
|
-
/** Shows a bottom drawer with a title, description, body content, and action buttons. */
|
|
22
|
-
export const Default: Story = {
|
|
23
|
-
render: () => (
|
|
24
|
-
<Drawer>
|
|
25
|
-
<DrawerTrigger asChild>
|
|
26
|
-
<Button variant="outline">Open Drawer</Button>
|
|
27
|
-
</DrawerTrigger>
|
|
28
|
-
<DrawerContent>
|
|
29
|
-
<DrawerHeader>
|
|
30
|
-
<DrawerTitle>Move Goal</DrawerTitle>
|
|
31
|
-
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
|
|
32
|
-
</DrawerHeader>
|
|
33
|
-
<div className="p-4">
|
|
34
|
-
<p className="text-muted-foreground text-sm">Adjust the settings below to configure your preferences.</p>
|
|
35
|
-
</div>
|
|
36
|
-
<DrawerFooter>
|
|
37
|
-
<Button>Submit</Button>
|
|
38
|
-
<DrawerClose asChild>
|
|
39
|
-
<Button variant="outline">Cancel</Button>
|
|
40
|
-
</DrawerClose>
|
|
41
|
-
</DrawerFooter>
|
|
42
|
-
</DrawerContent>
|
|
43
|
-
</Drawer>
|
|
44
|
-
),
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/** Shows a drawer sliding in from the right side, useful for side panels and detail views. */
|
|
48
|
-
export const RightSide: Story = {
|
|
49
|
-
render: () => (
|
|
50
|
-
<Drawer direction="right">
|
|
51
|
-
<DrawerTrigger asChild>
|
|
52
|
-
<Button variant="outline">Open Right Drawer</Button>
|
|
53
|
-
</DrawerTrigger>
|
|
54
|
-
<DrawerContent>
|
|
55
|
-
<DrawerHeader>
|
|
56
|
-
<DrawerTitle>Side Panel</DrawerTitle>
|
|
57
|
-
<DrawerDescription>This drawer opens from the right side.</DrawerDescription>
|
|
58
|
-
</DrawerHeader>
|
|
59
|
-
<div className="p-4">
|
|
60
|
-
<p className="text-muted-foreground text-sm">Content goes here.</p>
|
|
61
|
-
</div>
|
|
62
|
-
<DrawerFooter>
|
|
63
|
-
<DrawerClose asChild>
|
|
64
|
-
<Button variant="outline">Close</Button>
|
|
65
|
-
</DrawerClose>
|
|
66
|
-
</DrawerFooter>
|
|
67
|
-
</DrawerContent>
|
|
68
|
-
</Drawer>
|
|
69
|
-
),
|
|
70
|
-
};
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Drawer as DrawerPrimitive } from 'vaul';
|
|
3
|
-
|
|
4
|
-
import { cn } from '@/lib/utils';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A panel that slides in from the edge of the screen, ideal for mobile-friendly interactions.
|
|
8
|
-
* Built on Vaul with swipe-to-dismiss gestures. Supports top, bottom, left, and right directions.
|
|
9
|
-
*
|
|
10
|
-
* Compose with DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, and DrawerFooter.
|
|
11
|
-
*/
|
|
12
|
-
function Drawer({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) {
|
|
13
|
-
return <DrawerPrimitive.Root data-slot="drawer" {...props} />;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** Button or element that opens the drawer when clicked. */
|
|
17
|
-
function DrawerTrigger({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
|
|
18
|
-
return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Renders drawer content into a React portal. */
|
|
22
|
-
function DrawerPortal({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
|
|
23
|
-
return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Programmatic close trigger for the drawer. */
|
|
27
|
-
function DrawerClose({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Close>) {
|
|
28
|
-
return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** Semi-transparent backdrop behind the drawer that dims the page content. */
|
|
32
|
-
function DrawerOverlay({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
|
|
33
|
-
return (
|
|
34
|
-
<DrawerPrimitive.Overlay
|
|
35
|
-
data-slot="drawer-overlay"
|
|
36
|
-
className={cn(
|
|
37
|
-
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
|
|
38
|
-
className,
|
|
39
|
-
)}
|
|
40
|
-
{...props}
|
|
41
|
-
/>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The main drawer panel that slides in from the configured direction.
|
|
47
|
-
* Automatically shows a drag handle for bottom drawers.
|
|
48
|
-
*/
|
|
49
|
-
function DrawerContent({ className, children, ...props }: React.ComponentProps<typeof DrawerPrimitive.Content>) {
|
|
50
|
-
return (
|
|
51
|
-
<DrawerPortal data-slot="drawer-portal">
|
|
52
|
-
<DrawerOverlay />
|
|
53
|
-
<DrawerPrimitive.Content
|
|
54
|
-
data-slot="drawer-content"
|
|
55
|
-
className={cn(
|
|
56
|
-
'group/drawer-content bg-background fixed z-50 flex h-auto flex-col',
|
|
57
|
-
'data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b',
|
|
58
|
-
'data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t',
|
|
59
|
-
'data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm',
|
|
60
|
-
'data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm',
|
|
61
|
-
className,
|
|
62
|
-
)}
|
|
63
|
-
{...props}
|
|
64
|
-
>
|
|
65
|
-
<div className="bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
|
|
66
|
-
{children}
|
|
67
|
-
</DrawerPrimitive.Content>
|
|
68
|
-
</DrawerPortal>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** Container for DrawerTitle and DrawerDescription at the top of the drawer. */
|
|
73
|
-
function DrawerHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
74
|
-
return (
|
|
75
|
-
<div
|
|
76
|
-
data-slot="drawer-header"
|
|
77
|
-
className={cn(
|
|
78
|
-
'flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left',
|
|
79
|
-
className,
|
|
80
|
-
)}
|
|
81
|
-
{...props}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** Container for action buttons at the bottom of the drawer. */
|
|
87
|
-
function DrawerFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
88
|
-
return <div data-slot="drawer-footer" className={cn('mt-auto flex flex-col gap-2 p-4', className)} {...props} />;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Accessible title for the drawer. */
|
|
92
|
-
function DrawerTitle({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Title>) {
|
|
93
|
-
return (
|
|
94
|
-
<DrawerPrimitive.Title
|
|
95
|
-
data-slot="drawer-title"
|
|
96
|
-
className={cn('text-foreground font-semibold', className)}
|
|
97
|
-
{...props}
|
|
98
|
-
/>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** Accessible description text for the drawer, displayed below the title. */
|
|
103
|
-
function DrawerDescription({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Description>) {
|
|
104
|
-
return (
|
|
105
|
-
<DrawerPrimitive.Description
|
|
106
|
-
data-slot="drawer-description"
|
|
107
|
-
className={cn('text-muted-foreground text-sm', className)}
|
|
108
|
-
{...props}
|
|
109
|
-
/>
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export {
|
|
114
|
-
Drawer,
|
|
115
|
-
DrawerPortal,
|
|
116
|
-
DrawerOverlay,
|
|
117
|
-
DrawerTrigger,
|
|
118
|
-
DrawerClose,
|
|
119
|
-
DrawerContent,
|
|
120
|
-
DrawerHeader,
|
|
121
|
-
DrawerFooter,
|
|
122
|
-
DrawerTitle,
|
|
123
|
-
DrawerDescription,
|
|
124
|
-
};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import {
|
|
3
|
-
DropdownMenu,
|
|
4
|
-
DropdownMenuTrigger,
|
|
5
|
-
DropdownMenuContent,
|
|
6
|
-
DropdownMenuItem,
|
|
7
|
-
DropdownMenuLabel,
|
|
8
|
-
DropdownMenuSeparator,
|
|
9
|
-
DropdownMenuShortcut,
|
|
10
|
-
DropdownMenuGroup,
|
|
11
|
-
} from '@/components/ui/DropdownMenu';
|
|
12
|
-
import { Button } from '@/components/ui/Button';
|
|
13
|
-
import { UserIcon, SettingsIcon, LogOutIcon, CreditCardIcon } from 'lucide-react';
|
|
14
|
-
|
|
15
|
-
const meta: Meta<typeof DropdownMenu> = {
|
|
16
|
-
title: 'UI Components/DropdownMenu',
|
|
17
|
-
component: DropdownMenu,
|
|
18
|
-
};
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof DropdownMenu>;
|
|
21
|
-
|
|
22
|
-
/** Shows a dropdown menu with grouped items, icons, keyboard shortcuts, and a destructive logout action. */
|
|
23
|
-
export const Default: Story = {
|
|
24
|
-
render: () => (
|
|
25
|
-
<DropdownMenu>
|
|
26
|
-
<DropdownMenuTrigger asChild>
|
|
27
|
-
<Button variant="outline">Open Menu</Button>
|
|
28
|
-
</DropdownMenuTrigger>
|
|
29
|
-
<DropdownMenuContent className="w-56">
|
|
30
|
-
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
31
|
-
<DropdownMenuSeparator />
|
|
32
|
-
<DropdownMenuGroup>
|
|
33
|
-
<DropdownMenuItem>
|
|
34
|
-
<UserIcon />
|
|
35
|
-
<span>Profile</span>
|
|
36
|
-
<DropdownMenuShortcut>Ctrl+P</DropdownMenuShortcut>
|
|
37
|
-
</DropdownMenuItem>
|
|
38
|
-
<DropdownMenuItem>
|
|
39
|
-
<CreditCardIcon />
|
|
40
|
-
<span>Billing</span>
|
|
41
|
-
<DropdownMenuShortcut>Ctrl+B</DropdownMenuShortcut>
|
|
42
|
-
</DropdownMenuItem>
|
|
43
|
-
<DropdownMenuItem>
|
|
44
|
-
<SettingsIcon />
|
|
45
|
-
<span>Settings</span>
|
|
46
|
-
<DropdownMenuShortcut>Ctrl+S</DropdownMenuShortcut>
|
|
47
|
-
</DropdownMenuItem>
|
|
48
|
-
</DropdownMenuGroup>
|
|
49
|
-
<DropdownMenuSeparator />
|
|
50
|
-
<DropdownMenuItem variant="destructive">
|
|
51
|
-
<LogOutIcon />
|
|
52
|
-
<span>Log out</span>
|
|
53
|
-
</DropdownMenuItem>
|
|
54
|
-
</DropdownMenuContent>
|
|
55
|
-
</DropdownMenu>
|
|
56
|
-
),
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/** Shows a minimal dropdown menu with basic edit/duplicate/delete actions. */
|
|
60
|
-
export const Simple: Story = {
|
|
61
|
-
render: () => (
|
|
62
|
-
<DropdownMenu>
|
|
63
|
-
<DropdownMenuTrigger asChild>
|
|
64
|
-
<Button variant="outline">Actions</Button>
|
|
65
|
-
</DropdownMenuTrigger>
|
|
66
|
-
<DropdownMenuContent>
|
|
67
|
-
<DropdownMenuItem>Edit</DropdownMenuItem>
|
|
68
|
-
<DropdownMenuItem>Duplicate</DropdownMenuItem>
|
|
69
|
-
<DropdownMenuSeparator />
|
|
70
|
-
<DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
|
|
71
|
-
</DropdownMenuContent>
|
|
72
|
-
</DropdownMenu>
|
|
73
|
-
),
|
|
74
|
-
};
|