@alpic-ai/ui 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/components/accordion-card.d.mts +41 -0
  2. package/dist/components/accordion-card.mjs +61 -0
  3. package/dist/components/accordion.d.mts +29 -0
  4. package/dist/components/accordion.mjs +48 -0
  5. package/dist/components/alert.d.mts +40 -0
  6. package/dist/components/alert.mjs +63 -0
  7. package/dist/components/attachment-tile.d.mts +26 -0
  8. package/dist/components/attachment-tile.mjs +35 -0
  9. package/dist/components/avatar.d.mts +52 -0
  10. package/dist/components/avatar.mjs +81 -0
  11. package/dist/components/badge.d.mts +20 -0
  12. package/dist/components/badge.mjs +36 -0
  13. package/dist/components/breadcrumb.d.mts +42 -0
  14. package/dist/components/breadcrumb.mjs +79 -0
  15. package/dist/components/button.d.mts +29 -0
  16. package/dist/components/button.mjs +67 -0
  17. package/dist/components/card.d.mts +37 -0
  18. package/dist/components/card.mjs +54 -0
  19. package/dist/components/checkbox.d.mts +11 -0
  20. package/dist/components/checkbox.mjs +26 -0
  21. package/dist/components/collapsible.d.mts +16 -0
  22. package/dist/components/collapsible.mjs +24 -0
  23. package/dist/components/combobox.d.mts +86 -0
  24. package/dist/components/combobox.mjs +207 -0
  25. package/dist/components/command.d.mts +38 -0
  26. package/dist/components/command.mjs +68 -0
  27. package/dist/components/copyable.d.mts +22 -0
  28. package/dist/components/copyable.mjs +33 -0
  29. package/dist/components/description-list.d.mts +22 -0
  30. package/dist/components/description-list.mjs +34 -0
  31. package/dist/components/dialog.d.mts +61 -0
  32. package/dist/components/dialog.mjs +110 -0
  33. package/dist/components/dropdown-menu.d.mts +72 -0
  34. package/dist/components/dropdown-menu.mjs +122 -0
  35. package/dist/components/input-group.d.mts +25 -0
  36. package/dist/components/input-group.mjs +43 -0
  37. package/dist/components/input.d.mts +27 -0
  38. package/dist/components/input.mjs +90 -0
  39. package/dist/components/label.d.mts +11 -0
  40. package/dist/components/label.mjs +14 -0
  41. package/dist/components/pagination.d.mts +18 -0
  42. package/dist/components/pagination.mjs +42 -0
  43. package/dist/components/popover.d.mts +22 -0
  44. package/dist/components/popover.mjs +34 -0
  45. package/dist/components/radio-group.d.mts +15 -0
  46. package/dist/components/radio-group.mjs +26 -0
  47. package/dist/components/scroll-area.d.mts +17 -0
  48. package/dist/components/scroll-area.mjs +35 -0
  49. package/dist/components/select-trigger-variants.d.mts +13 -0
  50. package/dist/components/select-trigger-variants.mjs +23 -0
  51. package/dist/components/select.d.mts +51 -0
  52. package/dist/components/select.mjs +95 -0
  53. package/dist/components/separator.d.mts +13 -0
  54. package/dist/components/separator.mjs +16 -0
  55. package/dist/components/sheet.d.mts +43 -0
  56. package/dist/components/sheet.mjs +74 -0
  57. package/dist/components/sidebar.d.mts +163 -0
  58. package/dist/components/sidebar.mjs +378 -0
  59. package/dist/components/skeleton.d.mts +16 -0
  60. package/dist/components/skeleton.mjs +21 -0
  61. package/dist/components/sonner.d.mts +29 -0
  62. package/dist/components/sonner.mjs +76 -0
  63. package/dist/components/spinner.d.mts +30 -0
  64. package/dist/components/spinner.mjs +46 -0
  65. package/dist/components/status-dot.d.mts +19 -0
  66. package/dist/components/status-dot.mjs +34 -0
  67. package/dist/components/switch.d.mts +11 -0
  68. package/dist/components/switch.mjs +18 -0
  69. package/dist/components/table.d.mts +38 -0
  70. package/dist/components/table.mjs +65 -0
  71. package/dist/components/tabs.d.mts +58 -0
  72. package/dist/components/tabs.mjs +119 -0
  73. package/dist/components/tag.d.mts +35 -0
  74. package/dist/components/tag.mjs +65 -0
  75. package/dist/components/textarea.d.mts +21 -0
  76. package/dist/components/textarea.mjs +44 -0
  77. package/dist/components/toggle-group.d.mts +28 -0
  78. package/dist/components/toggle-group.mjs +72 -0
  79. package/dist/components/tooltip-icon-button.d.mts +12 -0
  80. package/dist/components/tooltip-icon-button.mjs +27 -0
  81. package/dist/components/tooltip.d.mts +23 -0
  82. package/dist/components/tooltip.mjs +35 -0
  83. package/dist/hooks/use-copy-to-clipboard.d.mts +11 -0
  84. package/dist/hooks/use-copy-to-clipboard.mjs +24 -0
  85. package/dist/hooks/use-mobile.d.mts +4 -0
  86. package/dist/hooks/use-mobile.mjs +16 -0
  87. package/dist/lib/cn.d.mts +6 -0
  88. package/dist/lib/cn.mjs +8 -0
  89. package/package.json +88 -0
  90. package/src/components/accordion-card.tsx +103 -0
  91. package/src/components/accordion.tsx +63 -0
  92. package/src/components/alert.tsx +74 -0
  93. package/src/components/attachment-tile.tsx +68 -0
  94. package/src/components/avatar.tsx +127 -0
  95. package/src/components/badge.tsx +41 -0
  96. package/src/components/breadcrumb.tsx +98 -0
  97. package/src/components/button.tsx +106 -0
  98. package/src/components/card.tsx +62 -0
  99. package/src/components/checkbox.tsx +35 -0
  100. package/src/components/collapsible.tsx +18 -0
  101. package/src/components/combobox.tsx +393 -0
  102. package/src/components/command.tsx +112 -0
  103. package/src/components/copyable.tsx +47 -0
  104. package/src/components/description-list.tsx +36 -0
  105. package/src/components/dialog.tsx +161 -0
  106. package/src/components/dropdown-menu.tsx +234 -0
  107. package/src/components/input-group.tsx +97 -0
  108. package/src/components/input.tsx +145 -0
  109. package/src/components/label.tsx +20 -0
  110. package/src/components/pagination.tsx +53 -0
  111. package/src/components/popover.tsx +49 -0
  112. package/src/components/radio-group.tsx +33 -0
  113. package/src/components/scroll-area.tsx +48 -0
  114. package/src/components/select-trigger-variants.ts +28 -0
  115. package/src/components/select.tsx +186 -0
  116. package/src/components/separator.tsx +30 -0
  117. package/src/components/sheet.tsx +112 -0
  118. package/src/components/sidebar.tsx +682 -0
  119. package/src/components/skeleton.tsx +24 -0
  120. package/src/components/sonner.tsx +91 -0
  121. package/src/components/spinner.tsx +62 -0
  122. package/src/components/status-dot.tsx +33 -0
  123. package/src/components/switch.tsx +33 -0
  124. package/src/components/table.tsx +89 -0
  125. package/src/components/tabs.tsx +226 -0
  126. package/src/components/tag.tsx +82 -0
  127. package/src/components/textarea.tsx +70 -0
  128. package/src/components/toggle-group.tsx +96 -0
  129. package/src/components/tooltip-icon-button.tsx +33 -0
  130. package/src/components/tooltip.tsx +54 -0
  131. package/src/hooks/use-copy-to-clipboard.ts +27 -0
  132. package/src/hooks/use-mobile.ts +17 -0
  133. package/src/lib/cn.ts +6 -0
  134. package/src/styles/tokens.css +352 -0
@@ -0,0 +1,96 @@
1
+ "use client";
2
+
3
+ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
4
+ import { cva, type VariantProps } from "class-variance-authority";
5
+ import * as React from "react";
6
+
7
+ import { cn } from "../lib/cn";
8
+
9
+ const toggleGroupItemVariants = cva(
10
+ [
11
+ "inline-flex items-center justify-center gap-1 whitespace-nowrap",
12
+ "type-text-sm font-medium",
13
+ "transition-colors",
14
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background focus:z-10 focus-visible:z-10",
15
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
16
+ "disabled:pointer-events-none disabled:opacity-50",
17
+ ].join(" "),
18
+ {
19
+ variants: {
20
+ variant: {
21
+ default: [
22
+ "bg-transparent text-muted-foreground",
23
+ "data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
24
+ "[@media(hover:hover)]:hover:bg-background-hover [@media(hover:hover)]:hover:text-muted-foreground-hover",
25
+ ].join(" "),
26
+ outline: [
27
+ "border border-border bg-transparent text-muted-foreground",
28
+ "data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
29
+ "[@media(hover:hover)]:hover:bg-background-hover [@media(hover:hover)]:hover:text-muted-foreground-hover",
30
+ ].join(" "),
31
+ },
32
+ size: {
33
+ default: "h-8 px-2 min-w-8",
34
+ sm: "h-7 px-1.5 min-w-7",
35
+ },
36
+ },
37
+ defaultVariants: {
38
+ variant: "default",
39
+ size: "default",
40
+ },
41
+ },
42
+ );
43
+
44
+ type ToggleGroupContextValue = VariantProps<typeof toggleGroupItemVariants>;
45
+
46
+ const ToggleGroupContext = React.createContext<ToggleGroupContextValue>({
47
+ size: "default",
48
+ variant: "default",
49
+ });
50
+
51
+ function ToggleGroup({
52
+ className,
53
+ variant,
54
+ size,
55
+ children,
56
+ ...props
57
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & ToggleGroupContextValue) {
58
+ return (
59
+ <ToggleGroupPrimitive.Root
60
+ data-slot="toggle-group"
61
+ className={cn("group/toggle-group flex h-fit w-fit items-center rounded-md", className)}
62
+ {...props}
63
+ >
64
+ <ToggleGroupContext.Provider value={{ variant, size }}>{children}</ToggleGroupContext.Provider>
65
+ </ToggleGroupPrimitive.Root>
66
+ );
67
+ }
68
+
69
+ function ToggleGroupItem({
70
+ className,
71
+ children,
72
+ variant,
73
+ size,
74
+ ...props
75
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleGroupItemVariants>) {
76
+ const context = React.useContext(ToggleGroupContext);
77
+ const resolvedVariant = context.variant ?? variant;
78
+ const resolvedSize = context.size ?? size;
79
+
80
+ return (
81
+ <ToggleGroupPrimitive.Item
82
+ data-slot="toggle-group-item"
83
+ className={cn(
84
+ toggleGroupItemVariants({ variant: resolvedVariant, size: resolvedSize }),
85
+ "min-w-0 flex-1 shrink-0 rounded-none first:rounded-l-md last:rounded-r-md",
86
+ resolvedVariant === "outline" && "border-l-0 first:border-l",
87
+ className,
88
+ )}
89
+ {...props}
90
+ >
91
+ {children}
92
+ </ToggleGroupPrimitive.Item>
93
+ );
94
+ }
95
+
96
+ export { ToggleGroup, ToggleGroupItem, toggleGroupItemVariants };
@@ -0,0 +1,33 @@
1
+ "use client";
2
+
3
+ import { Slottable } from "@radix-ui/react-slot";
4
+ import { type ComponentPropsWithRef, forwardRef } from "react";
5
+
6
+ import { Button } from "./button";
7
+ import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip";
8
+
9
+ type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
10
+ tooltip: string;
11
+ side?: "top" | "bottom" | "left" | "right";
12
+ };
13
+
14
+ const TooltipIconButton = forwardRef<HTMLButtonElement, TooltipIconButtonProps>(
15
+ ({ children, tooltip, side = "bottom", ...rest }, ref) => {
16
+ return (
17
+ <Tooltip>
18
+ <TooltipTrigger asChild>
19
+ <Button size="icon" {...rest} ref={ref}>
20
+ <Slottable>{children}</Slottable>
21
+ <span className="sr-only">{tooltip}</span>
22
+ </Button>
23
+ </TooltipTrigger>
24
+ <TooltipContent side={side}>{tooltip}</TooltipContent>
25
+ </Tooltip>
26
+ );
27
+ },
28
+ );
29
+
30
+ TooltipIconButton.displayName = "TooltipIconButton";
31
+
32
+ export type { TooltipIconButtonProps };
33
+ export { TooltipIconButton };
@@ -0,0 +1,54 @@
1
+ "use client";
2
+
3
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
4
+ import type * as React from "react";
5
+
6
+ import { cn } from "../lib/cn";
7
+
8
+ function TooltipProvider({ delayDuration = 0, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
9
+ return <TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />;
10
+ }
11
+
12
+ function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
13
+ return (
14
+ <TooltipProvider>
15
+ <TooltipPrimitive.Root data-slot="tooltip" {...props} />
16
+ </TooltipProvider>
17
+ );
18
+ }
19
+
20
+ function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
21
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
22
+ }
23
+
24
+ function TooltipContent({
25
+ className,
26
+ sideOffset = 6,
27
+ children,
28
+ ...props
29
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
30
+ return (
31
+ <TooltipPrimitive.Portal>
32
+ <TooltipPrimitive.Content
33
+ data-slot="tooltip-content"
34
+ sideOffset={sideOffset}
35
+ className={cn(
36
+ "bg-inverted text-inverted-foreground dark:bg-subtle dark:text-foreground",
37
+ "z-50 w-fit rounded-md px-3 py-2 shadow-lg dark:shadow-none dark:drop-shadow-[0_0_0.5px_var(--color-border)]",
38
+ "type-text-xs font-semibold text-balance text-center",
39
+ "animate-in fade-in-0 zoom-in-95",
40
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
41
+ "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",
42
+ "origin-(--radix-tooltip-content-transform-origin)",
43
+ className,
44
+ )}
45
+ {...props}
46
+ >
47
+ {children}
48
+ <TooltipPrimitive.Arrow className="bg-inverted fill-inverted dark:bg-subtle dark:fill-subtle z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
49
+ </TooltipPrimitive.Content>
50
+ </TooltipPrimitive.Portal>
51
+ );
52
+ }
53
+
54
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
@@ -0,0 +1,27 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+
5
+ export function useCopyToClipboard({ resetDelay = 2000 }: { resetDelay?: number } = {}) {
6
+ const [isCopied, setIsCopied] = useState(false);
7
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
8
+
9
+ useEffect(() => {
10
+ return () => {
11
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
12
+ };
13
+ }, []);
14
+
15
+ const copy = useCallback(
16
+ (text: string) => {
17
+ navigator.clipboard.writeText(text).then(() => {
18
+ setIsCopied(true);
19
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
20
+ timeoutRef.current = setTimeout(() => setIsCopied(false), resetDelay);
21
+ });
22
+ },
23
+ [resetDelay],
24
+ );
25
+
26
+ return { copy, isCopied };
27
+ }
@@ -0,0 +1,17 @@
1
+ import * as React from "react";
2
+
3
+ const MOBILE_BREAKPOINT = 768;
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
10
+ const onChange = () => setIsMobile(mql.matches);
11
+ mql.addEventListener("change", onChange);
12
+ setIsMobile(mql.matches);
13
+ return () => mql.removeEventListener("change", onChange);
14
+ }, []);
15
+
16
+ return !!isMobile;
17
+ }
package/src/lib/cn.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,352 @@
1
+ /* ─── Color tokens ────────────────────────────────────────────────────────── */
2
+
3
+ @theme {
4
+ --font-sans: "Inter", system-ui, sans-serif;
5
+ --font-display: "Inter", sans-serif;
6
+ --font-body: "Inter", sans-serif;
7
+
8
+ --color-background: #ffffff; /* Figma: bg-primary */
9
+ --color-foreground: #121e1e; /* Figma: fg-primary */
10
+ --color-border: #acb8b8; /* Figma: border-primary */
11
+
12
+ --color-accent: #f1f5f5; /* Figma: bg-secondary */
13
+ --color-accent-foreground: #121e1e; /* Figma: fg-primary */
14
+
15
+ --color-muted: #f1f5f5; /* Figma: bg-secondary */
16
+ --color-muted-foreground: #3a4848; /* Figma: fg-secondary */
17
+
18
+ --color-shadow: #0000001a;
19
+
20
+ --color-inverted: #071718; /* Figma: bg-primary-solid */
21
+ --color-inverted-foreground: #ffffff; /* Figma: fg-white */
22
+
23
+ --color-primary-hover: #c70054; /* Figma: bg-brand-solid-hover */
24
+ --color-primary-hover-foreground: #ffffff;
25
+
26
+ --color-background-hover: #f1f5f5; /* Figma: bg-primary-hover */
27
+ --color-muted-foreground-hover: #232e2e; /* Figma: text-secondary-hover */
28
+ --color-link: #c70054; /* Figma: text-brand-secondary */
29
+ --color-link-muted: #536262; /* Figma: text-tertiary */
30
+
31
+ --color-primary: #e90060; /* Figma: bg-brand-solid */
32
+ --color-primary-foreground: #ffffff; /* Figma: fg-white */
33
+
34
+ --color-tertiary: #e90060; /* Figma: fg-brand-primary */
35
+
36
+ --color-destructive: #d92d20; /* Figma: bg-error-solid */
37
+ --color-destructive-hover: #b42318; /* Figma: bg-error-solid-hover */
38
+ --color-destructive-foreground: #ffffff;
39
+
40
+ --color-ring: #f22b79; /* Figma: focus-ring */
41
+
42
+ /* sidebar */
43
+ --color-sidebar: #f8fafa; /* Figma: bg-secondary-subtle */
44
+ --color-sidebar-foreground: #3a4848; /* Figma: fg-secondary */
45
+ --color-sidebar-primary: #121e1e; /* Figma: fg-primary */
46
+ --color-sidebar-primary-foreground: #ffffff;
47
+ --color-sidebar-accent: #f1f5f5; /* Figma: bg-secondary */
48
+ --color-sidebar-accent-foreground: #121e1e;
49
+ --color-sidebar-border: #e3eaea; /* Figma: border-tertiary */
50
+ --color-sidebar-ring: #f22b79; /* Figma: focus-ring */
51
+
52
+ /* card */
53
+ --color-card: #f8fafa; /* Figma: bg-secondary-subtle */
54
+ --color-card-foreground: #121e1e; /* Figma: fg-primary */
55
+
56
+ /* popover */
57
+ --color-popover: #ffffff; /* Figma: bg-primary */
58
+ --color-popover-foreground: #121e1e; /* Figma: fg-primary */
59
+
60
+ /* code editor */
61
+ --color-code: #ffffff;
62
+ --color-code-foreground: #121e1e;
63
+ --color-code-warning: #eab308;
64
+ --color-code-debug: #3b82f6;
65
+ --color-code-error: #d92d20; /* Figma: bg-error-solid */
66
+
67
+ /* surfaces */
68
+ --color-subtle: #e3eaea; /* Figma: bg-tertiary */
69
+ --color-subtle-foreground: #536262; /* Figma: fg-tertiary */
70
+
71
+ /* input */
72
+ --color-placeholder: #6f7f7f; /* Figma: text-placeholder */
73
+ --color-border-error: #fda29b; /* Figma: border-error-subtle */
74
+ --color-disabled: #f1f5f5; /* Figma: bg-disabled (lightened to distinguish from switch bg) */
75
+ --color-disabled-foreground: #6f7f7f; /* Figma: text-disabled */
76
+ --color-border-secondary: #c9d4d4; /* Figma: border-secondary */
77
+ --color-required: #ffaac9; /* Figma: text-secondary-on-brand */
78
+
79
+ /* badge */
80
+ --color-badge-success: #079455; /* Figma: fg-success-primary */
81
+ --color-badge-warning: #dc6803; /* Figma: fg-warning-primary */
82
+ --color-badge-error: #d92d20; /* Figma: fg-error-primary */
83
+
84
+ /* status */
85
+ --color-success: #079455; /* Figma: bg-success-solid */
86
+ --color-warning: #dc6803; /* Figma: bg-warning-solid */
87
+
88
+ /* tabs */
89
+ --color-quaternary-foreground: #6f7f7f; /* Figma: text-quaternary */
90
+
91
+ /* avatar */
92
+ --color-avatar-border: rgba(0, 0, 0, 0.08); /* Figma: border overlay on avatar image */
93
+ --color-avatar-online: #079455; /* Figma: bg-success-solid */
94
+
95
+ /* radius */
96
+ --radius-xs: 4px; /* Figma: radius-xs */
97
+ --radius-sm: 6px; /* Figma: radius-sm */
98
+ --radius-md: 8px; /* Figma: radius-md */
99
+ --radius-lg: 10px; /* Figma: radius-lg */
100
+ --radius-xl: 12px; /* Figma: radius-xl */
101
+ --radius-2xl: 16px; /* Figma: radius-2xl */
102
+
103
+ /* overlay */
104
+ --color-overlay: rgba(7, 23, 24, 0.7); /* Figma: bg-overlay at 70% */
105
+
106
+ /* animations */
107
+ --animate-accordion-down: accordion-down 200ms ease-out;
108
+ --animate-accordion-up: accordion-up 200ms ease-out;
109
+ }
110
+
111
+ @keyframes accordion-down {
112
+ from {
113
+ height: 0;
114
+ }
115
+ to {
116
+ height: var(--radix-accordion-content-height);
117
+ }
118
+ }
119
+
120
+ @keyframes accordion-up {
121
+ from {
122
+ height: var(--radix-accordion-content-height);
123
+ }
124
+ to {
125
+ height: 0;
126
+ }
127
+ }
128
+
129
+ /* ─── Dark mode ───────────────────────────────────────────────────────────── */
130
+
131
+ .dark {
132
+ --color-background: #071718; /* Figma: bg-primary */
133
+ --color-foreground: #ffffff; /* Figma: fg-primary */
134
+ --color-border: #213535; /* Figma: border-primary */
135
+
136
+ --color-accent: #0c1c1c; /* Figma: bg-secondary */
137
+ --color-accent-foreground: #ffffff;
138
+
139
+ --color-muted: #0c1c1c; /* Figma: bg-secondary */
140
+ --color-muted-foreground: #90a4a4; /* Figma: fg-secondary */
141
+
142
+ --color-shadow: #ffffff1a;
143
+
144
+ --color-inverted: #0c1c1c; /* Figma: bg-primary-solid */
145
+ --color-inverted-foreground: #ffffff; /* Figma: fg-white */
146
+
147
+ --color-primary-hover: #f22b79; /* Figma: bg-brand-solid-hover */
148
+ --color-primary-hover-foreground: #ffffff;
149
+
150
+ --color-background-hover: #162828; /* Figma: bg-primary-hover */
151
+ --color-muted-foreground-hover: #b8c8c8; /* Figma: text-secondary-hover */
152
+ --color-link: #90a4a4; /* Figma: text-brand-secondary */
153
+ --color-link-muted: #698080; /* Figma: text-tertiary */
154
+
155
+ --color-primary: #e90060; /* Figma: bg-brand-solid */
156
+ --color-primary-foreground: #ffffff; /* Figma: fg-white */
157
+
158
+ --color-tertiary: #f22b79; /* Figma: fg-brand-primary */
159
+
160
+ --color-destructive: #d92d20; /* Figma: bg-error-solid */
161
+ --color-destructive-foreground: #ffffff;
162
+ --color-destructive-hover: #f04438; /* Figma: bg-error-solid-hover */
163
+
164
+ --color-ring: #f22b79; /* Figma: focus-ring */
165
+
166
+ /* sidebar */
167
+ --color-sidebar: #0c1c1c; /* Figma: bg-secondary */
168
+ --color-sidebar-foreground: #90a4a4; /* Figma: fg-secondary */
169
+ --color-sidebar-primary: #ffffff; /* Figma: fg-primary */
170
+ --color-sidebar-primary-foreground: #071718;
171
+ --color-sidebar-accent: #162828; /* Figma: bg-tertiary */
172
+ --color-sidebar-accent-foreground: #ffffff;
173
+ --color-sidebar-border: #162828; /* Figma: border-tertiary */
174
+ --color-sidebar-ring: #f22b79; /* Figma: focus-ring */
175
+
176
+ /* card */
177
+ --color-card: #0c1c1c; /* Figma: bg-secondary */
178
+ --color-card-foreground: #ffffff;
179
+
180
+ /* popover */
181
+ --color-popover: #071718; /* Figma: bg-primary */
182
+ --color-popover-foreground: #ffffff; /* Figma: fg-primary */
183
+
184
+ /* surfaces */
185
+ --color-subtle: #243838; /* Figma: bg-tertiary (darkened to distinguish from disabled) */
186
+ --color-subtle-foreground: #698080; /* Figma: fg-tertiary */
187
+
188
+ /* input */
189
+ --color-placeholder: #465b5b; /* Figma: text-placeholder */
190
+ --color-border-error: #f04438; /* Figma: border-error-subtle */
191
+ --color-disabled: #162828; /* Figma: bg-disabled */
192
+ --color-disabled-foreground: #465b5b; /* Figma: text-disabled */
193
+ --color-border-secondary: #162828; /* Figma: border-secondary */
194
+ --color-required: #90a4a4; /* Figma: text-secondary-on-brand */
195
+
196
+ /* badge */
197
+ --color-badge-success: #17b26a; /* Figma: fg-success-primary */
198
+ --color-badge-warning: #f79009; /* Figma: fg-warning-primary */
199
+ --color-badge-error: #f04438; /* Figma: fg-error-primary */
200
+
201
+ /* status */
202
+ --color-success: #079455; /* Figma: bg-success-solid */
203
+ --color-warning: #dc6803; /* Figma: bg-warning-solid */
204
+
205
+ /* tabs */
206
+ --color-quaternary-foreground: #698080; /* Figma: text-quaternary */
207
+
208
+ /* avatar */
209
+ --color-avatar-border: rgba(255, 255, 255, 0.08); /* Figma: border overlay on avatar image */
210
+ --color-avatar-online: #17b26a; /* Figma: fg-success-secondary */
211
+
212
+ /* overlay */
213
+ --color-overlay: rgba(22, 40, 40, 0.7); /* Figma: bg-overlay at 70% */
214
+
215
+ /* code editor */
216
+ --color-code: #071718;
217
+ --color-code-foreground: #ffffff;
218
+ }
219
+
220
+ /* ─── Base layer ──────────────────────────────────────────────────────────── */
221
+
222
+ @custom-variant dark (&:where(.dark, .dark *));
223
+
224
+ @layer base {
225
+ * {
226
+ @apply border-border shadow-shadow;
227
+ }
228
+ body {
229
+ @apply bg-background text-foreground;
230
+ }
231
+ button,
232
+ a {
233
+ cursor: pointer;
234
+ }
235
+ }
236
+
237
+ /* ─── Typography ──────────────────────────────────────────────────────────── */
238
+
239
+ :root {
240
+ /* Font sizes — display */
241
+ --font-size-display-2xl: 72px;
242
+ --font-size-display-xl: 60px;
243
+ --font-size-display-lg: 48px;
244
+ --font-size-display-md: 36px;
245
+ --font-size-display-sm: 30px;
246
+ --font-size-display-xs: 24px;
247
+
248
+ /* Font sizes — text */
249
+ --font-size-text-xl: 20px;
250
+ --font-size-text-lg: 18px;
251
+ --font-size-text-md: 16px;
252
+ --font-size-text-sm: 14px;
253
+ --font-size-text-xs: 12px;
254
+
255
+ /* Line heights — display */
256
+ --line-height-display-2xl: 90px;
257
+ --line-height-display-xl: 72px;
258
+ --line-height-display-lg: 60px;
259
+ --line-height-display-md: 44px;
260
+ --line-height-display-sm: 38px;
261
+ --line-height-display-xs: 32px;
262
+
263
+ /* Line heights — text */
264
+ --line-height-text-xl: 30px;
265
+ --line-height-text-lg: 28px;
266
+ --line-height-text-md: 24px;
267
+ --line-height-text-sm: 20px;
268
+ --line-height-text-xs: 18px;
269
+
270
+ /* Letter spacing */
271
+ --tracking-display: -2px;
272
+ --tracking-normal: 0px;
273
+ }
274
+
275
+ /* ─── Type preset utilities ───────────────────────────────────────────────── */
276
+
277
+ @utility type-display-2xl {
278
+ font-family: var(--font-display);
279
+ font-size: var(--font-size-display-2xl);
280
+ line-height: var(--line-height-display-2xl);
281
+ letter-spacing: var(--tracking-display);
282
+ }
283
+
284
+ @utility type-display-xl {
285
+ font-family: var(--font-display);
286
+ font-size: var(--font-size-display-xl);
287
+ line-height: var(--line-height-display-xl);
288
+ letter-spacing: var(--tracking-display);
289
+ }
290
+
291
+ @utility type-display-lg {
292
+ font-family: var(--font-display);
293
+ font-size: var(--font-size-display-lg);
294
+ line-height: var(--line-height-display-lg);
295
+ letter-spacing: var(--tracking-display);
296
+ }
297
+
298
+ @utility type-display-md {
299
+ font-family: var(--font-display);
300
+ font-size: var(--font-size-display-md);
301
+ line-height: var(--line-height-display-md);
302
+ letter-spacing: var(--tracking-display);
303
+ }
304
+
305
+ @utility type-display-sm {
306
+ font-family: var(--font-display);
307
+ font-size: var(--font-size-display-sm);
308
+ line-height: var(--line-height-display-sm);
309
+ letter-spacing: var(--tracking-normal);
310
+ }
311
+
312
+ @utility type-display-xs {
313
+ font-family: var(--font-display);
314
+ font-size: var(--font-size-display-xs);
315
+ line-height: var(--line-height-display-xs);
316
+ letter-spacing: var(--tracking-normal);
317
+ }
318
+
319
+ @utility type-text-xl {
320
+ font-family: var(--font-body);
321
+ font-size: var(--font-size-text-xl);
322
+ line-height: var(--line-height-text-xl);
323
+ letter-spacing: var(--tracking-normal);
324
+ }
325
+
326
+ @utility type-text-lg {
327
+ font-family: var(--font-body);
328
+ font-size: var(--font-size-text-lg);
329
+ line-height: var(--line-height-text-lg);
330
+ letter-spacing: var(--tracking-normal);
331
+ }
332
+
333
+ @utility type-text-md {
334
+ font-family: var(--font-body);
335
+ font-size: var(--font-size-text-md);
336
+ line-height: var(--line-height-text-md);
337
+ letter-spacing: var(--tracking-normal);
338
+ }
339
+
340
+ @utility type-text-sm {
341
+ font-family: var(--font-body);
342
+ font-size: var(--font-size-text-sm);
343
+ line-height: var(--line-height-text-sm);
344
+ letter-spacing: var(--tracking-normal);
345
+ }
346
+
347
+ @utility type-text-xs {
348
+ font-family: var(--font-body);
349
+ font-size: var(--font-size-text-xs);
350
+ line-height: var(--line-height-text-xs);
351
+ letter-spacing: var(--tracking-normal);
352
+ }