@trycompai/design-system 1.0.0 → 1.0.2

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 (101) hide show
  1. package/package.json +6 -3
  2. package/src/components/atoms/badge.tsx +49 -0
  3. package/src/components/{ui → atoms}/button.tsx +6 -1
  4. package/src/components/{ui → atoms}/checkbox.tsx +3 -3
  5. package/src/components/{ui → atoms}/heading.tsx +6 -6
  6. package/src/components/atoms/index.ts +21 -0
  7. package/src/components/atoms/kbd.tsx +21 -0
  8. package/src/components/atoms/logo.tsx +52 -0
  9. package/src/components/{ui → atoms}/slider.tsx +4 -4
  10. package/src/components/{ui → atoms}/spinner.tsx +3 -3
  11. package/src/components/atoms/stack.tsx +97 -0
  12. package/src/components/{ui → atoms}/switch.tsx +1 -1
  13. package/src/components/{ui → atoms}/text.tsx +5 -1
  14. package/src/components/{ui → atoms}/textarea.tsx +8 -2
  15. package/src/components/{ui → atoms}/toggle.tsx +3 -6
  16. package/src/components/{ui → molecules}/accordion.tsx +3 -3
  17. package/src/components/molecules/ai-chat.tsx +217 -0
  18. package/src/components/{ui → molecules}/alert.tsx +5 -5
  19. package/src/components/{ui → molecules}/breadcrumb.tsx +9 -8
  20. package/src/components/{ui → molecules}/card.tsx +24 -5
  21. package/src/components/molecules/command-search.tsx +147 -0
  22. package/src/components/molecules/empty.tsx +82 -0
  23. package/src/components/{ui → molecules}/field.tsx +16 -37
  24. package/src/components/{ui → molecules}/hover-card.tsx +2 -8
  25. package/src/components/molecules/index.ts +29 -0
  26. package/src/components/{ui → molecules}/input-group.tsx +1 -1
  27. package/src/components/molecules/input-otp.tsx +70 -0
  28. package/src/components/{ui → molecules}/item.tsx +18 -36
  29. package/src/components/molecules/page-header.tsx +80 -0
  30. package/src/components/{ui → molecules}/pagination.tsx +14 -23
  31. package/src/components/{ui → molecules}/popover.tsx +4 -2
  32. package/src/components/molecules/radio-group.tsx +33 -0
  33. package/src/components/{ui → molecules}/scroll-area.tsx +8 -11
  34. package/src/components/{ui → molecules}/section.tsx +3 -3
  35. package/src/components/{ui → molecules}/select.tsx +22 -10
  36. package/src/components/molecules/settings.tsx +169 -0
  37. package/src/components/{ui → molecules}/table.tsx +16 -3
  38. package/src/components/molecules/tabs.tsx +70 -0
  39. package/src/components/molecules/theme-switcher.tsx +176 -0
  40. package/src/components/{ui → molecules}/toggle-group.tsx +1 -1
  41. package/src/components/organisms/alert-dialog.tsx +135 -0
  42. package/src/components/organisms/app-shell.tsx +822 -0
  43. package/src/components/{ui → organisms}/calendar.tsx +6 -7
  44. package/src/components/{ui → organisms}/carousel.tsx +9 -11
  45. package/src/components/{ui → organisms}/chart.tsx +9 -24
  46. package/src/components/{ui → organisms}/combobox.tsx +7 -7
  47. package/src/components/{ui → organisms}/command.tsx +3 -3
  48. package/src/components/{ui → organisms}/context-menu.tsx +23 -53
  49. package/src/components/{ui → organisms}/dialog.tsx +3 -3
  50. package/src/components/{ui → organisms}/dropdown-menu.tsx +8 -6
  51. package/src/components/organisms/index.ts +17 -0
  52. package/src/components/{ui → organisms}/menubar.tsx +3 -3
  53. package/src/components/organisms/navigation-menu.tsx +137 -0
  54. package/src/components/organisms/page-layout.tsx +95 -0
  55. package/src/components/{ui → organisms}/sheet.tsx +7 -7
  56. package/src/components/{ui → organisms}/sidebar.tsx +61 -86
  57. package/src/components/organisms/sonner.tsx +41 -0
  58. package/src/components/ui/index.ts +3 -61
  59. package/src/fonts/TWKLausanne/TWKLausanne-300-Italic.woff +0 -0
  60. package/src/fonts/TWKLausanne/TWKLausanne-300-Italic.woff2 +0 -0
  61. package/src/fonts/TWKLausanne/TWKLausanne-300.woff +0 -0
  62. package/src/fonts/TWKLausanne/TWKLausanne-300.woff2 +0 -0
  63. package/src/fonts/TWKLausanne/TWKLausanne-350-Italic.woff +0 -0
  64. package/src/fonts/TWKLausanne/TWKLausanne-350-Italic.woff2 +0 -0
  65. package/src/fonts/TWKLausanne/TWKLausanne-350.woff +0 -0
  66. package/src/fonts/TWKLausanne/TWKLausanne-350.woff2 +0 -0
  67. package/src/fonts/TWKLausanne/TWKLausanne-400-Italic.woff +0 -0
  68. package/src/fonts/TWKLausanne/TWKLausanne-400-Italic.woff2 +0 -0
  69. package/src/fonts/TWKLausanne/TWKLausanne-400.woff +0 -0
  70. package/src/fonts/TWKLausanne/TWKLausanne-400.woff2 +0 -0
  71. package/src/fonts/TWKLausanne/TWKLausanne-700-Italic.woff +0 -0
  72. package/src/fonts/TWKLausanne/TWKLausanne-700-Italic.woff2 +0 -0
  73. package/src/fonts/TWKLausanne/TWKLausanne-700.woff +0 -0
  74. package/src/fonts/TWKLausanne/TWKLausanne-700.woff2 +0 -0
  75. package/src/styles/globals.css +167 -23
  76. package/src/components/ui/alert-dialog.tsx +0 -161
  77. package/src/components/ui/badge.tsx +0 -48
  78. package/src/components/ui/empty.tsx +0 -94
  79. package/src/components/ui/input-otp.tsx +0 -84
  80. package/src/components/ui/kbd.tsx +0 -26
  81. package/src/components/ui/navigation-menu.tsx +0 -147
  82. package/src/components/ui/page-header.tsx +0 -51
  83. package/src/components/ui/page-layout.tsx +0 -65
  84. package/src/components/ui/radio-group.tsx +0 -37
  85. package/src/components/ui/sonner.tsx +0 -43
  86. package/src/components/ui/stack.tsx +0 -72
  87. package/src/components/ui/tabs.tsx +0 -69
  88. /package/src/components/{ui → atoms}/aspect-ratio.tsx +0 -0
  89. /package/src/components/{ui → atoms}/avatar.tsx +0 -0
  90. /package/src/components/{ui → atoms}/container.tsx +0 -0
  91. /package/src/components/{ui → atoms}/input.tsx +0 -0
  92. /package/src/components/{ui → atoms}/label.tsx +0 -0
  93. /package/src/components/{ui → atoms}/progress.tsx +0 -0
  94. /package/src/components/{ui → atoms}/separator.tsx +0 -0
  95. /package/src/components/{ui → atoms}/skeleton.tsx +0 -0
  96. /package/src/components/{ui → molecules}/button-group.tsx +0 -0
  97. /package/src/components/{ui → molecules}/collapsible.tsx +0 -0
  98. /package/src/components/{ui → molecules}/grid.tsx +0 -0
  99. /package/src/components/{ui → molecules}/resizable.tsx +0 -0
  100. /package/src/components/{ui → molecules}/tooltip.tsx +0 -0
  101. /package/src/components/{ui → organisms}/drawer.tsx +0 -0
@@ -1,39 +1,120 @@
1
1
  @import 'tailwindcss';
2
2
  @import 'tw-animate-css';
3
3
 
4
+ /* Ramp font: Lausanne */
5
+ @font-face {
6
+ font-family: 'Lausanne';
7
+ src:
8
+ url('../fonts/TWKLausanne/TWKLausanne-300.woff2') format('woff2'),
9
+ url('../fonts/TWKLausanne/TWKLausanne-300.woff') format('woff');
10
+ font-weight: 300;
11
+ font-style: normal;
12
+ font-display: swap;
13
+ }
14
+ @font-face {
15
+ font-family: 'Lausanne';
16
+ src:
17
+ url('../fonts/TWKLausanne/TWKLausanne-300-Italic.woff2') format('woff2'),
18
+ url('../fonts/TWKLausanne/TWKLausanne-300-Italic.woff') format('woff');
19
+ font-weight: 300;
20
+ font-style: italic;
21
+ font-display: swap;
22
+ }
23
+ @font-face {
24
+ font-family: 'Lausanne';
25
+ src:
26
+ url('../fonts/TWKLausanne/TWKLausanne-350.woff2') format('woff2'),
27
+ url('../fonts/TWKLausanne/TWKLausanne-350.woff') format('woff');
28
+ font-weight: 350;
29
+ font-style: normal;
30
+ font-display: swap;
31
+ }
32
+ @font-face {
33
+ font-family: 'Lausanne';
34
+ src:
35
+ url('../fonts/TWKLausanne/TWKLausanne-350-Italic.woff2') format('woff2'),
36
+ url('../fonts/TWKLausanne/TWKLausanne-350-Italic.woff') format('woff');
37
+ font-weight: 350;
38
+ font-style: italic;
39
+ font-display: swap;
40
+ }
41
+ @font-face {
42
+ font-family: 'Lausanne';
43
+ src:
44
+ url('../fonts/TWKLausanne/TWKLausanne-400.woff2') format('woff2'),
45
+ url('../fonts/TWKLausanne/TWKLausanne-400.woff') format('woff');
46
+ font-weight: 400;
47
+ font-style: normal;
48
+ font-display: swap;
49
+ }
50
+ @font-face {
51
+ font-family: 'Lausanne';
52
+ src:
53
+ url('../fonts/TWKLausanne/TWKLausanne-400-Italic.woff2') format('woff2'),
54
+ url('../fonts/TWKLausanne/TWKLausanne-400-Italic.woff') format('woff');
55
+ font-weight: 400;
56
+ font-style: italic;
57
+ font-display: swap;
58
+ }
59
+ @font-face {
60
+ font-family: 'Lausanne';
61
+ src:
62
+ url('../fonts/TWKLausanne/TWKLausanne-700.woff2') format('woff2'),
63
+ url('../fonts/TWKLausanne/TWKLausanne-700.woff') format('woff');
64
+ font-weight: 700;
65
+ font-style: normal;
66
+ font-display: swap;
67
+ }
68
+ @font-face {
69
+ font-family: 'Lausanne';
70
+ src:
71
+ url('../fonts/TWKLausanne/TWKLausanne-700-Italic.woff2') format('woff2'),
72
+ url('../fonts/TWKLausanne/TWKLausanne-700-Italic.woff') format('woff');
73
+ font-weight: 700;
74
+ font-style: italic;
75
+ font-display: swap;
76
+ }
77
+
78
+ /* Include design system components in Tailwind's content scan */
79
+ @source "../components/**/*.tsx";
80
+
4
81
  @custom-variant dark (&:is(.dark *));
5
82
 
6
83
  @layer base {
7
84
  :root {
85
+ --font-sans: 'Lausanne', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
8
86
  --background: oklch(1 0 0);
9
87
  --foreground: oklch(0.145 0 0);
10
88
  --card: oklch(1 0 0);
11
89
  --card-foreground: oklch(0.145 0 0);
12
90
  --popover: oklch(1 0 0);
13
91
  --popover-foreground: oklch(0.145 0 0);
14
- --primary: oklch(0.6 0.13 163);
15
- --primary-foreground: oklch(0.98 0.02 166);
16
- --secondary: oklch(0.967 0.001 286.375);
92
+ --primary: oklch(0.596 0.145 163.225);
93
+ --primary-foreground: oklch(0.979 0.021 166.113);
94
+ --secondary: oklch(0.92 0.001 286.375);
17
95
  --secondary-foreground: oklch(0.21 0.006 285.885);
18
- --muted: oklch(0.97 0 0);
96
+ --muted: oklch(0.91 0 0);
19
97
  --muted-foreground: oklch(0.556 0 0);
20
- --accent: oklch(0.97 0 0);
98
+ --accent: oklch(0.91 0 0);
21
99
  --accent-foreground: oklch(0.205 0 0);
22
100
  --destructive: oklch(0.58 0.22 27);
101
+ --success: oklch(0.6 0.16 145);
102
+ --warning: oklch(0.75 0.15 85);
103
+ --info: oklch(0.6 0.15 250);
23
104
  --border: oklch(0.922 0 0);
24
105
  --input: oklch(0.922 0 0);
25
106
  --ring: oklch(0.708 0 0);
26
- --chart-1: oklch(0.85 0.13 165);
27
- --chart-2: oklch(0.77 0.15 163);
28
- --chart-3: oklch(0.7 0.15 162);
29
- --chart-4: oklch(0.6 0.13 163);
30
- --chart-5: oklch(0.51 0.1 166);
31
- --radius: 0.45rem;
107
+ --chart-1: oklch(0.845 0.143 164.978);
108
+ --chart-2: oklch(0.765 0.177 163.223);
109
+ --chart-3: oklch(0.696 0.17 162.48);
110
+ --chart-4: oklch(0.596 0.145 163.225);
111
+ --chart-5: oklch(0.508 0.118 165.612);
112
+ --radius: 0.3rem;
32
113
  --sidebar: oklch(0.985 0 0);
33
114
  --sidebar-foreground: oklch(0.145 0 0);
34
- --sidebar-primary: oklch(0.6 0.13 163);
35
- --sidebar-primary-foreground: oklch(0.98 0.02 166);
36
- --sidebar-accent: oklch(0.97 0 0);
115
+ --sidebar-primary: oklch(0.596 0.145 163.225);
116
+ --sidebar-primary-foreground: oklch(0.979 0.021 166.113);
117
+ --sidebar-accent: oklch(0.91 0 0);
37
118
  --sidebar-accent-foreground: oklch(0.205 0 0);
38
119
  --sidebar-border: oklch(0.922 0 0);
39
120
  --sidebar-ring: oklch(0.708 0 0);
@@ -45,8 +126,8 @@
45
126
  --card-foreground: oklch(0.985 0 0);
46
127
  --popover: oklch(0.205 0 0);
47
128
  --popover-foreground: oklch(0.985 0 0);
48
- --primary: oklch(0.7 0.15 162);
49
- --primary-foreground: oklch(0.26 0.05 173);
129
+ --primary: oklch(0.696 0.17 162.48);
130
+ --primary-foreground: oklch(0.262 0.051 172.552);
50
131
  --secondary: oklch(0.274 0.006 286.033);
51
132
  --secondary-foreground: oklch(0.985 0 0);
52
133
  --muted: oklch(0.269 0 0);
@@ -54,18 +135,21 @@
54
135
  --accent: oklch(0.371 0 0);
55
136
  --accent-foreground: oklch(0.985 0 0);
56
137
  --destructive: oklch(0.704 0.191 22.216);
138
+ --success: oklch(0.7 0.16 145);
139
+ --warning: oklch(0.8 0.15 85);
140
+ --info: oklch(0.7 0.15 250);
57
141
  --border: oklch(1 0 0 / 10%);
58
142
  --input: oklch(1 0 0 / 15%);
59
143
  --ring: oklch(0.556 0 0);
60
- --chart-1: oklch(0.85 0.13 165);
61
- --chart-2: oklch(0.77 0.15 163);
62
- --chart-3: oklch(0.7 0.15 162);
63
- --chart-4: oklch(0.6 0.13 163);
64
- --chart-5: oklch(0.51 0.1 166);
144
+ --chart-1: oklch(0.845 0.143 164.978);
145
+ --chart-2: oklch(0.765 0.177 163.223);
146
+ --chart-3: oklch(0.696 0.17 162.48);
147
+ --chart-4: oklch(0.596 0.145 163.225);
148
+ --chart-5: oklch(0.508 0.118 165.612);
65
149
  --sidebar: oklch(0.205 0 0);
66
150
  --sidebar-foreground: oklch(0.985 0 0);
67
- --sidebar-primary: oklch(0.77 0.15 163);
68
- --sidebar-primary-foreground: oklch(0.26 0.05 173);
151
+ --sidebar-primary: oklch(0.696 0.17 162.48);
152
+ --sidebar-primary-foreground: oklch(0.262 0.051 172.552);
69
153
  --sidebar-accent: oklch(0.269 0 0);
70
154
  --sidebar-accent-foreground: oklch(0.985 0 0);
71
155
  --sidebar-border: oklch(1 0 0 / 10%);
@@ -74,6 +158,7 @@
74
158
  }
75
159
 
76
160
  @theme inline {
161
+ --font-sans: 'Lausanne', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
77
162
  --color-background: var(--background);
78
163
  --color-foreground: var(--foreground);
79
164
  --color-card: var(--card);
@@ -90,6 +175,9 @@
90
175
  --color-accent-foreground: var(--accent-foreground);
91
176
  --color-destructive: var(--destructive);
92
177
  --color-destructive-foreground: var(--destructive-foreground);
178
+ --color-success: var(--success);
179
+ --color-warning: var(--warning);
180
+ --color-info: var(--info);
93
181
  --color-border: var(--border);
94
182
  --color-input: var(--input);
95
183
  --color-ring: var(--ring);
@@ -116,7 +204,63 @@
116
204
  * {
117
205
  @apply border-border outline-ring/50;
118
206
  }
207
+ html {
208
+ font-family: var(--font-sans);
209
+ }
119
210
  body {
120
211
  @apply bg-background text-foreground;
212
+ font-family: var(--font-sans);
213
+ }
214
+ }
215
+
216
+ /* Lausanne-only weight mapping.
217
+ We DO NOT have 500/600 files, so make Tailwind's common semantic weights resolve to real faces. */
218
+ @layer utilities {
219
+ .font-normal {
220
+ font-weight: 350;
221
+ }
222
+ .font-medium {
223
+ font-weight: 400;
224
+ }
225
+ .font-semibold {
226
+ font-weight: 700;
227
+ }
228
+ }
229
+
230
+ /* View Transitions API for smooth page transitions */
231
+ @view-transition {
232
+ navigation: auto;
233
+ }
234
+
235
+ ::view-transition-old(page-content) {
236
+ animation: fade-out 250ms ease-out forwards;
237
+ }
238
+
239
+ ::view-transition-new(page-content) {
240
+ animation: fade-in 250ms ease-out forwards;
241
+ }
242
+
243
+ @keyframes fade-out {
244
+ from { opacity: 1; }
245
+ to { opacity: 0; }
246
+ }
247
+
248
+ @keyframes fade-in {
249
+ from { opacity: 0; }
250
+ to { opacity: 1; }
251
+ }
252
+
253
+ /* Page content animation fallback for non-View Transitions browsers */
254
+ [data-slot="page-layout"] {
255
+ view-transition-name: page-content;
256
+ animation: page-enter 250ms ease-out;
257
+ }
258
+
259
+ @keyframes page-enter {
260
+ from {
261
+ opacity: 0;
262
+ }
263
+ to {
264
+ opacity: 1;
121
265
  }
122
266
  }
@@ -1,161 +0,0 @@
1
- import { AlertDialog as AlertDialogPrimitive } from '@base-ui/react/alert-dialog';
2
- import * as React from 'react';
3
-
4
- import { cn } from '../../../lib/utils';
5
- import { Button } from './button';
6
-
7
- function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
8
- return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
9
- }
10
-
11
- function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
12
- return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />;
13
- }
14
-
15
- function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
16
- return <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />;
17
- }
18
-
19
- function AlertDialogOverlay({ className, ...props }: AlertDialogPrimitive.Backdrop.Props) {
20
- return (
21
- <AlertDialogPrimitive.Backdrop
22
- data-slot="alert-dialog-overlay"
23
- className={cn(
24
- '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',
25
- className,
26
- )}
27
- {...props}
28
- />
29
- );
30
- }
31
-
32
- function AlertDialogContent({
33
- className,
34
- size = 'default',
35
- ...props
36
- }: AlertDialogPrimitive.Popup.Props & {
37
- size?: 'default' | 'sm';
38
- }) {
39
- return (
40
- <AlertDialogPortal>
41
- <AlertDialogOverlay />
42
- <AlertDialogPrimitive.Popup
43
- data-slot="alert-dialog-content"
44
- data-size={size}
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 bg-background ring-foreground/10 gap-4 rounded-xl p-4 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none',
47
- className,
48
- )}
49
- {...props}
50
- />
51
- </AlertDialogPortal>
52
- );
53
- }
54
-
55
- function AlertDialogHeader({ className, ...props }: React.ComponentProps<'div'>) {
56
- return (
57
- <div
58
- data-slot="alert-dialog-header"
59
- className={cn(
60
- 'grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]',
61
- className,
62
- )}
63
- {...props}
64
- />
65
- );
66
- }
67
-
68
- function AlertDialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
69
- return (
70
- <div
71
- data-slot="alert-dialog-footer"
72
- className={cn(
73
- 'bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end',
74
- className,
75
- )}
76
- {...props}
77
- />
78
- );
79
- }
80
-
81
- function AlertDialogMedia({ className, ...props }: React.ComponentProps<'div'>) {
82
- return (
83
- <div
84
- data-slot="alert-dialog-media"
85
- className={cn(
86
- "bg-muted mb-2 inline-flex size-10 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
87
- className,
88
- )}
89
- {...props}
90
- />
91
- );
92
- }
93
-
94
- function AlertDialogTitle({
95
- className,
96
- ...props
97
- }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
98
- return (
99
- <AlertDialogPrimitive.Title
100
- data-slot="alert-dialog-title"
101
- className={cn(
102
- 'text-sm font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2',
103
- className,
104
- )}
105
- {...props}
106
- />
107
- );
108
- }
109
-
110
- function AlertDialogDescription({
111
- className,
112
- ...props
113
- }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
114
- return (
115
- <AlertDialogPrimitive.Description
116
- data-slot="alert-dialog-description"
117
- className={cn(
118
- 'text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3',
119
- className,
120
- )}
121
- {...props}
122
- />
123
- );
124
- }
125
-
126
- function AlertDialogAction({
127
- variant = 'default',
128
- ...props
129
- }: Omit<React.ComponentProps<typeof Button>, 'className'>) {
130
- return <Button data-slot="alert-dialog-action" variant={variant} {...props} />;
131
- }
132
-
133
- function AlertDialogCancel({
134
- variant = 'secondary',
135
- size = 'default',
136
- ...props
137
- }: Omit<AlertDialogPrimitive.Close.Props, 'className'> &
138
- Pick<React.ComponentProps<typeof Button>, 'variant' | 'size'>) {
139
- return (
140
- <AlertDialogPrimitive.Close
141
- data-slot="alert-dialog-cancel"
142
- render={<Button variant={variant} size={size} />}
143
- {...props}
144
- />
145
- );
146
- }
147
-
148
- export {
149
- AlertDialog,
150
- AlertDialogAction,
151
- AlertDialogCancel,
152
- AlertDialogContent,
153
- AlertDialogDescription,
154
- AlertDialogFooter,
155
- AlertDialogHeader,
156
- AlertDialogMedia,
157
- AlertDialogOverlay,
158
- AlertDialogPortal,
159
- AlertDialogTitle,
160
- AlertDialogTrigger,
161
- };
@@ -1,48 +0,0 @@
1
- import { mergeProps } from '@base-ui/react/merge-props';
2
- import { useRender } from '@base-ui/react/use-render';
3
- import { cva, type VariantProps } from 'class-variance-authority';
4
-
5
- const badgeVariants = cva(
6
- 'h-5 gap-1 rounded-4xl border px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge',
7
- {
8
- variants: {
9
- variant: {
10
- default: 'border-transparent bg-primary text-primary-foreground [a]:hover:bg-primary/80',
11
- secondary:
12
- 'border-transparent bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80',
13
- destructive:
14
- 'border-transparent bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20',
15
- outline:
16
- 'border-border bg-transparent text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',
17
- ghost:
18
- 'border-transparent bg-transparent hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50',
19
- link: 'border-transparent bg-transparent text-primary underline-offset-4 hover:underline',
20
- },
21
- },
22
- defaultVariants: {
23
- variant: 'default',
24
- },
25
- },
26
- );
27
-
28
- type BadgeProps = Omit<useRender.ComponentProps<'span'>, 'className'> &
29
- VariantProps<typeof badgeVariants>;
30
-
31
- function Badge({ variant = 'default', render, ...props }: BadgeProps) {
32
- return useRender({
33
- defaultTagName: 'span',
34
- props: mergeProps<'span'>(
35
- {
36
- className: badgeVariants({ variant }),
37
- },
38
- props,
39
- ),
40
- render,
41
- state: {
42
- slot: 'badge',
43
- variant,
44
- },
45
- });
46
- }
47
-
48
- export { Badge, badgeVariants };
@@ -1,94 +0,0 @@
1
- import { cva, type VariantProps } from 'class-variance-authority';
2
-
3
- import { cn } from '../../../lib/utils';
4
-
5
- function Empty({ className, ...props }: React.ComponentProps<'div'>) {
6
- return (
7
- <div
8
- data-slot="empty"
9
- className={cn(
10
- 'gap-4 rounded-lg border-dashed p-12 flex w-full min-w-0 flex-1 flex-col items-center justify-center text-center text-balance',
11
- className,
12
- )}
13
- {...props}
14
- />
15
- );
16
- }
17
-
18
- function EmptyHeader({ className, ...props }: React.ComponentProps<'div'>) {
19
- return (
20
- <div
21
- data-slot="empty-header"
22
- className={cn('gap-2 flex max-w-sm flex-col items-center', className)}
23
- {...props}
24
- />
25
- );
26
- }
27
-
28
- const emptyMediaVariants = cva(
29
- 'mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0',
30
- {
31
- variants: {
32
- variant: {
33
- default: 'bg-transparent',
34
- icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
35
- },
36
- },
37
- defaultVariants: {
38
- variant: 'default',
39
- },
40
- },
41
- );
42
-
43
- function EmptyMedia({
44
- className,
45
- variant = 'default',
46
- ...props
47
- }: React.ComponentProps<'div'> & VariantProps<typeof emptyMediaVariants>) {
48
- return (
49
- <div
50
- data-slot="empty-icon"
51
- data-variant={variant}
52
- className={cn(emptyMediaVariants({ variant, className }))}
53
- {...props}
54
- />
55
- );
56
- }
57
-
58
- function EmptyTitle({ className, ...props }: React.ComponentProps<'div'>) {
59
- return (
60
- <div
61
- data-slot="empty-title"
62
- className={cn('text-lg font-medium tracking-tight', className)}
63
- {...props}
64
- />
65
- );
66
- }
67
-
68
- function EmptyDescription({ className, ...props }: React.ComponentProps<'p'>) {
69
- return (
70
- <div
71
- data-slot="empty-description"
72
- className={cn(
73
- 'text-sm/relaxed text-muted-foreground [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',
74
- className,
75
- )}
76
- {...props}
77
- />
78
- );
79
- }
80
-
81
- function EmptyContent({ className, ...props }: React.ComponentProps<'div'>) {
82
- return (
83
- <div
84
- data-slot="empty-content"
85
- className={cn(
86
- 'gap-4 text-sm flex w-full max-w-sm min-w-0 flex-col items-center text-balance',
87
- className,
88
- )}
89
- {...props}
90
- />
91
- );
92
- }
93
-
94
- export { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle };
@@ -1,84 +0,0 @@
1
- import { OTPInput, OTPInputContext } from 'input-otp';
2
- import * as React from 'react';
3
-
4
- import { MinusIcon } from 'lucide-react';
5
- import { cn } from '../../../lib/utils';
6
-
7
- function InputOTP({
8
- className,
9
- containerClassName,
10
- ...props
11
- }: React.ComponentProps<typeof OTPInput> & {
12
- containerClassName?: string;
13
- }) {
14
- return (
15
- <OTPInput
16
- data-slot="input-otp"
17
- containerClassName={cn(
18
- 'cn-input-otp flex items-center has-disabled:opacity-50',
19
- containerClassName,
20
- )}
21
- spellCheck={false}
22
- className={cn('disabled:cursor-not-allowed', className)}
23
- {...props}
24
- />
25
- );
26
- }
27
-
28
- function InputOTPGroup({ className, ...props }: React.ComponentProps<'div'>) {
29
- return (
30
- <div
31
- data-slot="input-otp-group"
32
- className={cn(
33
- 'has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive rounded-md has-aria-invalid:ring-[3px] flex items-center',
34
- className,
35
- )}
36
- {...props}
37
- />
38
- );
39
- }
40
-
41
- function InputOTPSlot({
42
- index,
43
- className,
44
- ...props
45
- }: React.ComponentProps<'div'> & {
46
- index: number;
47
- }) {
48
- const inputOTPContext = React.useContext(OTPInputContext);
49
- const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
50
-
51
- return (
52
- <div
53
- data-slot="input-otp-slot"
54
- data-active={isActive}
55
- className={cn(
56
- 'dark:bg-input/30 border-input data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive size-9 border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:ring-[3px] relative flex items-center justify-center data-[active=true]:z-10',
57
- className,
58
- )}
59
- {...props}
60
- >
61
- {char}
62
- {hasFakeCaret && (
63
- <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
64
- <div className="animate-caret-blink bg-foreground h-4 w-px duration-1000 bg-foreground h-4 w-px" />
65
- </div>
66
- )}
67
- </div>
68
- );
69
- }
70
-
71
- function InputOTPSeparator({ ...props }: React.ComponentProps<'div'>) {
72
- return (
73
- <div
74
- data-slot="input-otp-separator"
75
- className="[&_svg:not([class*='size-'])]:size-4 flex items-center"
76
- role="separator"
77
- {...props}
78
- >
79
- <MinusIcon />
80
- </div>
81
- );
82
- }
83
-
84
- export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot };
@@ -1,26 +0,0 @@
1
- import { cn } from '../../../lib/utils';
2
-
3
- function Kbd({ className, ...props }: React.ComponentProps<'kbd'>) {
4
- return (
5
- <kbd
6
- data-slot="kbd"
7
- className={cn(
8
- "bg-muted text-muted-foreground [[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10 h-5 w-fit min-w-5 gap-1 rounded-sm px-1 font-sans text-xs font-medium [&_svg:not([class*='size-'])]:size-3 pointer-events-none inline-flex items-center justify-center select-none",
9
- className,
10
- )}
11
- {...props}
12
- />
13
- );
14
- }
15
-
16
- function KbdGroup({ className, ...props }: React.ComponentProps<'div'>) {
17
- return (
18
- <kbd
19
- data-slot="kbd-group"
20
- className={cn('gap-1 inline-flex items-center', className)}
21
- {...props}
22
- />
23
- );
24
- }
25
-
26
- export { Kbd, KbdGroup };