@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
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.2",
4
4
  "description": "Design system for Comp AI - shadcn-style components with Tailwind CSS",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -23,6 +23,7 @@
23
23
  "default": "./lib/utils.ts"
24
24
  },
25
25
  "./globals.css": "./src/styles/globals.css",
26
+ "./fonts/*": "./src/fonts/*",
26
27
  "./tailwind.config": {
27
28
  "types": "./tailwind.config.ts",
28
29
  "import": "./tailwind.config.ts",
@@ -48,7 +49,7 @@
48
49
  "repository": {
49
50
  "type": "git",
50
51
  "url": "git+https://github.com/trycompai/comp.git",
51
- "directory": "packages/ui-shadcn"
52
+ "directory": "packages/design-system"
52
53
  },
53
54
  "license": "MIT",
54
55
  "keywords": [
@@ -67,13 +68,14 @@
67
68
  },
68
69
  "dependencies": {
69
70
  "@base-ui/react": "^1.0.0",
71
+ "@carbon/icons-react": "^11.72.0",
72
+ "@fontsource-variable/plus-jakarta-sans": "^5.2.8",
70
73
  "class-variance-authority": "^0.7.1",
71
74
  "clsx": "^2.1.1",
72
75
  "cmdk": "^1.1.1",
73
76
  "date-fns": "^4.1.0",
74
77
  "embla-carousel-react": "^8.6.0",
75
78
  "input-otp": "^1.4.2",
76
- "lucide-react": "^0.562.0",
77
79
  "next-themes": "^0.4.6",
78
80
  "react-day-picker": "^9.13.0",
79
81
  "react-resizable-panels": "^4.2.0",
@@ -90,6 +92,7 @@
90
92
  "tailwindcss": "^4.0.0"
91
93
  },
92
94
  "devDependencies": {
95
+ "@repo/typescript-config": "workspace:*",
93
96
  "@tailwindcss/postcss": "^4.1.10",
94
97
  "@types/node": "^22.18.0",
95
98
  "@types/react": "^19.2.7",
@@ -0,0 +1,49 @@
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
+ 'gap-1 rounded-sm px-1.5 py-1 text-[10px] font-semibold uppercase tracking-wider leading-none transition-colors has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 [&>svg]:size-2.5! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:ring-ring/50 focus-visible:ring-[3px] overflow-hidden antialiased select-none',
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default:
11
+ 'bg-primary text-primary-foreground [a]:hover:bg-primary/90',
12
+ secondary:
13
+ 'bg-muted text-muted-foreground [a]:hover:bg-muted/80',
14
+ destructive:
15
+ 'bg-destructive/10 text-destructive [a]:hover:bg-destructive/15 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/15',
16
+ outline:
17
+ 'border border-border/50 bg-transparent text-foreground [a]:hover:bg-muted/30',
18
+ ghost:
19
+ 'bg-transparent text-muted-foreground hover:bg-muted/50 hover:text-foreground',
20
+ link: 'bg-transparent text-primary underline-offset-4 hover:underline',
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ variant: 'default',
25
+ },
26
+ },
27
+ );
28
+
29
+ type BadgeProps = Omit<useRender.ComponentProps<'span'>, 'className'> &
30
+ VariantProps<typeof badgeVariants>;
31
+
32
+ function Badge({ variant = 'default', render, ...props }: BadgeProps) {
33
+ return useRender({
34
+ defaultTagName: 'span',
35
+ props: mergeProps<'span'>(
36
+ {
37
+ className: badgeVariants({ variant }),
38
+ },
39
+ props,
40
+ ),
41
+ render,
42
+ state: {
43
+ slot: 'badge',
44
+ variant,
45
+ },
46
+ });
47
+ }
48
+
49
+ export { Badge, badgeVariants };
@@ -5,7 +5,7 @@ import * as React from 'react';
5
5
  import { Spinner } from './spinner';
6
6
 
7
7
  const buttonVariants = cva(
8
- "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 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
8
+ "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 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all duration-150 ease-out active:scale-[0.98] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none cursor-pointer",
9
9
  {
10
10
  variants: {
11
11
  variant: {
@@ -36,6 +36,11 @@ const buttonVariants = cva(
36
36
  'icon-sm':
37
37
  'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',
38
38
  'icon-lg': 'size-9',
39
+ // Round icon buttons - for avatar triggers and circular icons
40
+ 'icon-round': 'size-8 rounded-full',
41
+ 'icon-round-xs': "size-6 rounded-full [&_svg:not([class*='size-'])]:size-3",
42
+ 'icon-round-sm': 'size-7 rounded-full',
43
+ 'icon-round-lg': 'size-9 rounded-full',
39
44
  // Calendar day button - special size for calendar day cells
40
45
  'calendar-day': [
41
46
  // Base sizing
@@ -1,19 +1,19 @@
1
1
  import { Checkbox as CheckboxPrimitive } from '@base-ui/react/checkbox';
2
2
 
3
- import { CheckIcon } from 'lucide-react';
3
+ import { Checkmark } from '@carbon/icons-react';
4
4
 
5
5
  function Checkbox({ ...props }: Omit<CheckboxPrimitive.Root.Props, 'className'>) {
6
6
  return (
7
7
  <CheckboxPrimitive.Root
8
8
  data-slot="checkbox"
9
- className="border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-[3px] aria-invalid:ring-[3px] peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50"
9
+ className="border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-[3px] aria-invalid:ring-[3px] peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50 cursor-pointer"
10
10
  {...props}
11
11
  >
12
12
  <CheckboxPrimitive.Indicator
13
13
  data-slot="checkbox-indicator"
14
14
  className="[&>svg]:size-3.5 grid place-content-center text-current transition-none"
15
15
  >
16
- <CheckIcon />
16
+ <Checkmark />
17
17
  </CheckboxPrimitive.Indicator>
18
18
  </CheckboxPrimitive.Root>
19
19
  );
@@ -1,15 +1,15 @@
1
1
  import { cva, type VariantProps } from 'class-variance-authority';
2
2
  import * as React from 'react';
3
3
 
4
- const headingVariants = cva('font-semibold', {
4
+ const headingVariants = cva('font-medium', {
5
5
  variants: {
6
6
  level: {
7
- '1': 'text-2xl tracking-tight',
7
+ '1': 'text-4xl tracking-tight',
8
8
  '2': 'text-xl',
9
- '3': 'text-lg font-medium',
10
- '4': 'text-base font-medium',
11
- '5': 'text-sm font-medium',
12
- '6': 'text-sm font-medium',
9
+ '3': 'text-lg ',
10
+ '4': 'text-base ',
11
+ '5': 'text-sm ',
12
+ '6': 'text-sm ',
13
13
  },
14
14
  variant: {
15
15
  default: 'text-foreground',
@@ -0,0 +1,21 @@
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 './logo';
12
+ export * from './progress';
13
+ export * from './separator';
14
+ export * from './skeleton';
15
+ export * from './slider';
16
+ export * from './spinner';
17
+ export * from './stack';
18
+ export * from './switch';
19
+ export * from './text';
20
+ export * from './textarea';
21
+ 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 };
@@ -0,0 +1,52 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+
5
+ interface LogoProps extends Omit<React.SVGProps<SVGSVGElement>, 'className'> {
6
+ /** Logo variant - 'dark' shows dark logo (for light backgrounds), 'light' shows white logo (for dark backgrounds) */
7
+ variant?: 'dark' | 'light';
8
+ }
9
+
10
+ function Logo({ variant = 'dark', ...props }: LogoProps) {
11
+ const fill = variant === 'light' ? '#FFFFFF' : '#16171B';
12
+
13
+ return (
14
+ <svg
15
+ viewBox="0 0 1119 272"
16
+ fill="none"
17
+ xmlns="http://www.w3.org/2000/svg"
18
+ {...props}
19
+ >
20
+ <path
21
+ d="M204 52.885L195.465 46.2399L136.011 0L0 105.77V166.217L136.011 272L272 166.217V105.77L204 52.885ZM136.011 26.631L178.349 59.5553L156.598 76.4509L154.653 77.9583L136.011 63.4621L81.6113 105.77L100.253 120.266L117.369 133.594L136.011 148.091L190.4 105.758L171.781 91.2613L173.725 89.7538L195.476 72.8583L237.791 105.77L216.04 122.691L136.023 184.934L93.6851 152.01L76.5692 138.707L55.9827 122.703L34.2431 105.783L136.011 26.631Z"
22
+ fill={fill}
23
+ />
24
+ <path
25
+ d="M423.8 210.2C411.133 210.2 400 207.267 390.4 201.4C380.8 195.4 373.333 186.867 368 175.8C362.667 164.733 360 151.533 360 136.2C360 120.867 362.667 107.667 368 96.6C373.333 85.4 380.8 76.8 390.4 70.8C400 64.8 411.133 61.8 423.8 61.8C441 61.8 454.333 66.1333 463.8 74.8C473.267 83.4667 479.467 95.2667 482.4 110.2L464.2 111.4C462.2 101.267 457.933 93.2667 451.4 87.4C444.867 81.5333 435.667 78.6 423.8 78.6C414.733 78.6 406.733 80.9333 399.8 85.6C393 90.1333 387.667 96.7333 383.8 105.4C379.933 113.933 378 124.2 378 136.2C378 148.2 379.933 158.467 383.8 167C387.667 175.533 393 182.067 399.8 186.6C406.733 191.133 414.733 193.4 423.8 193.4C436.2 193.4 445.8 190.2 452.6 183.8C459.4 177.267 463.667 168.467 465.4 157.4L483.6 158.6C481.867 168.867 478.467 177.867 473.4 185.6C468.333 193.333 461.6 199.4 453.2 203.8C444.933 208.067 435.133 210.2 423.8 210.2ZM547.463 209.4C537.729 209.4 529.196 207.133 521.863 202.6C514.529 198.067 508.863 191.667 504.863 183.4C500.863 175 498.863 165.2 498.863 154C498.863 142.667 500.863 132.867 504.863 124.6C508.863 116.333 514.529 109.933 521.863 105.4C529.196 100.867 537.729 98.6 547.463 98.6C557.196 98.6 565.663 100.867 572.863 105.4C580.196 109.933 585.863 116.333 589.863 124.6C593.863 132.867 595.863 142.667 595.863 154C595.863 165.2 593.863 175 589.863 183.4C585.863 191.667 580.196 198.067 572.863 202.6C565.663 207.133 557.196 209.4 547.463 209.4ZM547.463 193.4C557.196 193.4 564.729 189.933 570.063 183C575.529 175.933 578.263 166.267 578.263 154C578.263 141.733 575.529 132.133 570.063 125.2C564.729 118.133 557.196 114.6 547.463 114.6C537.729 114.6 530.129 118.133 524.663 125.2C519.196 132.133 516.462 141.733 516.462 154C516.462 166.267 519.196 175.933 524.663 183C530.129 189.933 537.729 193.4 547.463 193.4ZM618.758 207V101H634.158L634.758 127.8L632.358 127C633.558 121.133 635.624 116.133 638.558 112C641.624 107.733 645.358 104.467 649.758 102.2C654.158 99.8 659.024 98.6 664.358 98.6C673.558 98.6 681.024 101.133 686.758 106.2C692.624 111.267 696.291 118.333 697.758 127.4L694.558 127.2C695.624 121.067 697.558 115.933 700.358 111.8C703.291 107.533 707.024 104.267 711.558 102C716.091 99.7333 721.291 98.6 727.158 98.6C734.758 98.6 741.158 100.2 746.358 103.4C751.558 106.467 755.491 111 758.158 117C760.824 123 762.158 130.267 762.158 138.8V207H745.358V142.4C745.358 132.8 743.491 125.6 739.758 120.8C736.024 115.867 730.491 113.4 723.158 113.4C718.224 113.4 713.891 114.6 710.158 117C706.558 119.4 703.758 122.867 701.758 127.4C699.758 131.8 698.758 137.2 698.758 143.6V207H681.958V143.6C681.958 134.133 680.291 126.733 676.958 121.4C673.624 116.067 668.024 113.4 660.158 113.4C655.224 113.4 650.891 114.6 647.158 117C643.558 119.4 640.691 122.867 638.558 127.4C636.558 131.933 635.558 137.333 635.558 143.6V207H618.758ZM790.242 237V101H805.842L806.242 123.8L803.842 122.6C806.509 114.733 810.909 108.8 817.042 104.8C823.309 100.667 830.509 98.6 838.642 98.6C849.176 98.6 857.776 101.2 864.442 106.4C871.242 111.6 876.242 118.4 879.442 126.8C882.776 135.2 884.442 144.267 884.442 154C884.442 163.733 882.776 172.8 879.442 181.2C876.242 189.6 871.242 196.4 864.442 201.6C857.776 206.8 849.176 209.4 838.642 209.4C833.176 209.4 828.042 208.467 823.242 206.6C818.576 204.733 814.576 202.133 811.242 198.8C808.042 195.467 805.842 191.533 804.642 187L807.042 184.2V237H790.242ZM837.042 193.4C846.242 193.4 853.509 189.933 858.842 183C864.176 176.067 866.842 166.4 866.842 154C866.842 141.6 864.176 131.933 858.842 125C853.509 118.067 846.242 114.6 837.042 114.6C830.909 114.6 825.576 116.067 821.042 119C816.642 121.933 813.176 126.333 810.642 132.2C808.242 138.067 807.042 145.333 807.042 154C807.042 162.667 808.242 169.933 810.642 175.8C813.042 181.667 816.509 186.067 821.042 189C825.576 191.933 830.909 193.4 837.042 193.4ZM939.188 207L990.388 65H1013.59L1064.79 207H1045.99L1031.79 166.6H972.188L957.988 207H939.188ZM977.988 149.8H1025.99L1001.99 80L977.988 149.8ZM1083.28 207V65H1100.48V207H1083.28Z"
26
+ fill={fill}
27
+ />
28
+ </svg>
29
+ );
30
+ }
31
+
32
+ /** Icon-only version of the logo (just the shield/chevron mark) */
33
+ function LogoIcon({ variant = 'dark', ...props }: LogoProps) {
34
+ const fill = variant === 'light' ? '#FFFFFF' : '#16171B';
35
+
36
+ return (
37
+ <svg
38
+ viewBox="0 0 272 272"
39
+ fill="none"
40
+ xmlns="http://www.w3.org/2000/svg"
41
+ {...props}
42
+ >
43
+ <path
44
+ d="M204 52.885L195.465 46.2399L136.011 0L0 105.77V166.217L136.011 272L272 166.217V105.77L204 52.885ZM136.011 26.631L178.349 59.5553L156.598 76.4509L154.653 77.9583L136.011 63.4621L81.6113 105.77L100.253 120.266L117.369 133.594L136.011 148.091L190.4 105.758L171.781 91.2613L173.725 89.7538L195.476 72.8583L237.791 105.77L216.04 122.691L136.023 184.934L93.6851 152.01L76.5692 138.707L55.9827 122.703L34.2431 105.783L136.011 26.631Z"
45
+ fill={fill}
46
+ />
47
+ </svg>
48
+ );
49
+ }
50
+
51
+ export { Logo, LogoIcon };
52
+ export type { LogoProps };
@@ -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,8 +1,8 @@
1
- import { Loader2Icon } from 'lucide-react';
1
+ import { Renew } from '@carbon/icons-react';
2
2
 
3
- function Spinner({ ...props }: Omit<React.ComponentProps<'svg'>, 'className'>) {
3
+ function Spinner({ ...props }: Omit<React.ComponentProps<typeof Renew>, 'className'>) {
4
4
  return (
5
- <Loader2Icon
5
+ <Renew
6
6
  role="status"
7
7
  aria-label="Loading"
8
8
  className="size-4 shrink-0 animate-spin"
@@ -0,0 +1,97 @@
1
+ import { cva, type VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
+
4
+ const stackVariants = cva('flex', {
5
+ variants: {
6
+ direction: {
7
+ row: 'flex-row',
8
+ column: 'flex-col',
9
+ 'row-reverse': 'flex-row-reverse',
10
+ 'column-reverse': 'flex-col-reverse',
11
+ },
12
+ gap: {
13
+ none: 'gap-0',
14
+ xs: 'gap-1',
15
+ sm: 'gap-2',
16
+ md: 'gap-4',
17
+ lg: 'gap-6',
18
+ xl: 'gap-8',
19
+ // Numeric values for backward compatibility
20
+ '0': 'gap-0',
21
+ '1': 'gap-1',
22
+ '2': 'gap-2',
23
+ '3': 'gap-3',
24
+ '4': 'gap-4',
25
+ '6': 'gap-6',
26
+ '8': 'gap-8',
27
+ },
28
+ align: {
29
+ start: 'items-start',
30
+ center: 'items-center',
31
+ end: 'items-end',
32
+ stretch: 'items-stretch',
33
+ baseline: 'items-baseline',
34
+ },
35
+ justify: {
36
+ start: 'justify-start',
37
+ center: 'justify-center',
38
+ end: 'justify-end',
39
+ between: 'justify-between',
40
+ around: 'justify-around',
41
+ evenly: 'justify-evenly',
42
+ },
43
+ wrap: {
44
+ nowrap: 'flex-nowrap',
45
+ wrap: 'flex-wrap',
46
+ 'wrap-reverse': 'flex-wrap-reverse',
47
+ },
48
+ },
49
+ defaultVariants: {
50
+ direction: 'column',
51
+ gap: 'md',
52
+ align: 'stretch',
53
+ justify: 'start',
54
+ wrap: 'nowrap',
55
+ },
56
+ });
57
+
58
+ type StackElement = 'div' | 'section' | 'nav' | 'ul' | 'ol' | 'main' | 'article' | 'aside' | 'header' | 'footer';
59
+
60
+ interface StackProps
61
+ extends Omit<React.HTMLAttributes<HTMLElement>, 'className'>,
62
+ VariantProps<typeof stackVariants> {
63
+ as?: StackElement;
64
+ }
65
+
66
+ function Stack({
67
+ as: Component = 'div',
68
+ direction,
69
+ gap,
70
+ align,
71
+ justify,
72
+ wrap,
73
+ ...props
74
+ }: StackProps) {
75
+ return (
76
+ <Component
77
+ data-slot="stack"
78
+ className={stackVariants({ direction, gap, align, justify, wrap })}
79
+ {...props}
80
+ />
81
+ );
82
+ }
83
+
84
+ type VStackProps = Omit<StackProps, 'direction'>;
85
+
86
+ function VStack({ gap, align, justify, wrap, ...props }: VStackProps) {
87
+ return <Stack direction="column" gap={gap} align={align} justify={justify} wrap={wrap} {...props} />;
88
+ }
89
+
90
+ type HStackProps = Omit<StackProps, 'direction'>;
91
+
92
+ function HStack({ gap, align, justify, wrap, ...props }: HStackProps) {
93
+ return <Stack direction="row" gap={gap} align={align} justify={justify} wrap={wrap} {...props} />;
94
+ }
95
+
96
+ export { Stack, VStack, HStack, stackVariants };
97
+ export type { StackProps, VStackProps, HStackProps };
@@ -12,7 +12,7 @@ function Switch({
12
12
  <SwitchPrimitive.Root
13
13
  data-slot="switch"
14
14
  data-size={size}
15
- className="data-checked:bg-primary data-unchecked:bg-input 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 dark:data-unchecked:bg-input/80 shrink-0 rounded-full border border-transparent shadow-xs focus-visible:ring-[3px] aria-invalid:ring-[3px] data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] peer group/switch relative inline-flex items-center transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 data-disabled:cursor-not-allowed data-disabled:opacity-50"
15
+ className="data-checked:bg-primary data-unchecked:bg-input 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 dark:data-unchecked:bg-input/80 shrink-0 rounded-full border border-transparent shadow-xs focus-visible:ring-[3px] aria-invalid:ring-[3px] data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] peer group/switch relative inline-flex items-center transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 data-disabled:cursor-not-allowed data-disabled:opacity-50 cursor-pointer"
16
16
  {...props}
17
17
  >
18
18
  <SwitchPrimitive.Thumb
@@ -47,10 +47,14 @@ interface TextProps
47
47
  }
48
48
 
49
49
  function Text({ as: Component = 'p', size, variant, weight, leading, font, ...props }: TextProps) {
50
+ const resolvedSize = size ?? 'base';
51
+ const isDefaultSize = size === undefined;
50
52
  return (
51
53
  <Component
52
54
  data-slot="text"
53
- className={textVariants({ size, variant, weight, leading, font })}
55
+ data-size={resolvedSize}
56
+ data-default-size={isDefaultSize ? 'true' : undefined}
57
+ className={textVariants({ size: resolvedSize, variant, weight, leading, font })}
54
58
  {...props}
55
59
  />
56
60
  );
@@ -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,10 +1,8 @@
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
- "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",
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 cursor-pointer",
8
6
  {
9
7
  variants: {
10
8
  variant: {
@@ -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
  );
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { Accordion as AccordionPrimitive } from '@base-ui/react/accordion';
4
- import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
4
+ import { ChevronDown, ChevronUp } from '@carbon/icons-react';
5
5
 
6
6
  function Accordion({ ...props }: Omit<AccordionPrimitive.Root.Props, 'className'>) {
7
7
  return (
@@ -27,11 +27,11 @@ function AccordionTrigger({
27
27
  {...props}
28
28
  >
29
29
  {children}
30
- <ChevronDownIcon
30
+ <ChevronDown
31
31
  data-slot="accordion-trigger-icon"
32
32
  className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden"
33
33
  />
34
- <ChevronUpIcon
34
+ <ChevronUp
35
35
  data-slot="accordion-trigger-icon"
36
36
  className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline"
37
37
  />