@trycompai/design-system 1.0.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.
Files changed (71) hide show
  1. package/README.md +110 -0
  2. package/components.json +21 -0
  3. package/hooks/use-mobile.tsx +19 -0
  4. package/lib/utils.ts +6 -0
  5. package/package.json +103 -0
  6. package/postcss.config.mjs +8 -0
  7. package/src/components/ui/accordion.tsx +60 -0
  8. package/src/components/ui/alert-dialog.tsx +161 -0
  9. package/src/components/ui/alert.tsx +109 -0
  10. package/src/components/ui/aspect-ratio.tsx +21 -0
  11. package/src/components/ui/avatar.tsx +74 -0
  12. package/src/components/ui/badge.tsx +48 -0
  13. package/src/components/ui/breadcrumb.tsx +254 -0
  14. package/src/components/ui/button-group.tsx +89 -0
  15. package/src/components/ui/button.tsx +122 -0
  16. package/src/components/ui/calendar.tsx +190 -0
  17. package/src/components/ui/card.tsx +155 -0
  18. package/src/components/ui/carousel.tsx +216 -0
  19. package/src/components/ui/chart.tsx +325 -0
  20. package/src/components/ui/checkbox.tsx +22 -0
  21. package/src/components/ui/collapsible.tsx +17 -0
  22. package/src/components/ui/combobox.tsx +248 -0
  23. package/src/components/ui/command.tsx +189 -0
  24. package/src/components/ui/container.tsx +34 -0
  25. package/src/components/ui/context-menu.tsx +235 -0
  26. package/src/components/ui/dialog.tsx +122 -0
  27. package/src/components/ui/drawer.tsx +102 -0
  28. package/src/components/ui/dropdown-menu.tsx +242 -0
  29. package/src/components/ui/empty.tsx +94 -0
  30. package/src/components/ui/field.tsx +215 -0
  31. package/src/components/ui/grid.tsx +135 -0
  32. package/src/components/ui/heading.tsx +56 -0
  33. package/src/components/ui/hover-card.tsx +46 -0
  34. package/src/components/ui/index.ts +61 -0
  35. package/src/components/ui/input-group.tsx +128 -0
  36. package/src/components/ui/input-otp.tsx +84 -0
  37. package/src/components/ui/input.tsx +15 -0
  38. package/src/components/ui/item.tsx +188 -0
  39. package/src/components/ui/kbd.tsx +26 -0
  40. package/src/components/ui/label.tsx +15 -0
  41. package/src/components/ui/menubar.tsx +163 -0
  42. package/src/components/ui/navigation-menu.tsx +147 -0
  43. package/src/components/ui/page-header.tsx +51 -0
  44. package/src/components/ui/page-layout.tsx +65 -0
  45. package/src/components/ui/pagination.tsx +104 -0
  46. package/src/components/ui/popover.tsx +57 -0
  47. package/src/components/ui/progress.tsx +61 -0
  48. package/src/components/ui/radio-group.tsx +37 -0
  49. package/src/components/ui/resizable.tsx +41 -0
  50. package/src/components/ui/scroll-area.tsx +48 -0
  51. package/src/components/ui/section.tsx +64 -0
  52. package/src/components/ui/select.tsx +166 -0
  53. package/src/components/ui/separator.tsx +17 -0
  54. package/src/components/ui/sheet.tsx +104 -0
  55. package/src/components/ui/sidebar.tsx +707 -0
  56. package/src/components/ui/skeleton.tsx +5 -0
  57. package/src/components/ui/slider.tsx +51 -0
  58. package/src/components/ui/sonner.tsx +43 -0
  59. package/src/components/ui/spinner.tsx +14 -0
  60. package/src/components/ui/stack.tsx +72 -0
  61. package/src/components/ui/switch.tsx +26 -0
  62. package/src/components/ui/table.tsx +65 -0
  63. package/src/components/ui/tabs.tsx +69 -0
  64. package/src/components/ui/text.tsx +59 -0
  65. package/src/components/ui/textarea.tsx +13 -0
  66. package/src/components/ui/toggle-group.tsx +87 -0
  67. package/src/components/ui/toggle.tsx +42 -0
  68. package/src/components/ui/tooltip.tsx +52 -0
  69. package/src/index.ts +3 -0
  70. package/src/styles/globals.css +122 -0
  71. package/tailwind.config.ts +59 -0
@@ -0,0 +1,189 @@
1
+ 'use client';
2
+
3
+ import { Command as CommandPrimitive } from 'cmdk';
4
+ import * as React from 'react';
5
+
6
+ import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
7
+ import { cva, type VariantProps } from 'class-variance-authority';
8
+ import { CheckIcon, SearchIcon } from 'lucide-react';
9
+
10
+ const commandVariants = cva(
11
+ 'bg-popover text-popover-foreground rounded-xl p-1 flex size-full flex-col overflow-hidden',
12
+ {
13
+ variants: {
14
+ width: {
15
+ auto: '',
16
+ sm: 'w-sm',
17
+ md: 'w-md',
18
+ lg: 'w-lg',
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ width: 'auto',
23
+ },
24
+ },
25
+ );
26
+
27
+ interface CommandProps
28
+ extends
29
+ Omit<React.ComponentProps<typeof CommandPrimitive>, 'className'>,
30
+ VariantProps<typeof commandVariants> {}
31
+
32
+ function Command({ width, ...props }: CommandProps) {
33
+ return <CommandPrimitive data-slot="command" className={commandVariants({ width })} {...props} />;
34
+ }
35
+
36
+ function CommandDialog({
37
+ title = 'Command Palette',
38
+ description = 'Search for a command to run...',
39
+ children,
40
+ ...props
41
+ }: Omit<DialogPrimitive.Root.Props, 'children'> & {
42
+ title?: string;
43
+ description?: string;
44
+ children: React.ReactNode;
45
+ }) {
46
+ return (
47
+ <DialogPrimitive.Root data-slot="dialog" {...props}>
48
+ <DialogPrimitive.Portal>
49
+ <DialogPrimitive.Backdrop
50
+ data-slot="dialog-overlay"
51
+ className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50"
52
+ />
53
+ <DialogPrimitive.Popup
54
+ data-slot="command-dialog-content"
55
+ className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 rounded-xl p-0 ring-1 duration-100 sm:max-w-lg group/dialog-content fixed top-1/2 left-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 overflow-hidden outline-none"
56
+ >
57
+ <div
58
+ data-slot="dialog-header"
59
+ className="sr-only flex flex-col gap-1.5 text-center sm:text-left"
60
+ >
61
+ <DialogPrimitive.Title data-slot="dialog-title" className="text-lg font-medium">
62
+ {title}
63
+ </DialogPrimitive.Title>
64
+ <DialogPrimitive.Description
65
+ data-slot="dialog-description"
66
+ className="text-muted-foreground text-sm text-balance md:text-pretty"
67
+ >
68
+ {description}
69
+ </DialogPrimitive.Description>
70
+ </div>
71
+ {children}
72
+ </DialogPrimitive.Popup>
73
+ </DialogPrimitive.Portal>
74
+ </DialogPrimitive.Root>
75
+ );
76
+ }
77
+
78
+ function CommandInput({
79
+ ...props
80
+ }: Omit<React.ComponentProps<typeof CommandPrimitive.Input>, 'className'>) {
81
+ return (
82
+ <div data-slot="command-input-wrapper" className="p-1 pb-0">
83
+ <div
84
+ data-slot="input-group"
85
+ role="group"
86
+ className="border-input/30 bg-input/30 h-8 rounded-lg border shadow-none transition-[color,box-shadow] has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] group/input-group relative flex w-full min-w-0 items-center outline-none"
87
+ >
88
+ <CommandPrimitive.Input
89
+ data-slot="command-input"
90
+ className="w-full flex-1 bg-transparent px-2.5 py-1 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50"
91
+ {...props}
92
+ />
93
+ <div
94
+ data-slot="input-group-addon"
95
+ data-align="inline-end"
96
+ className="text-muted-foreground flex h-auto cursor-text items-center justify-center gap-2 pr-2 text-sm font-medium select-none"
97
+ >
98
+ <SearchIcon className="size-4 shrink-0 opacity-50" />
99
+ </div>
100
+ </div>
101
+ </div>
102
+ );
103
+ }
104
+
105
+ function CommandList({
106
+ ...props
107
+ }: Omit<React.ComponentProps<typeof CommandPrimitive.List>, 'className'>) {
108
+ return (
109
+ <CommandPrimitive.List
110
+ data-slot="command-list"
111
+ className="no-scrollbar max-h-72 scroll-py-1 outline-none overflow-x-hidden overflow-y-auto"
112
+ {...props}
113
+ />
114
+ );
115
+ }
116
+
117
+ function CommandEmpty({
118
+ ...props
119
+ }: Omit<React.ComponentProps<typeof CommandPrimitive.Empty>, 'className'>) {
120
+ return (
121
+ <CommandPrimitive.Empty
122
+ data-slot="command-empty"
123
+ className="py-6 text-center text-sm"
124
+ {...props}
125
+ />
126
+ );
127
+ }
128
+
129
+ function CommandGroup({
130
+ ...props
131
+ }: Omit<React.ComponentProps<typeof CommandPrimitive.Group>, 'className'>) {
132
+ return (
133
+ <CommandPrimitive.Group
134
+ data-slot="command-group"
135
+ className="text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium"
136
+ {...props}
137
+ />
138
+ );
139
+ }
140
+
141
+ function CommandSeparator({
142
+ ...props
143
+ }: Omit<React.ComponentProps<typeof CommandPrimitive.Separator>, 'className'>) {
144
+ return (
145
+ <CommandPrimitive.Separator
146
+ data-slot="command-separator"
147
+ className="bg-border -mx-1 h-px w-auto"
148
+ {...props}
149
+ />
150
+ );
151
+ }
152
+
153
+ function CommandItem({
154
+ children,
155
+ ...props
156
+ }: Omit<React.ComponentProps<typeof CommandPrimitive.Item>, 'className'>) {
157
+ return (
158
+ <CommandPrimitive.Item
159
+ data-slot="command-item"
160
+ className="data-[selected=true]:bg-muted data-[selected=true]:text-foreground data-[selected=true]:**:[svg]:text-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none [&_svg:not([class*='size-'])]:size-4 [[data-slot=dialog-content]_&]:rounded-lg group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0"
161
+ {...props}
162
+ >
163
+ {children}
164
+ <CheckIcon className="ml-auto opacity-0 group-has-[[data-slot=command-shortcut]]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
165
+ </CommandPrimitive.Item>
166
+ );
167
+ }
168
+
169
+ function CommandShortcut({ ...props }: Omit<React.ComponentProps<'span'>, 'className'>) {
170
+ return (
171
+ <span
172
+ data-slot="command-shortcut"
173
+ className="text-muted-foreground group-data-[selected=true]/command-item:text-foreground ml-auto text-xs tracking-widest"
174
+ {...props}
175
+ />
176
+ );
177
+ }
178
+
179
+ export {
180
+ Command,
181
+ CommandDialog,
182
+ CommandEmpty,
183
+ CommandGroup,
184
+ CommandInput,
185
+ CommandItem,
186
+ CommandList,
187
+ CommandSeparator,
188
+ CommandShortcut,
189
+ };
@@ -0,0 +1,34 @@
1
+ import { cva, type VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
+
4
+ const containerVariants = cva('mx-auto w-full', {
5
+ variants: {
6
+ size: {
7
+ sm: 'max-w-screen-sm', // 640px
8
+ md: 'max-w-screen-md', // 768px
9
+ lg: 'max-w-screen-lg', // 1024px
10
+ xl: 'max-w-[1200px]',
11
+ '2xl': 'max-w-[1400px]',
12
+ full: 'max-w-full',
13
+ },
14
+ padding: {
15
+ none: 'px-0',
16
+ sm: 'px-4',
17
+ default: 'px-4 sm:px-6 lg:px-8',
18
+ lg: 'px-6 sm:px-8 lg:px-12',
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ size: 'xl',
23
+ padding: 'default',
24
+ },
25
+ });
26
+
27
+ interface ContainerProps
28
+ extends Omit<React.ComponentProps<'div'>, 'className'>, VariantProps<typeof containerVariants> {}
29
+
30
+ function Container({ size, padding, ...props }: ContainerProps) {
31
+ return <div data-slot="container" className={containerVariants({ size, padding })} {...props} />;
32
+ }
33
+
34
+ export { Container, containerVariants };
@@ -0,0 +1,235 @@
1
+ import { ContextMenu as ContextMenuPrimitive } from '@base-ui/react/context-menu';
2
+ import * as React from 'react';
3
+
4
+ import { CheckIcon, ChevronRightIcon } from 'lucide-react';
5
+ import { cn } from '../../../lib/utils';
6
+
7
+ function ContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) {
8
+ return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />;
9
+ }
10
+
11
+ function ContextMenuPortal({ ...props }: ContextMenuPrimitive.Portal.Props) {
12
+ return <ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />;
13
+ }
14
+
15
+ function ContextMenuTrigger({ className, ...props }: ContextMenuPrimitive.Trigger.Props) {
16
+ return (
17
+ <ContextMenuPrimitive.Trigger
18
+ data-slot="context-menu-trigger"
19
+ className={cn('select-none', className)}
20
+ {...props}
21
+ />
22
+ );
23
+ }
24
+
25
+ function ContextMenuContent({
26
+ className,
27
+ align = 'start',
28
+ alignOffset = 4,
29
+ side = 'right',
30
+ sideOffset = 0,
31
+ ...props
32
+ }: ContextMenuPrimitive.Popup.Props &
33
+ Pick<ContextMenuPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {
34
+ return (
35
+ <ContextMenuPrimitive.Portal>
36
+ <ContextMenuPrimitive.Positioner
37
+ className="isolate z-50 outline-none"
38
+ align={align}
39
+ alignOffset={alignOffset}
40
+ side={side}
41
+ sideOffset={sideOffset}
42
+ >
43
+ <ContextMenuPrimitive.Popup
44
+ data-slot="context-menu-content"
45
+ className={cn(
46
+ 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-36 rounded-md p-1 shadow-md ring-1 duration-100 z-50 max-h-(--available-height) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none',
47
+ className,
48
+ )}
49
+ {...props}
50
+ />
51
+ </ContextMenuPrimitive.Positioner>
52
+ </ContextMenuPrimitive.Portal>
53
+ );
54
+ }
55
+
56
+ function ContextMenuGroup({ ...props }: ContextMenuPrimitive.Group.Props) {
57
+ return <ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />;
58
+ }
59
+
60
+ function ContextMenuLabel({
61
+ className,
62
+ inset,
63
+ ...props
64
+ }: ContextMenuPrimitive.GroupLabel.Props & {
65
+ inset?: boolean;
66
+ }) {
67
+ return (
68
+ <ContextMenuPrimitive.GroupLabel
69
+ data-slot="context-menu-label"
70
+ data-inset={inset}
71
+ className={cn(
72
+ 'text-muted-foreground px-2 py-1.5 text-xs font-medium data-[inset]:pl-8',
73
+ className,
74
+ )}
75
+ {...props}
76
+ />
77
+ );
78
+ }
79
+
80
+ function ContextMenuItem({
81
+ className,
82
+ inset,
83
+ variant = 'default',
84
+ ...props
85
+ }: ContextMenuPrimitive.Item.Props & {
86
+ inset?: boolean;
87
+ variant?: 'default' | 'destructive';
88
+ }) {
89
+ return (
90
+ <ContextMenuPrimitive.Item
91
+ data-slot="context-menu-item"
92
+ data-inset={inset}
93
+ data-variant={variant}
94
+ className={cn(
95
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive focus:*:[svg]:text-accent-foreground gap-2 rounded-sm px-2 py-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 group/context-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
96
+ className,
97
+ )}
98
+ {...props}
99
+ />
100
+ );
101
+ }
102
+
103
+ function ContextMenuSub({ ...props }: ContextMenuPrimitive.SubmenuRoot.Props) {
104
+ return <ContextMenuPrimitive.SubmenuRoot data-slot="context-menu-sub" {...props} />;
105
+ }
106
+
107
+ function ContextMenuSubTrigger({
108
+ className,
109
+ inset,
110
+ children,
111
+ ...props
112
+ }: ContextMenuPrimitive.SubmenuTrigger.Props & {
113
+ inset?: boolean;
114
+ }) {
115
+ return (
116
+ <ContextMenuPrimitive.SubmenuTrigger
117
+ data-slot="context-menu-sub-trigger"
118
+ data-inset={inset}
119
+ className={cn(
120
+ "focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground rounded-sm px-2 py-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
121
+ className,
122
+ )}
123
+ {...props}
124
+ >
125
+ {children}
126
+ <ChevronRightIcon className="ml-auto" />
127
+ </ContextMenuPrimitive.SubmenuTrigger>
128
+ );
129
+ }
130
+
131
+ function ContextMenuSubContent({ ...props }: React.ComponentProps<typeof ContextMenuContent>) {
132
+ return (
133
+ <ContextMenuContent
134
+ data-slot="context-menu-sub-content"
135
+ className="shadow-lg"
136
+ side="right"
137
+ {...props}
138
+ />
139
+ );
140
+ }
141
+
142
+ function ContextMenuCheckboxItem({
143
+ className,
144
+ children,
145
+ checked,
146
+ ...props
147
+ }: ContextMenuPrimitive.CheckboxItem.Props) {
148
+ return (
149
+ <ContextMenuPrimitive.CheckboxItem
150
+ data-slot="context-menu-checkbox-item"
151
+ className={cn(
152
+ "focus:bg-accent focus:text-accent-foreground gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
153
+ className,
154
+ )}
155
+ checked={checked}
156
+ {...props}
157
+ >
158
+ <span className="absolute right-2 pointer-events-none">
159
+ <ContextMenuPrimitive.CheckboxItemIndicator>
160
+ <CheckIcon />
161
+ </ContextMenuPrimitive.CheckboxItemIndicator>
162
+ </span>
163
+ {children}
164
+ </ContextMenuPrimitive.CheckboxItem>
165
+ );
166
+ }
167
+
168
+ function ContextMenuRadioGroup({ ...props }: ContextMenuPrimitive.RadioGroup.Props) {
169
+ return <ContextMenuPrimitive.RadioGroup data-slot="context-menu-radio-group" {...props} />;
170
+ }
171
+
172
+ function ContextMenuRadioItem({
173
+ className,
174
+ children,
175
+ ...props
176
+ }: ContextMenuPrimitive.RadioItem.Props) {
177
+ return (
178
+ <ContextMenuPrimitive.RadioItem
179
+ data-slot="context-menu-radio-item"
180
+ className={cn(
181
+ "focus:bg-accent focus:text-accent-foreground gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
182
+ className,
183
+ )}
184
+ {...props}
185
+ >
186
+ <span className="absolute right-2 pointer-events-none">
187
+ <ContextMenuPrimitive.RadioItemIndicator>
188
+ <CheckIcon />
189
+ </ContextMenuPrimitive.RadioItemIndicator>
190
+ </span>
191
+ {children}
192
+ </ContextMenuPrimitive.RadioItem>
193
+ );
194
+ }
195
+
196
+ function ContextMenuSeparator({ className, ...props }: ContextMenuPrimitive.Separator.Props) {
197
+ return (
198
+ <ContextMenuPrimitive.Separator
199
+ data-slot="context-menu-separator"
200
+ className={cn('bg-border -mx-1 my-1 h-px', className)}
201
+ {...props}
202
+ />
203
+ );
204
+ }
205
+
206
+ function ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
207
+ return (
208
+ <span
209
+ data-slot="context-menu-shortcut"
210
+ className={cn(
211
+ 'text-muted-foreground group-focus/context-menu-item:text-accent-foreground ml-auto text-xs tracking-widest',
212
+ className,
213
+ )}
214
+ {...props}
215
+ />
216
+ );
217
+ }
218
+
219
+ export {
220
+ ContextMenu,
221
+ ContextMenuCheckboxItem,
222
+ ContextMenuContent,
223
+ ContextMenuGroup,
224
+ ContextMenuItem,
225
+ ContextMenuLabel,
226
+ ContextMenuPortal,
227
+ ContextMenuRadioGroup,
228
+ ContextMenuRadioItem,
229
+ ContextMenuSeparator,
230
+ ContextMenuShortcut,
231
+ ContextMenuSub,
232
+ ContextMenuSubContent,
233
+ ContextMenuSubTrigger,
234
+ ContextMenuTrigger,
235
+ };
@@ -0,0 +1,122 @@
1
+ 'use client';
2
+
3
+ import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
4
+ import * as React from 'react';
5
+
6
+ import { XIcon } from 'lucide-react';
7
+ import { Button } from './button';
8
+
9
+ function Dialog({ ...props }: DialogPrimitive.Root.Props) {
10
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />;
11
+ }
12
+
13
+ function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
14
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
15
+ }
16
+
17
+ function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
18
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
19
+ }
20
+
21
+ function DialogClose({ ...props }: DialogPrimitive.Close.Props) {
22
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
23
+ }
24
+
25
+ function DialogOverlay({ ...props }: Omit<DialogPrimitive.Backdrop.Props, 'className'>) {
26
+ return (
27
+ <DialogPrimitive.Backdrop
28
+ data-slot="dialog-overlay"
29
+ className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50"
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ function DialogContent({
36
+ children,
37
+ showCloseButton = true,
38
+ ...props
39
+ }: Omit<DialogPrimitive.Popup.Props, 'className'> & {
40
+ showCloseButton?: boolean;
41
+ }) {
42
+ return (
43
+ <DialogPortal>
44
+ <DialogOverlay />
45
+ <DialogPrimitive.Popup
46
+ data-slot="dialog-content"
47
+ className="bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-4 rounded-xl p-4 text-sm ring-1 duration-100 sm:max-w-sm fixed top-1/2 left-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 outline-none"
48
+ {...props}
49
+ >
50
+ {children}
51
+ {showCloseButton && (
52
+ <DialogPrimitive.Close
53
+ data-slot="dialog-close"
54
+ render={<Button variant="ghost" size="icon-sm" />}
55
+ className="absolute top-2 right-2"
56
+ >
57
+ <XIcon />
58
+ <span className="sr-only">Close</span>
59
+ </DialogPrimitive.Close>
60
+ )}
61
+ </DialogPrimitive.Popup>
62
+ </DialogPortal>
63
+ );
64
+ }
65
+
66
+ function DialogHeader({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
67
+ return <div data-slot="dialog-header" className="gap-2 flex flex-col" {...props} />;
68
+ }
69
+
70
+ function DialogFooter({
71
+ showCloseButton = false,
72
+ children,
73
+ ...props
74
+ }: Omit<React.ComponentProps<'div'>, 'className'> & {
75
+ showCloseButton?: boolean;
76
+ }) {
77
+ return (
78
+ <div
79
+ data-slot="dialog-footer"
80
+ className="bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"
81
+ {...props}
82
+ >
83
+ {children}
84
+ {showCloseButton && (
85
+ <DialogPrimitive.Close render={<Button variant="outline" />}>Close</DialogPrimitive.Close>
86
+ )}
87
+ </div>
88
+ );
89
+ }
90
+
91
+ function DialogTitle({ ...props }: Omit<DialogPrimitive.Title.Props, 'className'>) {
92
+ return (
93
+ <DialogPrimitive.Title
94
+ data-slot="dialog-title"
95
+ className="text-sm leading-none font-medium"
96
+ {...props}
97
+ />
98
+ );
99
+ }
100
+
101
+ function DialogDescription({ ...props }: Omit<DialogPrimitive.Description.Props, 'className'>) {
102
+ return (
103
+ <DialogPrimitive.Description
104
+ data-slot="dialog-description"
105
+ className="text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3"
106
+ {...props}
107
+ />
108
+ );
109
+ }
110
+
111
+ export {
112
+ Dialog,
113
+ DialogClose,
114
+ DialogContent,
115
+ DialogDescription,
116
+ DialogFooter,
117
+ DialogHeader,
118
+ DialogOverlay,
119
+ DialogPortal,
120
+ DialogTitle,
121
+ DialogTrigger,
122
+ };
@@ -0,0 +1,102 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { Drawer as DrawerPrimitive } from 'vaul';
5
+
6
+ function Drawer({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) {
7
+ return <DrawerPrimitive.Root data-slot="drawer" {...props} />;
8
+ }
9
+
10
+ function DrawerTrigger({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
11
+ return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
12
+ }
13
+
14
+ function DrawerPortal({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
15
+ return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
16
+ }
17
+
18
+ function DrawerClose({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Close>) {
19
+ return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
20
+ }
21
+
22
+ function DrawerOverlay({
23
+ ...props
24
+ }: Omit<React.ComponentProps<typeof DrawerPrimitive.Overlay>, 'className'>) {
25
+ return (
26
+ <DrawerPrimitive.Overlay
27
+ data-slot="drawer-overlay"
28
+ className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50"
29
+ {...props}
30
+ />
31
+ );
32
+ }
33
+
34
+ function DrawerContent({
35
+ children,
36
+ ...props
37
+ }: Omit<React.ComponentProps<typeof DrawerPrimitive.Content>, 'className'>) {
38
+ return (
39
+ <DrawerPortal data-slot="drawer-portal">
40
+ <DrawerOverlay />
41
+ <DrawerPrimitive.Content
42
+ data-slot="drawer-content"
43
+ className="bg-background flex h-auto flex-col text-sm 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-xl data-[vaul-drawer-direction=bottom]:border-t 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]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r 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]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l 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-xl data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm group/drawer-content fixed z-50"
44
+ {...props}
45
+ >
46
+ <div className="bg-muted mx-auto mt-4 hidden h-1.5 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block bg-muted mx-auto hidden shrink-0 group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
47
+ {children}
48
+ </DrawerPrimitive.Content>
49
+ </DrawerPortal>
50
+ );
51
+ }
52
+
53
+ function DrawerHeader({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
54
+ return (
55
+ <div
56
+ data-slot="drawer-header"
57
+ className="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 flex flex-col"
58
+ {...props}
59
+ />
60
+ );
61
+ }
62
+
63
+ function DrawerFooter({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
64
+ return <div data-slot="drawer-footer" className="gap-2 p-4 mt-auto flex flex-col" {...props} />;
65
+ }
66
+
67
+ function DrawerTitle({
68
+ ...props
69
+ }: Omit<React.ComponentProps<typeof DrawerPrimitive.Title>, 'className'>) {
70
+ return (
71
+ <DrawerPrimitive.Title
72
+ data-slot="drawer-title"
73
+ className="text-foreground font-medium"
74
+ {...props}
75
+ />
76
+ );
77
+ }
78
+
79
+ function DrawerDescription({
80
+ ...props
81
+ }: Omit<React.ComponentProps<typeof DrawerPrimitive.Description>, 'className'>) {
82
+ return (
83
+ <DrawerPrimitive.Description
84
+ data-slot="drawer-description"
85
+ className="text-muted-foreground text-sm"
86
+ {...props}
87
+ />
88
+ );
89
+ }
90
+
91
+ export {
92
+ Drawer,
93
+ DrawerClose,
94
+ DrawerContent,
95
+ DrawerDescription,
96
+ DrawerFooter,
97
+ DrawerHeader,
98
+ DrawerOverlay,
99
+ DrawerPortal,
100
+ DrawerTitle,
101
+ DrawerTrigger,
102
+ };