@hilum/ui 0.1.1 → 0.1.3

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 (92) hide show
  1. package/README.md +23 -4
  2. package/dist/chunk-J2QQDUF4.js +204 -0
  3. package/dist/chunk-J2QQDUF4.js.map +1 -0
  4. package/dist/create-theme.d.ts +27 -0
  5. package/dist/create-theme.js +172 -0
  6. package/dist/create-theme.js.map +1 -0
  7. package/dist/index.d.ts +21 -8
  8. package/dist/index.js +393 -381
  9. package/dist/index.js.map +1 -1
  10. package/dist/tokens.css +59 -50
  11. package/dist/tokens.d.ts +46 -38
  12. package/dist/tokens.js +1 -191
  13. package/dist/tokens.js.map +1 -1
  14. package/llms.txt +1514 -0
  15. package/package.json +11 -7
  16. package/src/components/accordion.tsx +5 -5
  17. package/src/components/action-panel.tsx +6 -6
  18. package/src/components/activity-feed.tsx +4 -4
  19. package/src/components/alert-dialog.tsx +3 -3
  20. package/src/components/alert.tsx +4 -4
  21. package/src/components/avatar-stack.tsx +2 -2
  22. package/src/components/avatar.tsx +2 -2
  23. package/src/components/badge.tsx +6 -5
  24. package/src/components/breadcrumb.tsx +5 -5
  25. package/src/components/button-group.tsx +4 -4
  26. package/src/components/button.tsx +6 -5
  27. package/src/components/calendar.tsx +7 -7
  28. package/src/components/card-heading.tsx +3 -3
  29. package/src/components/card.tsx +3 -3
  30. package/src/components/chart.tsx +11 -11
  31. package/src/components/checkbox.tsx +1 -1
  32. package/src/components/color-input.tsx +7 -7
  33. package/src/components/color-picker.tsx +5 -5
  34. package/src/components/combobox.tsx +10 -10
  35. package/src/components/command-palette.tsx +11 -11
  36. package/src/components/command.tsx +13 -13
  37. package/src/components/context-menu.tsx +15 -16
  38. package/src/components/data-table.tsx +6 -6
  39. package/src/components/date-picker.tsx +9 -4
  40. package/src/components/description-list.tsx +8 -8
  41. package/src/components/dialog.tsx +3 -3
  42. package/src/components/drawer.tsx +5 -5
  43. package/src/components/dropdown-menu.tsx +15 -16
  44. package/src/components/empty-state.tsx +3 -3
  45. package/src/components/field.tsx +13 -6
  46. package/src/components/grid-list.tsx +12 -12
  47. package/src/components/hover-card.tsx +1 -1
  48. package/src/components/input-group.tsx +8 -8
  49. package/src/components/input-number.tsx +7 -7
  50. package/src/components/input-otp.tsx +3 -3
  51. package/src/components/input.tsx +5 -4
  52. package/src/components/kbd.tsx +1 -1
  53. package/src/components/label.tsx +1 -1
  54. package/src/components/menubar.tsx +21 -22
  55. package/src/components/native-select.tsx +4 -4
  56. package/src/components/navigation-menu.tsx +10 -10
  57. package/src/components/notification.tsx +10 -10
  58. package/src/components/page-heading.tsx +8 -8
  59. package/src/components/pagination.tsx +1 -1
  60. package/src/components/progress.tsx +1 -1
  61. package/src/components/property-row.tsx +1 -1
  62. package/src/components/radio-card.tsx +6 -6
  63. package/src/components/radio-group.tsx +3 -3
  64. package/src/components/resizable.tsx +3 -3
  65. package/src/components/scroll-area.tsx +1 -1
  66. package/src/components/section-heading.tsx +3 -3
  67. package/src/components/select.tsx +11 -11
  68. package/src/components/separator.tsx +1 -1
  69. package/src/components/sheet.tsx +3 -3
  70. package/src/components/sidebar.tsx +19 -19
  71. package/src/components/skeleton.tsx +1 -1
  72. package/src/components/slider.tsx +1 -1
  73. package/src/components/sonner.tsx +5 -5
  74. package/src/components/stacked-list.tsx +4 -4
  75. package/src/components/stat-card.tsx +6 -6
  76. package/src/components/steps.tsx +13 -12
  77. package/src/components/switch.tsx +1 -1
  78. package/src/components/table.tsx +9 -9
  79. package/src/components/tabs.tsx +2 -2
  80. package/src/components/textarea.tsx +4 -4
  81. package/src/components/toggle.tsx +8 -8
  82. package/src/components/tooltip.tsx +1 -1
  83. package/src/index.ts +3 -2
  84. package/src/tokens/tokens.ts +54 -40
  85. package/src/components/__tests__/data.test.tsx +0 -180
  86. package/src/components/__tests__/disclosure.test.tsx +0 -198
  87. package/src/components/__tests__/display.test.tsx +0 -262
  88. package/src/components/__tests__/feedback.test.tsx +0 -138
  89. package/src/components/__tests__/form.test.tsx +0 -297
  90. package/src/components/__tests__/layout.test.tsx +0 -388
  91. package/src/components/__tests__/overlay.test.tsx +0 -90
  92. package/src/components/__tests__/primitives.test.tsx +0 -248
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hilum/ui",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "description": "Hilum UI — design system primitives (Button, Input, Dialog, Combobox, …) + tokens + fonts + icons",
6
6
  "license": "MIT",
@@ -29,18 +29,22 @@
29
29
  "import": "./dist/tokens.js",
30
30
  "types": "./dist/tokens.d.ts"
31
31
  },
32
- "./tokens.css": "./dist/tokens.css"
32
+ "./tokens.css": "./dist/tokens.css",
33
+ "./create-theme": {
34
+ "import": "./dist/create-theme.js",
35
+ "types": "./dist/create-theme.d.ts"
36
+ }
33
37
  },
34
38
  "files": [
35
39
  "dist",
36
- "src/components",
37
- "!src/components/__tests__",
40
+ "src/components/*.tsx",
38
41
  "src/icons.ts",
39
42
  "src/index.ts",
40
- "src/lib",
41
- "src/tokens",
43
+ "src/lib/*.ts",
44
+ "src/tokens/*.ts",
42
45
  "README.md",
43
- "LICENSE"
46
+ "LICENSE",
47
+ "llms.txt"
44
48
  ],
45
49
  "peerDependencies": {
46
50
  "react": "^19.0.0",
@@ -9,7 +9,7 @@ const AccordionRoot = React.forwardRef<
9
9
  React.ComponentRef<typeof Accordion.Root>,
10
10
  React.ComponentPropsWithoutRef<typeof Accordion.Root>
11
11
  >(({ className, ...props }, ref) => (
12
- <Accordion.Root ref={ref} className={cn("divide-y divide-taupe-100", className)} {...props} />
12
+ <Accordion.Root ref={ref} className={cn("divide-y divide-ground-100", className)} {...props} />
13
13
  ));
14
14
  AccordionRoot.displayName = "Accordion";
15
15
 
@@ -30,9 +30,9 @@ const AccordionTrigger = React.forwardRef<
30
30
  ref={ref}
31
31
  className={cn(
32
32
  "flex w-full items-center justify-between py-4",
33
- "body font-medium text-taupe-900 transition-colors hover:text-taupe-700",
33
+ "body font-medium text-ground-900 transition-colors hover:text-ground-700",
34
34
  "[&[data-state=open]>svg]:rotate-180",
35
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-taupe-900/15",
35
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ground-900/15",
36
36
  className,
37
37
  )}
38
38
  {...props}
@@ -40,7 +40,7 @@ const AccordionTrigger = React.forwardRef<
40
40
  {children}
41
41
  <ChevronDown
42
42
  size={16}
43
- className="text-taupe-400 transition-transform duration-200 shrink-0"
43
+ className="text-ground-400 transition-transform duration-200 shrink-0"
44
44
  />
45
45
  </Accordion.Trigger>
46
46
  </Accordion.Header>
@@ -54,7 +54,7 @@ const AccordionContent = React.forwardRef<
54
54
  <Accordion.Content
55
55
  ref={ref}
56
56
  className={cn(
57
- "overflow-hidden body text-taupe-500",
57
+ "overflow-hidden body text-ground-500",
58
58
  "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
59
59
  className,
60
60
  )}
@@ -48,7 +48,7 @@ function ActionPanel({
48
48
  (link.href ? (
49
49
  <a
50
50
  href={link.href}
51
- className="body font-medium text-taupe-600 hover:text-taupe-900 transition-colors inline-flex items-center gap-1"
51
+ className="body font-medium text-ground-600 hover:text-ground-900 transition-colors inline-flex items-center gap-1"
52
52
  >
53
53
  {link.label} <span aria-hidden>→</span>
54
54
  </a>
@@ -56,7 +56,7 @@ function ActionPanel({
56
56
  <button
57
57
  type="button"
58
58
  onClick={link.onClick}
59
- className="body font-medium text-taupe-600 hover:text-taupe-900 transition-colors inline-flex items-center gap-1"
59
+ className="body font-medium text-ground-600 hover:text-ground-900 transition-colors inline-flex items-center gap-1"
60
60
  >
61
61
  {link.label} <span aria-hidden>→</span>
62
62
  </button>
@@ -81,16 +81,16 @@ function ActionPanel({
81
81
  className={cn(
82
82
  "rounded-xl border px-5 py-5",
83
83
  variant === "muted"
84
- ? "border-taupe-100 bg-taupe-50"
85
- : "border-taupe-100 bg-white shadow-natural",
84
+ ? "border-ground-100 bg-ground-50"
85
+ : "border-ground-100 bg-white shadow-natural",
86
86
  layout === "inline" && "flex items-center justify-between gap-6",
87
87
  className,
88
88
  )}
89
89
  >
90
90
  <div className={cn("min-w-0", layout === "inline" ? "flex-1" : "")}>
91
- <p className="body font-semibold text-taupe-900">{title}</p>
91
+ <p className="body font-semibold text-ground-900">{title}</p>
92
92
  {description && (
93
- <p className={cn("body text-taupe-400", layout === "stacked" ? "mt-1" : "")}>
93
+ <p className={cn("body text-ground-400", layout === "stacked" ? "mt-1" : "")}>
94
94
  {description}
95
95
  </p>
96
96
  )}
@@ -26,7 +26,7 @@ function ActivityFeed({ events, className }: ActivityFeedProps) {
26
26
  <div className="relative pb-8">
27
27
  {!isLast && (
28
28
  <span
29
- className="absolute top-4 left-4 -ml-px h-full w-0.5 bg-taupe-100"
29
+ className="absolute top-4 left-4 -ml-px h-full w-0.5 bg-ground-100"
30
30
  aria-hidden="true"
31
31
  />
32
32
  )}
@@ -36,7 +36,7 @@ function ActivityFeed({ events, className }: ActivityFeedProps) {
36
36
  <span
37
37
  className={cn(
38
38
  "flex size-8 items-center justify-center rounded-full ring-8 ring-white",
39
- event.iconBgClass ?? "bg-taupe-100 text-taupe-500",
39
+ event.iconBgClass ?? "bg-ground-100 text-ground-500",
40
40
  )}
41
41
  >
42
42
  {event.icon}
@@ -45,11 +45,11 @@ function ActivityFeed({ events, className }: ActivityFeedProps) {
45
45
 
46
46
  {/* Content */}
47
47
  <div className="flex min-w-0 flex-1 items-baseline justify-between gap-4 pt-1">
48
- <div className="body text-taupe-600">{event.content}</div>
48
+ <div className="body text-ground-600">{event.content}</div>
49
49
  {event.date && (
50
50
  <time
51
51
  dateTime={event.datetime ?? event.date}
52
- className="caption whitespace-nowrap text-taupe-400"
52
+ className="caption whitespace-nowrap text-ground-400"
53
53
  >
54
54
  {event.date}
55
55
  </time>
@@ -65,7 +65,7 @@ const AlertDialogTitle = React.forwardRef<
65
65
  >(({ className, ...props }, ref) => (
66
66
  <AlertDialog.Title
67
67
  ref={ref}
68
- className={cn("body-lg font-semibold text-taupe-900", className)}
68
+ className={cn("body-lg font-semibold text-ground-900", className)}
69
69
  {...props}
70
70
  />
71
71
  ));
@@ -75,7 +75,7 @@ const AlertDialogDescription = React.forwardRef<
75
75
  React.ComponentRef<typeof AlertDialog.Description>,
76
76
  React.ComponentPropsWithoutRef<typeof AlertDialog.Description>
77
77
  >(({ className, ...props }, ref) => (
78
- <AlertDialog.Description ref={ref} className={cn("body text-taupe-500", className)} {...props} />
78
+ <AlertDialog.Description ref={ref} className={cn("body text-ground-500", className)} {...props} />
79
79
  ));
80
80
  AlertDialogDescription.displayName = "AlertDialogDescription";
81
81
 
@@ -107,7 +107,7 @@ const AlertDialogCancel = React.forwardRef<
107
107
  className={cn(
108
108
  "inline-flex h-9 items-center justify-center rounded-md px-4",
109
109
  "body font-medium whitespace-nowrap transition-all duration-150",
110
- "bg-white text-taupe-700 shadow-natural hover:bg-taupe-50 rounded-xl",
110
+ "bg-white text-ground-700 shadow-natural hover:bg-ground-50 rounded-xl",
111
111
  "focus-visible:ring-2 focus-visible:ring-brand-primary/30 focus-visible:ring-offset-1 outline-none",
112
112
  "disabled:pointer-events-none disabled:opacity-50",
113
113
  className,
@@ -7,10 +7,10 @@ const alertVariants = cva(
7
7
  {
8
8
  variants: {
9
9
  variant: {
10
- default: "bg-taupe-50 text-taupe-800 [&>svg]:text-taupe-500",
11
- info: "bg-brand-secondary/40 text-taupe-700 [&>svg]:text-taupe-500",
12
- success: "bg-brand-secondary/15 text-taupe-800 [&>svg]:text-taupe-600",
13
- warning: "bg-brand-secondary/70 text-taupe-800 [&>svg]:text-taupe-600",
10
+ default: "bg-ground-50 text-ground-800 [&>svg]:text-ground-500",
11
+ info: "bg-brand-secondary/40 text-ground-700 [&>svg]:text-ground-500",
12
+ success: "bg-brand-secondary/15 text-ground-800 [&>svg]:text-ground-600",
13
+ warning: "bg-brand-secondary/70 text-ground-800 [&>svg]:text-ground-600",
14
14
  destructive: "bg-red-50 text-red-800 [&>svg]:text-red-500",
15
15
  },
16
16
  },
@@ -44,7 +44,7 @@ function AvatarStack({ avatars, max, size = "md", className }: AvatarStackProps)
44
44
  className={cn(
45
45
  "flex size-full items-center justify-center font-medium",
46
46
  s.text,
47
- avatar.colorClass ?? "bg-taupe-200 text-taupe-700",
47
+ avatar.colorClass ?? "bg-ground-200 text-ground-700",
48
48
  )}
49
49
  >
50
50
  {avatar.fallback ?? avatar.name.slice(0, 2).toUpperCase()}
@@ -55,7 +55,7 @@ function AvatarStack({ avatars, max, size = "md", className }: AvatarStackProps)
55
55
  {overflow > 0 && (
56
56
  <span
57
57
  className={cn(
58
- "relative inline-flex shrink-0 items-center justify-center rounded-full ring-white bg-taupe-100 font-medium text-taupe-600",
58
+ "relative inline-flex shrink-0 items-center justify-center rounded-full ring-white bg-ground-100 font-medium text-ground-600",
59
59
  s.wrapper,
60
60
  s.text,
61
61
  )}
@@ -52,7 +52,7 @@ const AvatarFallback = React.forwardRef<
52
52
  <AvatarPrimitive.Fallback
53
53
  ref={ref}
54
54
  className={cn(
55
- "flex h-full w-full items-center justify-center rounded-full bg-taupe-100 body font-semibold text-taupe-600",
55
+ "flex h-full w-full items-center justify-center rounded-full bg-ground-100 body font-semibold text-ground-600",
56
56
  className,
57
57
  )}
58
58
  {...props}
@@ -62,7 +62,7 @@ AvatarFallback.displayName = "AvatarFallback";
62
62
 
63
63
  const statusColorMap = {
64
64
  online: "bg-brand-secondary",
65
- offline: "bg-taupe-300",
65
+ offline: "bg-ground-300",
66
66
  busy: "bg-red-500",
67
67
  away: "bg-brand-secondary",
68
68
  };
@@ -7,12 +7,12 @@ const badgeVariants = cva(
7
7
  {
8
8
  variants: {
9
9
  variant: {
10
- default: "bg-taupe-900 text-white",
11
- secondary: "bg-taupe-100 text-taupe-700",
12
- outline: "border border-taupe-200 text-taupe-600 bg-transparent",
10
+ default: "bg-ground-900 text-white",
11
+ secondary: "bg-ground-100 text-ground-700",
12
+ outline: "border border-ground-200 text-ground-600 bg-transparent",
13
13
  brand: "bg-brand-primary text-white",
14
- success: "bg-brand-secondary/20 text-taupe-800 border border-brand-secondary/50",
15
- warning: "bg-brand-secondary/70 text-taupe-700 border border-brand-secondary",
14
+ success: "bg-brand-secondary/20 text-ground-800 border border-brand-secondary/50",
15
+ warning: "bg-brand-secondary/70 text-ground-700 border border-brand-secondary",
16
16
  destructive: "bg-red-50 text-red-700 border border-red-200",
17
17
  },
18
18
  },
@@ -29,5 +29,6 @@ function Badge({ className, variant, ...props }: BadgeProps) {
29
29
  <span data-slot="badge" className={cn(badgeVariants({ variant, className }))} {...props} />
30
30
  );
31
31
  }
32
+ Badge.displayName = "Badge";
32
33
 
33
34
  export { Badge, badgeVariants };
@@ -12,7 +12,7 @@ const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentProps<"
12
12
  ({ className, ...props }, ref) => (
13
13
  <ol
14
14
  ref={ref}
15
- className={cn("flex flex-wrap items-center gap-1.5 body text-taupe-500", className)}
15
+ className={cn("flex flex-wrap items-center gap-1.5 body text-ground-500", className)}
16
16
  {...props}
17
17
  />
18
18
  ),
@@ -28,7 +28,7 @@ BreadcrumbItem.displayName = "BreadcrumbItem";
28
28
 
29
29
  const BreadcrumbLink = React.forwardRef<HTMLAnchorElement, React.ComponentProps<"a">>(
30
30
  ({ className, ...props }, ref) => (
31
- <a ref={ref} className={cn("transition-colors hover:text-taupe-900", className)} {...props} />
31
+ <a ref={ref} className={cn("transition-colors hover:text-ground-900", className)} {...props} />
32
32
  ),
33
33
  );
34
34
  BreadcrumbLink.displayName = "BreadcrumbLink";
@@ -39,7 +39,7 @@ const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentProps<"s
39
39
  ref={ref}
40
40
  role="link"
41
41
  aria-current="page"
42
- className={cn("body font-medium text-taupe-900", className)}
42
+ className={cn("body font-medium text-ground-900", className)}
43
43
  {...props}
44
44
  />
45
45
  ),
@@ -47,7 +47,7 @@ const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentProps<"s
47
47
  BreadcrumbPage.displayName = "BreadcrumbPage";
48
48
 
49
49
  const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<"li">) => (
50
- <li role="presentation" aria-hidden="true" className={cn("text-taupe-300", className)} {...props}>
50
+ <li role="presentation" aria-hidden="true" className={cn("text-ground-300", className)} {...props}>
51
51
  {children ?? <ChevronRight size={14} />}
52
52
  </li>
53
53
  );
@@ -60,7 +60,7 @@ const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<"span"
60
60
  className={cn("flex size-5 items-center justify-center", className)}
61
61
  {...props}
62
62
  >
63
- <MoreHorizontal size={14} className="text-taupe-400" />
63
+ <MoreHorizontal size={14} className="text-ground-400" />
64
64
  </span>
65
65
  );
66
66
  BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
@@ -10,7 +10,7 @@ function ButtonGroup({ children, className }: ButtonGroupProps) {
10
10
  return (
11
11
  <div
12
12
  className={cn(
13
- "inline-flex divide-x divide-taupe-200 overflow-hidden rounded-lg border border-taupe-200 bg-white shadow-natural",
13
+ "inline-flex divide-x divide-ground-200 overflow-hidden rounded-lg border border-ground-200 bg-white shadow-natural",
14
14
  className,
15
15
  )}
16
16
  >
@@ -29,10 +29,10 @@ function ButtonGroupItem({ active, className, children, ...props }: ButtonGroupI
29
29
  type="button"
30
30
  className={cn(
31
31
  "relative inline-flex items-center gap-1.5 px-3.5 py-2 body font-medium transition-colors",
32
- "focus:z-10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-taupe-400/40 focus-visible:ring-inset",
32
+ "focus:z-10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ground-400/40 focus-visible:ring-inset",
33
33
  active
34
- ? "bg-taupe-900 text-white"
35
- : "text-taupe-600 hover:bg-taupe-50 hover:text-taupe-900",
34
+ ? "bg-ground-900 text-white"
35
+ : "text-ground-600 hover:bg-ground-50 hover:text-ground-900",
36
36
  className,
37
37
  )}
38
38
  {...props}
@@ -17,12 +17,12 @@ const buttonVariants = cva(
17
17
  variant: {
18
18
  default: "bg-brand-primary text-white hover:bg-brand-primary/90 active:bg-brand-primary/80",
19
19
  destructive: "bg-red-600 text-white hover:bg-red-700 active:bg-red-800",
20
- outline: "bg-white text-taupe-700 shadow-natural hover:bg-taupe-50 rounded-xl",
21
- secondary: "bg-taupe-100 text-taupe-700 hover:bg-taupe-200",
20
+ outline: "bg-white text-ground-700 shadow-natural hover:bg-ground-50 rounded-xl",
21
+ secondary: "bg-ground-100 text-ground-700 hover:bg-ground-200",
22
22
  brand:
23
- "bg-brand-secondary text-taupe-900 hover:bg-brand-secondary/90 active:bg-brand-secondary/80",
24
- ghost: "text-taupe-600 hover:bg-taupe-100 hover:text-taupe-900",
25
- link: "text-taupe-900 underline-offset-4 hover:underline",
23
+ "bg-brand-secondary text-ground-900 hover:bg-brand-secondary/90 active:bg-brand-secondary/80",
24
+ ghost: "text-ground-600 hover:bg-ground-100 hover:text-ground-900",
25
+ link: "text-ground-900 underline-offset-4 hover:underline",
26
26
  },
27
27
  size: {
28
28
  default: "h-9 px-4 py-2 rounded-md",
@@ -56,5 +56,6 @@ function Button({ className, variant, size, asChild = false, ...props }: ButtonP
56
56
  />
57
57
  );
58
58
  }
59
+ Button.displayName = "Button";
59
60
 
60
61
  export { Button, buttonVariants };
@@ -16,35 +16,35 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C
16
16
  months: "flex flex-col sm:flex-row gap-4",
17
17
  month: "flex flex-col gap-4",
18
18
  month_caption: "flex justify-center pt-1 relative items-center px-10",
19
- caption_label: "body font-semibold text-taupe-900",
19
+ caption_label: "body font-semibold text-ground-900",
20
20
  nav: "flex items-center justify-between absolute inset-x-0 top-1",
21
21
  button_previous: cn(
22
22
  "absolute left-0 h-7 w-7 flex items-center justify-center rounded-md",
23
- "text-taupe-400 hover:bg-taupe-100 hover:text-taupe-700 transition-colors",
23
+ "text-ground-400 hover:bg-ground-100 hover:text-ground-700 transition-colors",
24
24
  ),
25
25
  button_next: cn(
26
26
  "absolute right-0 h-7 w-7 flex items-center justify-center rounded-md",
27
- "text-taupe-400 hover:bg-taupe-100 hover:text-taupe-700 transition-colors",
27
+ "text-ground-400 hover:bg-ground-100 hover:text-ground-700 transition-colors",
28
28
  ),
29
29
  month_grid: "w-full border-collapse mt-1",
30
30
  weekdays: "flex",
31
- weekday: "w-9 h-9 flex items-center justify-center label text-taupe-400 font-normal",
31
+ weekday: "w-9 h-9 flex items-center justify-center label text-ground-400 font-normal",
32
32
  week: "flex w-full mt-1",
33
33
  day: "relative p-0 text-center",
34
34
  day_button: cn(
35
35
  "h-9 w-9 flex items-center justify-center rounded-full body font-normal",
36
- "text-taupe-900 hover:bg-taupe-100 transition-colors",
36
+ "text-ground-900 hover:bg-ground-100 transition-colors",
37
37
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-primary/30",
38
38
  ),
39
39
  selected:
40
40
  "[&>button]:bg-brand-primary [&>button]:text-white [&>button]:hover:bg-brand-primary/90",
41
41
  today: "[&>button]:font-semibold [&>button]:text-brand-primary",
42
- outside: "opacity-40 [&>button]:text-taupe-400",
42
+ outside: "opacity-40 [&>button]:text-ground-400",
43
43
  disabled: "opacity-30 [&>button]:cursor-not-allowed",
44
44
  range_start: "[&>button]:bg-brand-primary [&>button]:text-white [&>button]:rounded-full",
45
45
  range_end: "[&>button]:bg-brand-primary [&>button]:text-white [&>button]:rounded-full",
46
46
  range_middle:
47
- "[&>button]:bg-brand-primary/15 [&>button]:text-taupe-900 [&>button]:rounded-none",
47
+ "[&>button]:bg-brand-primary/15 [&>button]:text-ground-900 [&>button]:rounded-none",
48
48
  hidden: "invisible",
49
49
  ...classNames,
50
50
  }}
@@ -21,15 +21,15 @@ function CardHeading({ title, description, actions, children, className }: CardH
21
21
  return (
22
22
  <div
23
23
  className={cn(
24
- "flex items-start justify-between gap-4 border-b border-taupe-100 px-5 py-4",
24
+ "flex items-start justify-between gap-4 border-b border-ground-100 px-5 py-4",
25
25
  className,
26
26
  )}
27
27
  >
28
28
  <div className="flex min-w-0 items-center gap-3">
29
29
  {children}
30
30
  <div className="min-w-0">
31
- <p className="body font-semibold text-taupe-900 truncate">{title}</p>
32
- {description && <p className="caption text-taupe-400 mt-0.5">{description}</p>}
31
+ <p className="body font-semibold text-ground-900 truncate">{title}</p>
32
+ {description && <p className="caption text-ground-400 mt-0.5">{description}</p>}
33
33
  </div>
34
34
  </div>
35
35
 
@@ -10,7 +10,7 @@ const cardVariants = cva("rounded-xl", {
10
10
  variants: {
11
11
  variant: {
12
12
  default: "bg-white shadow-natural",
13
- muted: "bg-taupe-50",
13
+ muted: "bg-ground-50",
14
14
  ghost: "bg-transparent",
15
15
  },
16
16
  },
@@ -54,7 +54,7 @@ const CardTitle = React.forwardRef<HTMLHeadingElement, React.ComponentProps<"h3"
54
54
  <h3
55
55
  ref={ref}
56
56
  data-slot="card-title"
57
- className={cn("subheading text-taupe-900", className)}
57
+ className={cn("subheading text-ground-900", className)}
58
58
  {...props}
59
59
  />
60
60
  ),
@@ -66,7 +66,7 @@ const CardDescription = React.forwardRef<HTMLParagraphElement, React.ComponentPr
66
66
  <p
67
67
  ref={ref}
68
68
  data-slot="card-description"
69
- className={cn("caption text-taupe-500", className)}
69
+ className={cn("caption text-ground-500", className)}
70
70
  {...props}
71
71
  />
72
72
  ),
@@ -3,15 +3,15 @@
3
3
  import * as React from "react";
4
4
  import { ResponsiveContainer, type TooltipContentProps } from "recharts";
5
5
  import { cn } from "../lib/utils";
6
+ import { tokens } from "../tokens/tokens";
6
7
 
7
- // Color palette for charts
8
8
  export const CHART_COLORS = {
9
- primary: "#FF4D01", // brand-primary
10
- secondary: "#CDEA19", // brand-secondary
11
- tertiary: "#FDE086", // brand-secondary
12
- muted: "#a8978a", // taupe-400
13
- subtle: "#e3dcd4", // taupe-200
14
- dark: "#26181a", // taupe-900
9
+ primary: tokens.brand.primary, // "#C100F1" — vivid purple
10
+ secondary: tokens.semantic.light.success, // "#CDEA19" — lime
11
+ tertiary: tokens.brand.secondary, // "#FFF5BF" — pale lemon
12
+ muted: tokens.ground[400], // "#a8978a"
13
+ subtle: tokens.ground[200], // "#e3dcd4"
14
+ dark: tokens.ground[900], // "#26181a"
15
15
  };
16
16
 
17
17
  interface ChartContainerProps {
@@ -39,16 +39,16 @@ interface ChartTooltipProps extends Partial<TooltipContentProps<number, string>>
39
39
  function ChartTooltip({ active, payload, label, labelClassName }: ChartTooltipProps) {
40
40
  if (!active || !payload?.length) return null;
41
41
  return (
42
- <div className="rounded-xl border border-taupe-100 bg-white px-3 py-2 shadow-elevated">
43
- {label && <p className={cn("mb-1 label text-taupe-400", labelClassName)}>{label}</p>}
42
+ <div className="rounded-xl border border-ground-100 bg-white px-3 py-2 shadow-elevated">
43
+ {label && <p className={cn("mb-1 label text-ground-400", labelClassName)}>{label}</p>}
44
44
  {payload.map((entry, i) => (
45
45
  <div key={i} className="flex items-center gap-2">
46
46
  <span
47
47
  className="inline-block h-2 w-2 rounded-full"
48
48
  style={{ backgroundColor: entry.color }}
49
49
  />
50
- <span className="caption text-taupe-500">{entry.name}:</span>
51
- <span className="caption font-medium text-taupe-900">{entry.value}</span>
50
+ <span className="caption text-ground-500">{entry.name}:</span>
51
+ <span className="caption font-medium text-ground-900">{entry.value}</span>
52
52
  </div>
53
53
  ))}
54
54
  </div>
@@ -12,7 +12,7 @@ const CheckboxRoot = React.forwardRef<
12
12
  <Checkbox.Root
13
13
  ref={ref}
14
14
  className={cn(
15
- "peer size-4 shrink-0 rounded border border-taupe-300 bg-white transition-colors",
15
+ "peer size-4 shrink-0 rounded border border-ground-300 bg-white transition-colors",
16
16
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-primary/30",
17
17
  "disabled:cursor-not-allowed disabled:opacity-50",
18
18
  "data-[state=checked]:bg-brand-primary data-[state=checked]:border-brand-primary",
@@ -42,7 +42,7 @@ function ColorInput({
42
42
  return (
43
43
  <div
44
44
  className={cn(
45
- "inline-flex h-8 items-stretch gap-0 rounded-md border border-taupe-200 bg-white overflow-hidden",
45
+ "inline-flex h-8 items-stretch gap-0 rounded-md border border-ground-200 bg-white overflow-hidden",
46
46
  "focus-within:ring-2 focus-within:ring-brand-primary/20 focus-within:border-brand-primary",
47
47
  disabled && "opacity-50 pointer-events-none",
48
48
  className,
@@ -51,8 +51,8 @@ function ColorInput({
51
51
  <ColorPicker
52
52
  value={value}
53
53
  onChange={onChange}
54
- presets={presets}
55
- disabled={disabled}
54
+ {...(presets !== undefined && { presets })}
55
+ {...(disabled !== undefined && { disabled })}
56
56
  className="h-full w-8 border-0 rounded-none focus-visible:ring-0"
57
57
  />
58
58
  <input
@@ -65,19 +65,19 @@ function ColorInput({
65
65
  commitHex("#" + (e.target as HTMLInputElement).value.replace(/^#/, ""));
66
66
  }}
67
67
  spellCheck={false}
68
- className="w-[5.5rem] caption text-taupe-900 px-2 bg-transparent border-l border-taupe-100 focus:outline-none uppercase"
68
+ className="w-[5.5rem] caption text-ground-900 px-2 bg-transparent border-l border-ground-100 focus:outline-none uppercase"
69
69
  />
70
70
  {typeof opacity === "number" && onOpacityChange && (
71
- <div className="relative flex items-center border-l border-taupe-100">
71
+ <div className="relative flex items-center border-l border-ground-100">
72
72
  <input
73
73
  type="number"
74
74
  min={0}
75
75
  max={100}
76
76
  value={Math.round(opacity)}
77
77
  onChange={(e) => onOpacityChange(Number(e.target.value))}
78
- className="w-12 caption text-taupe-900 px-2 bg-transparent focus:outline-none text-right [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
78
+ className="w-12 caption text-ground-900 px-2 bg-transparent focus:outline-none text-right [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
79
79
  />
80
- <span aria-hidden className="caption-xs text-taupe-400 pr-2">
80
+ <span aria-hidden className="caption-xs text-ground-400 pr-2">
81
81
  %
82
82
  </span>
83
83
  </div>
@@ -45,8 +45,8 @@ function ColorPicker({
45
45
  disabled={disabled}
46
46
  aria-label={ariaLabel}
47
47
  className={cn(
48
- "inline-flex h-8 w-8 items-center justify-center rounded-md border border-taupe-200 bg-white",
49
- "transition-colors hover:border-taupe-300",
48
+ "inline-flex h-8 w-8 items-center justify-center rounded-md border border-ground-200 bg-white",
49
+ "transition-colors hover:border-ground-300",
50
50
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-primary/20 focus-visible:border-brand-primary",
51
51
  "disabled:cursor-not-allowed disabled:opacity-50",
52
52
  className,
@@ -72,10 +72,10 @@ function ColorPicker({
72
72
  setHex(e.target.value);
73
73
  onChange(e.target.value);
74
74
  }}
75
- className="h-10 w-full cursor-pointer rounded-md border border-taupe-200 bg-white p-0.5"
75
+ className="h-10 w-full cursor-pointer rounded-md border border-ground-200 bg-white p-0.5"
76
76
  />
77
77
  <div className="mt-2 flex items-center gap-2">
78
- <span className="caption text-taupe-500">Hex</span>
78
+ <span className="caption text-ground-500">Hex</span>
79
79
  <input
80
80
  type="text"
81
81
  value={hex}
@@ -84,7 +84,7 @@ function ColorPicker({
84
84
  onKeyDown={(e) => {
85
85
  if (e.key === "Enter") commit((e.target as HTMLInputElement).value);
86
86
  }}
87
- className="flex-1 h-7 rounded-md border border-taupe-200 bg-white px-2 caption text-taupe-900 focus:outline-none focus:border-brand-primary"
87
+ className="flex-1 h-7 rounded-md border border-ground-200 bg-white px-2 caption text-ground-900 focus:outline-none focus:border-brand-primary"
88
88
  />
89
89
  </div>
90
90
  {presets && presets.length > 0 && (