@trycompai/design-system 1.0.0 → 1.0.1

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 (72) hide show
  1. package/package.json +2 -2
  2. package/src/components/atoms/index.ts +19 -0
  3. package/src/components/atoms/kbd.tsx +21 -0
  4. package/src/components/{ui → atoms}/slider.tsx +4 -4
  5. package/src/components/{ui → atoms}/textarea.tsx +8 -2
  6. package/src/components/{ui → atoms}/toggle.tsx +2 -5
  7. package/src/components/{ui → molecules}/breadcrumb.tsx +1 -1
  8. package/src/components/molecules/empty.tsx +82 -0
  9. package/src/components/{ui → molecules}/field.tsx +16 -37
  10. package/src/components/{ui → molecules}/hover-card.tsx +2 -8
  11. package/src/components/molecules/index.ts +26 -0
  12. package/src/components/{ui → molecules}/input-group.tsx +1 -1
  13. package/src/components/molecules/input-otp.tsx +70 -0
  14. package/src/components/{ui → molecules}/item.tsx +18 -36
  15. package/src/components/{ui → molecules}/page-header.tsx +2 -2
  16. package/src/components/{ui → molecules}/pagination.tsx +10 -19
  17. package/src/components/{ui → molecules}/radio-group.tsx +4 -8
  18. package/src/components/{ui → molecules}/scroll-area.tsx +8 -11
  19. package/src/components/{ui → molecules}/section.tsx +2 -2
  20. package/src/components/{ui → molecules}/select.tsx +17 -5
  21. package/src/components/{ui → molecules}/table.tsx +11 -2
  22. package/src/components/{ui → molecules}/toggle-group.tsx +1 -1
  23. package/src/components/organisms/alert-dialog.tsx +135 -0
  24. package/src/components/{ui → organisms}/calendar.tsx +2 -3
  25. package/src/components/{ui → organisms}/carousel.tsx +6 -8
  26. package/src/components/{ui → organisms}/chart.tsx +9 -24
  27. package/src/components/{ui → organisms}/combobox.tsx +2 -2
  28. package/src/components/{ui → organisms}/context-menu.tsx +19 -49
  29. package/src/components/{ui → organisms}/dialog.tsx +1 -1
  30. package/src/components/organisms/index.ts +16 -0
  31. package/src/components/organisms/navigation-menu.tsx +137 -0
  32. package/src/components/{ui → organisms}/sheet.tsx +6 -6
  33. package/src/components/{ui → organisms}/sidebar.tsx +42 -83
  34. package/src/components/{ui → organisms}/sonner.tsx +7 -9
  35. package/src/components/ui/index.ts +3 -61
  36. package/src/styles/globals.css +12 -0
  37. package/src/components/ui/alert-dialog.tsx +0 -161
  38. package/src/components/ui/empty.tsx +0 -94
  39. package/src/components/ui/input-otp.tsx +0 -84
  40. package/src/components/ui/kbd.tsx +0 -26
  41. package/src/components/ui/navigation-menu.tsx +0 -147
  42. /package/src/components/{ui → atoms}/aspect-ratio.tsx +0 -0
  43. /package/src/components/{ui → atoms}/avatar.tsx +0 -0
  44. /package/src/components/{ui → atoms}/badge.tsx +0 -0
  45. /package/src/components/{ui → atoms}/button.tsx +0 -0
  46. /package/src/components/{ui → atoms}/checkbox.tsx +0 -0
  47. /package/src/components/{ui → atoms}/container.tsx +0 -0
  48. /package/src/components/{ui → atoms}/heading.tsx +0 -0
  49. /package/src/components/{ui → atoms}/input.tsx +0 -0
  50. /package/src/components/{ui → atoms}/label.tsx +0 -0
  51. /package/src/components/{ui → atoms}/progress.tsx +0 -0
  52. /package/src/components/{ui → atoms}/separator.tsx +0 -0
  53. /package/src/components/{ui → atoms}/skeleton.tsx +0 -0
  54. /package/src/components/{ui → atoms}/spinner.tsx +0 -0
  55. /package/src/components/{ui → atoms}/switch.tsx +0 -0
  56. /package/src/components/{ui → atoms}/text.tsx +0 -0
  57. /package/src/components/{ui → molecules}/accordion.tsx +0 -0
  58. /package/src/components/{ui → molecules}/alert.tsx +0 -0
  59. /package/src/components/{ui → molecules}/button-group.tsx +0 -0
  60. /package/src/components/{ui → molecules}/card.tsx +0 -0
  61. /package/src/components/{ui → molecules}/collapsible.tsx +0 -0
  62. /package/src/components/{ui → molecules}/grid.tsx +0 -0
  63. /package/src/components/{ui → molecules}/popover.tsx +0 -0
  64. /package/src/components/{ui → molecules}/resizable.tsx +0 -0
  65. /package/src/components/{ui → molecules}/stack.tsx +0 -0
  66. /package/src/components/{ui → molecules}/tabs.tsx +0 -0
  67. /package/src/components/{ui → molecules}/tooltip.tsx +0 -0
  68. /package/src/components/{ui → organisms}/command.tsx +0 -0
  69. /package/src/components/{ui → organisms}/drawer.tsx +0 -0
  70. /package/src/components/{ui → organisms}/dropdown-menu.tsx +0 -0
  71. /package/src/components/{ui → organisms}/menubar.tsx +0 -0
  72. /package/src/components/{ui → organisms}/page-layout.tsx +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trycompai/design-system",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Design system for Comp AI - shadcn-style components with Tailwind CSS",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -48,7 +48,7 @@
48
48
  "repository": {
49
49
  "type": "git",
50
50
  "url": "git+https://github.com/trycompai/comp.git",
51
- "directory": "packages/ui-shadcn"
51
+ "directory": "packages/design-system"
52
52
  },
53
53
  "license": "MIT",
54
54
  "keywords": [
@@ -0,0 +1,19 @@
1
+ export * from './aspect-ratio';
2
+ export * from './avatar';
3
+ export * from './badge';
4
+ export * from './button';
5
+ export * from './checkbox';
6
+ export * from './container';
7
+ export * from './heading';
8
+ export * from './input';
9
+ export * from './kbd';
10
+ export * from './label';
11
+ export * from './progress';
12
+ export * from './separator';
13
+ export * from './skeleton';
14
+ export * from './slider';
15
+ export * from './spinner';
16
+ export * from './switch';
17
+ export * from './text';
18
+ export * from './textarea';
19
+ export * from './toggle';
@@ -0,0 +1,21 @@
1
+ function Kbd({ ...props }: Omit<React.ComponentProps<'kbd'>, 'className'>) {
2
+ return (
3
+ <kbd
4
+ data-slot="kbd"
5
+ className="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"
6
+ {...props}
7
+ />
8
+ );
9
+ }
10
+
11
+ function KbdGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
12
+ return (
13
+ <kbd
14
+ data-slot="kbd-group"
15
+ className="gap-1 inline-flex items-center"
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ export { Kbd, KbdGroup };
@@ -17,7 +17,7 @@ function Slider({
17
17
 
18
18
  return (
19
19
  <SliderPrimitive.Root
20
- className="data-horizontal:w-full data-vertical:h-full"
20
+ className="data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full"
21
21
  data-slot="slider"
22
22
  defaultValue={defaultValue}
23
23
  value={value}
@@ -26,14 +26,14 @@ function Slider({
26
26
  thumbAlignment="edge"
27
27
  {...props}
28
28
  >
29
- <SliderPrimitive.Control className="data-vertical:min-h-40 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:w-auto data-vertical:flex-col">
29
+ <SliderPrimitive.Control className="data-[orientation=vertical]:min-h-40 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col">
30
30
  <SliderPrimitive.Track
31
31
  data-slot="slider-track"
32
- className="bg-muted rounded-full data-horizontal:h-1.5 data-horizontal:w-full data-vertical:h-full data-vertical:w-1.5 relative overflow-hidden select-none"
32
+ className="bg-border rounded-full h-1.5 w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5 relative overflow-hidden select-none"
33
33
  >
34
34
  <SliderPrimitive.Indicator
35
35
  data-slot="slider-range"
36
- className="bg-primary select-none data-horizontal:h-full data-vertical:w-full"
36
+ className="bg-primary select-none h-full data-[orientation=vertical]:w-full"
37
37
  />
38
38
  </SliderPrimitive.Track>
39
39
  {Array.from({ length: _values.length }, (_, index) => (
@@ -1,10 +1,16 @@
1
1
  import * as React from 'react';
2
2
 
3
- function Textarea({ ...props }: Omit<React.ComponentProps<'textarea'>, 'className'>) {
3
+ function Textarea({
4
+ size = 'default',
5
+ ...props
6
+ }: Omit<React.ComponentProps<'textarea'>, 'className'> & {
7
+ size?: 'sm' | 'default' | 'lg' | 'full';
8
+ }) {
4
9
  return (
5
10
  <textarea
6
11
  data-slot="textarea"
7
- className="border-input dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 rounded-lg border bg-transparent px-2.5 py-2 text-base transition-colors focus-visible:ring-[3px] aria-invalid:ring-[3px] md:text-sm placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50"
12
+ data-size={size}
13
+ className="border-input dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 rounded-lg border bg-transparent px-2.5 py-2 text-base transition-colors focus-visible:ring-[3px] aria-invalid:ring-[3px] md:text-sm placeholder:text-muted-foreground flex field-sizing-content min-h-16 outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[size=sm]:w-xs data-[size=default]:w-md data-[size=lg]:w-xl data-[size=full]:w-full"
8
14
  {...props}
9
15
  />
10
16
  );
@@ -1,8 +1,6 @@
1
1
  import { Toggle as TogglePrimitive } from '@base-ui/react/toggle';
2
2
  import { cva, type VariantProps } from 'class-variance-authority';
3
3
 
4
- import { cn } from '../../../lib/utils';
5
-
6
4
  const toggleVariants = cva(
7
5
  "hover:text-foreground aria-pressed:bg-muted focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive gap-1 rounded-md text-sm font-medium transition-[color,box-shadow] [&_svg:not([class*='size-'])]:size-4 group/toggle hover:bg-muted inline-flex items-center justify-center whitespace-nowrap outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
8
6
  {
@@ -25,15 +23,14 @@ const toggleVariants = cva(
25
23
  );
26
24
 
27
25
  function Toggle({
28
- className,
29
26
  variant = 'default',
30
27
  size = 'default',
31
28
  ...props
32
- }: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
29
+ }: Omit<TogglePrimitive.Props, 'className'> & VariantProps<typeof toggleVariants>) {
33
30
  return (
34
31
  <TogglePrimitive
35
32
  data-slot="toggle"
36
- className={cn(toggleVariants({ variant, size, className }))}
33
+ className={toggleVariants({ variant, size })}
37
34
  {...props}
38
35
  />
39
36
  );
@@ -8,7 +8,7 @@ import {
8
8
  DropdownMenuContent,
9
9
  DropdownMenuItem,
10
10
  DropdownMenuTrigger,
11
- } from './dropdown-menu';
11
+ } from '../organisms/dropdown-menu';
12
12
 
13
13
  interface BreadcrumbItemData {
14
14
  /** The text label for the breadcrumb item */
@@ -0,0 +1,82 @@
1
+ import { cva, type VariantProps } from 'class-variance-authority';
2
+
3
+ function Empty({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
4
+ return (
5
+ <div
6
+ data-slot="empty"
7
+ className="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"
8
+ {...props}
9
+ />
10
+ );
11
+ }
12
+
13
+ function EmptyHeader({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
14
+ return (
15
+ <div
16
+ data-slot="empty-header"
17
+ className="gap-2 flex max-w-sm flex-col items-center"
18
+ {...props}
19
+ />
20
+ );
21
+ }
22
+
23
+ const emptyMediaVariants = cva(
24
+ 'mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0',
25
+ {
26
+ variants: {
27
+ variant: {
28
+ default: 'bg-transparent',
29
+ icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
30
+ },
31
+ },
32
+ defaultVariants: {
33
+ variant: 'default',
34
+ },
35
+ },
36
+ );
37
+
38
+ function EmptyMedia({
39
+ variant = 'default',
40
+ ...props
41
+ }: Omit<React.ComponentProps<'div'>, 'className'> & VariantProps<typeof emptyMediaVariants>) {
42
+ return (
43
+ <div
44
+ data-slot="empty-icon"
45
+ data-variant={variant}
46
+ className={emptyMediaVariants({ variant })}
47
+ {...props}
48
+ />
49
+ );
50
+ }
51
+
52
+ function EmptyTitle({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
53
+ return (
54
+ <div
55
+ data-slot="empty-title"
56
+ className="text-lg font-medium tracking-tight"
57
+ {...props}
58
+ />
59
+ );
60
+ }
61
+
62
+ function EmptyDescription({ ...props }: Omit<React.ComponentProps<'p'>, 'className'>) {
63
+ return (
64
+ <div
65
+ data-slot="empty-description"
66
+ className="text-sm/relaxed text-muted-foreground [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4"
67
+ {...props}
68
+ />
69
+ );
70
+ }
71
+
72
+ function EmptyContent({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
73
+ return (
74
+ <div
75
+ data-slot="empty-content"
76
+ className="gap-4 text-sm flex w-full max-w-sm min-w-0 flex-col items-center text-balance"
77
+ {...props}
78
+ />
79
+ );
80
+ }
81
+
82
+ export { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle };
@@ -4,47 +4,36 @@ import { cva, type VariantProps } from 'class-variance-authority';
4
4
  import { useMemo } from 'react';
5
5
 
6
6
  import { Separator as SeparatorPrimitive } from '@base-ui/react/separator';
7
- import { cn } from '../../../lib/utils';
8
7
 
9
- function FieldSet({ className, ...props }: React.ComponentProps<'fieldset'>) {
8
+ function FieldSet({ ...props }: Omit<React.ComponentProps<'fieldset'>, 'className'>) {
10
9
  return (
11
10
  <fieldset
12
11
  data-slot="field-set"
13
- className={cn(
14
- 'gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col',
15
- className,
16
- )}
12
+ className="gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col"
17
13
  {...props}
18
14
  />
19
15
  );
20
16
  }
21
17
 
22
18
  function FieldLegend({
23
- className,
24
19
  variant = 'legend',
25
20
  ...props
26
- }: React.ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {
21
+ }: Omit<React.ComponentProps<'legend'>, 'className'> & { variant?: 'legend' | 'label' }) {
27
22
  return (
28
23
  <legend
29
24
  data-slot="field-legend"
30
25
  data-variant={variant}
31
- className={cn(
32
- 'mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base',
33
- className,
34
- )}
26
+ className="mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base"
35
27
  {...props}
36
28
  />
37
29
  );
38
30
  }
39
31
 
40
- function FieldGroup({ className, ...props }: React.ComponentProps<'div'>) {
32
+ function FieldGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
41
33
  return (
42
34
  <div
43
35
  data-slot="field-group"
44
- className={cn(
45
- 'gap-5 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4 group/field-group @container/field-group flex w-full flex-col',
46
- className,
47
- )}
36
+ className="gap-5 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4 group/field-group @container/field-group flex w-full flex-col"
48
37
  {...props}
49
38
  />
50
39
  );
@@ -66,26 +55,25 @@ const fieldVariants = cva('data-[invalid=true]:text-destructive gap-2 group/fiel
66
55
  });
67
56
 
68
57
  function Field({
69
- className,
70
58
  orientation = 'vertical',
71
59
  ...props
72
- }: React.ComponentProps<'div'> & VariantProps<typeof fieldVariants>) {
60
+ }: Omit<React.ComponentProps<'div'>, 'className'> & VariantProps<typeof fieldVariants>) {
73
61
  return (
74
62
  <div
75
63
  role="group"
76
64
  data-slot="field"
77
65
  data-orientation={orientation}
78
- className={cn(fieldVariants({ orientation }), className)}
66
+ className={fieldVariants({ orientation })}
79
67
  {...props}
80
68
  />
81
69
  );
82
70
  }
83
71
 
84
- function FieldContent({ className, ...props }: React.ComponentProps<'div'>) {
72
+ function FieldContent({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
85
73
  return (
86
74
  <div
87
75
  data-slot="field-content"
88
- className={cn('gap-0.5 group/field-content flex flex-1 flex-col leading-snug', className)}
76
+ className="gap-0.5 group/field-content flex flex-1 flex-col leading-snug"
89
77
  {...props}
90
78
  />
91
79
  );
@@ -101,29 +89,21 @@ function FieldLabel({ ...props }: Omit<React.ComponentProps<'label'>, 'className
101
89
  );
102
90
  }
103
91
 
104
- function FieldTitle({ className, ...props }: React.ComponentProps<'div'>) {
92
+ function FieldTitle({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
105
93
  return (
106
94
  <div
107
95
  data-slot="field-label"
108
- className={cn(
109
- 'gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50 flex w-fit items-center leading-snug',
110
- className,
111
- )}
96
+ className="gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50 flex w-fit items-center leading-snug"
112
97
  {...props}
113
98
  />
114
99
  );
115
100
  }
116
101
 
117
- function FieldDescription({ className, ...props }: React.ComponentProps<'p'>) {
102
+ function FieldDescription({ ...props }: Omit<React.ComponentProps<'p'>, 'className'>) {
118
103
  return (
119
104
  <p
120
105
  data-slot="field-description"
121
- className={cn(
122
- 'text-muted-foreground text-left text-sm [[data-variant=legend]+&]:-mt-1.5 leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance',
123
- 'last:mt-0 nth-last-2:-mt-1',
124
- '[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',
125
- className,
126
- )}
106
+ className="text-muted-foreground text-left text-sm [[data-variant=legend]+&]:-mt-1.5 leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance last:mt-0 nth-last-2:-mt-1 [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4"
127
107
  {...props}
128
108
  />
129
109
  );
@@ -156,11 +136,10 @@ function FieldSeparator({
156
136
  }
157
137
 
158
138
  function FieldError({
159
- className,
160
139
  children,
161
140
  errors,
162
141
  ...props
163
- }: React.ComponentProps<'div'> & {
142
+ }: Omit<React.ComponentProps<'div'>, 'className'> & {
164
143
  errors?: Array<{ message?: string } | undefined>;
165
144
  }) {
166
145
  const content = useMemo(() => {
@@ -193,7 +172,7 @@ function FieldError({
193
172
  <div
194
173
  role="alert"
195
174
  data-slot="field-error"
196
- className={cn('text-destructive text-sm font-normal', className)}
175
+ className="text-destructive text-sm font-normal"
197
176
  {...props}
198
177
  >
199
178
  {content}
@@ -2,8 +2,6 @@
2
2
 
3
3
  import { PreviewCard as PreviewCardPrimitive } from '@base-ui/react/preview-card';
4
4
 
5
- import { cn } from '../../../lib/utils';
6
-
7
5
  function HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) {
8
6
  return <PreviewCardPrimitive.Root data-slot="hover-card" {...props} />;
9
7
  }
@@ -13,13 +11,12 @@ function HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {
13
11
  }
14
12
 
15
13
  function HoverCardContent({
16
- className,
17
14
  side = 'bottom',
18
15
  sideOffset = 4,
19
16
  align = 'center',
20
17
  alignOffset = 4,
21
18
  ...props
22
- }: PreviewCardPrimitive.Popup.Props &
19
+ }: Omit<PreviewCardPrimitive.Popup.Props, 'className'> &
23
20
  Pick<PreviewCardPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {
24
21
  return (
25
22
  <PreviewCardPrimitive.Portal data-slot="hover-card-portal">
@@ -32,10 +29,7 @@ function HoverCardContent({
32
29
  >
33
30
  <PreviewCardPrimitive.Popup
34
31
  data-slot="hover-card-content"
35
- className={cn(
36
- '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 w-64 rounded-lg p-4 text-sm shadow-md ring-1 duration-100 z-50 origin-(--transform-origin) outline-hidden',
37
- className,
38
- )}
32
+ 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 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 w-64 rounded-lg p-4 text-sm shadow-md ring-1 duration-100 z-50 origin-(--transform-origin) outline-hidden"
39
33
  {...props}
40
34
  />
41
35
  </PreviewCardPrimitive.Positioner>
@@ -0,0 +1,26 @@
1
+ export * from './accordion';
2
+ export * from './alert';
3
+ export * from './breadcrumb';
4
+ export * from './button-group';
5
+ export * from './card';
6
+ export * from './collapsible';
7
+ export * from './empty';
8
+ export * from './field';
9
+ export * from './grid';
10
+ export * from './hover-card';
11
+ export * from './input-group';
12
+ export * from './input-otp';
13
+ export * from './item';
14
+ export * from './page-header';
15
+ export * from './pagination';
16
+ export * from './popover';
17
+ export * from './radio-group';
18
+ export * from './resizable';
19
+ export * from './scroll-area';
20
+ export * from './section';
21
+ export * from './select';
22
+ export * from './stack';
23
+ export * from './table';
24
+ export * from './tabs';
25
+ export * from './toggle-group';
26
+ export * from './tooltip';
@@ -4,7 +4,7 @@ import { cva, type VariantProps } from 'class-variance-authority';
4
4
  import * as React from 'react';
5
5
 
6
6
  import { cn } from '../../../lib/utils';
7
- import { buttonVariants } from './button';
7
+ import { buttonVariants } from '../atoms/button';
8
8
 
9
9
  function InputGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
10
10
  return (
@@ -0,0 +1,70 @@
1
+ import { OTPInput, OTPInputContext } from 'input-otp';
2
+ import * as React from 'react';
3
+
4
+ import { MinusIcon } from 'lucide-react';
5
+
6
+ function InputOTP({
7
+ className: _className,
8
+ ...props
9
+ }: React.ComponentProps<typeof OTPInput>) {
10
+ return (
11
+ <OTPInput
12
+ data-slot="input-otp"
13
+ containerClassName="cn-input-otp flex items-center has-disabled:opacity-50"
14
+ spellCheck={false}
15
+ className="disabled:cursor-not-allowed"
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ function InputOTPGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
22
+ return (
23
+ <div
24
+ data-slot="input-otp-group"
25
+ className="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"
26
+ {...props}
27
+ />
28
+ );
29
+ }
30
+
31
+ function InputOTPSlot({
32
+ index,
33
+ ...props
34
+ }: Omit<React.ComponentProps<'div'>, 'className'> & {
35
+ index: number;
36
+ }) {
37
+ const inputOTPContext = React.useContext(OTPInputContext);
38
+ const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
39
+
40
+ return (
41
+ <div
42
+ data-slot="input-otp-slot"
43
+ data-active={isActive}
44
+ className="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"
45
+ {...props}
46
+ >
47
+ {char}
48
+ {hasFakeCaret && (
49
+ <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
50
+ <div className="animate-caret-blink bg-foreground h-4 w-px duration-1000 bg-foreground h-4 w-px" />
51
+ </div>
52
+ )}
53
+ </div>
54
+ );
55
+ }
56
+
57
+ function InputOTPSeparator({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
58
+ return (
59
+ <div
60
+ data-slot="input-otp-separator"
61
+ className="[&_svg:not([class*='size-'])]:size-4 flex items-center"
62
+ role="separator"
63
+ {...props}
64
+ >
65
+ <MinusIcon />
66
+ </div>
67
+ );
68
+ }
69
+
70
+ export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot };
@@ -1,20 +1,15 @@
1
1
  import { mergeProps } from '@base-ui/react/merge-props';
2
2
  import { useRender } from '@base-ui/react/use-render';
3
3
  import { cva, type VariantProps } from 'class-variance-authority';
4
- import * as React from 'react';
5
4
 
6
5
  import { Separator as SeparatorPrimitive } from '@base-ui/react/separator';
7
- import { cn } from '../../../lib/utils';
8
6
 
9
- function ItemGroup({ className, ...props }: React.ComponentProps<'div'>) {
7
+ function ItemGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
10
8
  return (
11
9
  <div
12
10
  role="list"
13
11
  data-slot="item-group"
14
- className={cn(
15
- 'gap-4 has-[[data-size=sm]]:gap-2.5 has-[[data-size=xs]]:gap-2 group/item-group flex w-full flex-col',
16
- className,
17
- )}
12
+ className="gap-4 has-[[data-size=sm]]:gap-2.5 has-[[data-size=xs]]:gap-2 group/item-group flex w-full flex-col"
18
13
  {...props}
19
14
  />
20
15
  );
@@ -54,17 +49,16 @@ const itemVariants = cva(
54
49
  );
55
50
 
56
51
  function Item({
57
- className,
58
52
  variant = 'default',
59
53
  size = 'default',
60
54
  render,
61
55
  ...props
62
- }: useRender.ComponentProps<'div'> & VariantProps<typeof itemVariants>) {
56
+ }: Omit<useRender.ComponentProps<'div'>, 'className'> & VariantProps<typeof itemVariants>) {
63
57
  return useRender({
64
58
  defaultTagName: 'div',
65
59
  props: mergeProps<'div'>(
66
60
  {
67
- className: cn(itemVariants({ variant, size, className })),
61
+ className: itemVariants({ variant, size }),
68
62
  },
69
63
  props,
70
64
  ),
@@ -95,80 +89,68 @@ const itemMediaVariants = cva(
95
89
  );
96
90
 
97
91
  function ItemMedia({
98
- className,
99
92
  variant = 'default',
100
93
  ...props
101
- }: React.ComponentProps<'div'> & VariantProps<typeof itemMediaVariants>) {
94
+ }: Omit<React.ComponentProps<'div'>, 'className'> & VariantProps<typeof itemMediaVariants>) {
102
95
  return (
103
96
  <div
104
97
  data-slot="item-media"
105
98
  data-variant={variant}
106
- className={cn(itemMediaVariants({ variant, className }))}
99
+ className={itemMediaVariants({ variant })}
107
100
  {...props}
108
101
  />
109
102
  );
110
103
  }
111
104
 
112
- function ItemContent({ className, ...props }: React.ComponentProps<'div'>) {
105
+ function ItemContent({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
113
106
  return (
114
107
  <div
115
108
  data-slot="item-content"
116
- className={cn(
117
- 'gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none',
118
- className,
119
- )}
109
+ className="gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none"
120
110
  {...props}
121
111
  />
122
112
  );
123
113
  }
124
114
 
125
- function ItemTitle({ className, ...props }: React.ComponentProps<'div'>) {
115
+ function ItemTitle({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
126
116
  return (
127
117
  <div
128
118
  data-slot="item-title"
129
- className={cn(
130
- 'gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center',
131
- className,
132
- )}
119
+ className="gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center"
133
120
  {...props}
134
121
  />
135
122
  );
136
123
  }
137
124
 
138
- function ItemDescription({ className, ...props }: React.ComponentProps<'p'>) {
125
+ function ItemDescription({ ...props }: Omit<React.ComponentProps<'p'>, 'className'>) {
139
126
  return (
140
127
  <p
141
128
  data-slot="item-description"
142
- className={cn(
143
- 'text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4',
144
- className,
145
- )}
129
+ className="text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4"
146
130
  {...props}
147
131
  />
148
132
  );
149
133
  }
150
134
 
151
- function ItemActions({ className, ...props }: React.ComponentProps<'div'>) {
152
- return (
153
- <div data-slot="item-actions" className={cn('gap-2 flex items-center', className)} {...props} />
154
- );
135
+ function ItemActions({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
136
+ return <div data-slot="item-actions" className="gap-2 flex items-center" {...props} />;
155
137
  }
156
138
 
157
- function ItemHeader({ className, ...props }: React.ComponentProps<'div'>) {
139
+ function ItemHeader({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
158
140
  return (
159
141
  <div
160
142
  data-slot="item-header"
161
- className={cn('gap-2 flex basis-full items-center justify-between', className)}
143
+ className="gap-2 flex basis-full items-center justify-between"
162
144
  {...props}
163
145
  />
164
146
  );
165
147
  }
166
148
 
167
- function ItemFooter({ className, ...props }: React.ComponentProps<'div'>) {
149
+ function ItemFooter({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
168
150
  return (
169
151
  <div
170
152
  data-slot="item-footer"
171
- className={cn('gap-2 flex basis-full items-center justify-between', className)}
153
+ className="gap-2 flex basis-full items-center justify-between"
172
154
  {...props}
173
155
  />
174
156
  );
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
2
 
3
- import { Heading } from './heading';
3
+ import { Heading } from '../atoms/heading';
4
+ import { Text } from '../atoms/text';
4
5
  import { Stack } from './stack';
5
- import { Text } from './text';
6
6
 
7
7
  interface PageHeaderProps extends Omit<React.ComponentProps<'div'>, 'className'> {
8
8
  title: string;