@alpic-ai/ui 0.0.0-dev.85c8341 → 0.0.0-dev.862c47d
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.
- package/dist/components/avatar.d.mts +1 -1
- package/dist/components/button.d.mts +3 -1
- package/dist/components/button.mjs +20 -6
- package/dist/components/combobox.mjs +1 -1
- package/dist/components/dialog.mjs +2 -2
- package/dist/components/github-button.d.mts +13 -0
- package/dist/components/github-button.mjs +24 -0
- package/dist/components/page-loader.d.mts +11 -0
- package/dist/components/page-loader.mjs +122 -0
- package/dist/components/select.d.mts +1 -9
- package/dist/components/select.mjs +8 -28
- package/dist/components/shimmer-text.d.mts +12 -0
- package/dist/components/shimmer-text.mjs +22 -0
- package/dist/components/sidebar.mjs +65 -21
- package/dist/components/table.d.mts +10 -1
- package/dist/components/table.mjs +4 -4
- package/dist/components/typography.d.mts +34 -0
- package/dist/components/typography.mjs +29 -0
- package/package.json +15 -15
- package/src/components/button.tsx +13 -9
- package/src/components/combobox.tsx +19 -7
- package/src/components/dialog.tsx +2 -2
- package/src/components/github-button.tsx +34 -0
- package/src/components/page-loader.tsx +59 -0
- package/src/components/select.tsx +2 -35
- package/src/components/shimmer-text.tsx +23 -0
- package/src/components/sidebar.tsx +64 -27
- package/src/components/table.tsx +17 -4
- package/src/components/typography.tsx +19 -0
- package/src/hooks/use-copy-to-clipboard.ts +6 -2
- package/src/stories/button.stories.tsx +23 -1
- package/src/stories/sidebar.stories.tsx +11 -8
- package/src/stories/table.stories.tsx +2 -2
- package/src/styles/tokens.css +217 -0
package/src/components/table.tsx
CHANGED
|
@@ -44,7 +44,6 @@ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|
|
44
44
|
"border-b border-border-secondary transition-colors",
|
|
45
45
|
"data-[state=selected]:bg-muted",
|
|
46
46
|
"[@media(hover:hover)]:hover:bg-background-hover dark:[@media(hover:hover)]:hover:bg-muted",
|
|
47
|
-
"[@media(hover:hover)]:[&:hover_button:hover]:bg-subtle",
|
|
48
47
|
className,
|
|
49
48
|
)}
|
|
50
49
|
{...props}
|
|
@@ -58,7 +57,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
|
58
57
|
data-slot="table-head"
|
|
59
58
|
className={cn(
|
|
60
59
|
"h-11 px-6 py-3 bg-muted text-left align-middle type-text-xs font-semibold text-placeholder dark:text-subtle-foreground whitespace-nowrap",
|
|
61
|
-
"[&:has([role=checkbox])]:w-px [&:has([role=checkbox])]:
|
|
60
|
+
"[&:has([role=checkbox])]:w-px [&:has([role=checkbox])]:px-0",
|
|
62
61
|
className,
|
|
63
62
|
)}
|
|
64
63
|
{...props}
|
|
@@ -66,11 +65,25 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
|
66
65
|
);
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
interface TableCellProps extends React.ComponentProps<"td"> {
|
|
69
|
+
/**
|
|
70
|
+
* When true, the cell renders edge-to-edge so the child can act as the
|
|
71
|
+
* interactive surface (e.g. a button or popover trigger filling the cell).
|
|
72
|
+
* Defaults to false (standard padded cell).
|
|
73
|
+
*/
|
|
74
|
+
interactive?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function TableCell({ className, interactive = false, ...props }: TableCellProps) {
|
|
70
78
|
return (
|
|
71
79
|
<td
|
|
72
80
|
data-slot="table-cell"
|
|
73
|
-
className={cn(
|
|
81
|
+
className={cn(
|
|
82
|
+
"align-middle",
|
|
83
|
+
interactive ? "h-px p-0" : "px-6 py-2",
|
|
84
|
+
"[&:has([role=checkbox])]:w-px [&:has([role=checkbox])]:px-0",
|
|
85
|
+
className,
|
|
86
|
+
)}
|
|
74
87
|
{...props}
|
|
75
88
|
/>
|
|
76
89
|
);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../lib/cn";
|
|
4
|
+
|
|
5
|
+
export function H1({ children, className }: { children: ReactNode; className?: string }) {
|
|
6
|
+
return <h1 className={cn("scroll-m-20 type-display-sm font-bold", className)}>{children}</h1>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function H2({ children, className }: { children: ReactNode; className?: string }) {
|
|
10
|
+
return <h2 className={cn("scroll-m-20 type-display-xs font-semibold", className)}>{children}</h2>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function H3({ children, className }: { children: ReactNode; className?: string }) {
|
|
14
|
+
return <h3 className={cn("scroll-m-20 type-text-lg font-semibold", className)}>{children}</h3>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function H4({ children, className }: { children: ReactNode; className?: string }) {
|
|
18
|
+
return <h4 className={cn("scroll-m-20 type-text-md font-semibold", className)}>{children}</h4>;
|
|
19
|
+
}
|
|
@@ -8,7 +8,9 @@ export function useCopyToClipboard({ resetDelay = 2000 }: { resetDelay?: number
|
|
|
8
8
|
|
|
9
9
|
useEffect(() => {
|
|
10
10
|
return () => {
|
|
11
|
-
if (timeoutRef.current)
|
|
11
|
+
if (timeoutRef.current) {
|
|
12
|
+
clearTimeout(timeoutRef.current);
|
|
13
|
+
}
|
|
12
14
|
};
|
|
13
15
|
}, []);
|
|
14
16
|
|
|
@@ -16,7 +18,9 @@ export function useCopyToClipboard({ resetDelay = 2000 }: { resetDelay?: number
|
|
|
16
18
|
(text: string) => {
|
|
17
19
|
navigator.clipboard.writeText(text).then(() => {
|
|
18
20
|
setIsCopied(true);
|
|
19
|
-
if (timeoutRef.current)
|
|
21
|
+
if (timeoutRef.current) {
|
|
22
|
+
clearTimeout(timeoutRef.current);
|
|
23
|
+
}
|
|
20
24
|
timeoutRef.current = setTimeout(() => setIsCopied(false), resetDelay);
|
|
21
25
|
});
|
|
22
26
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Plus } from "lucide-react";
|
|
1
|
+
import { ArrowRight, Plus, Sparkles } from "lucide-react";
|
|
2
2
|
|
|
3
3
|
import { Button } from "../components/button";
|
|
4
4
|
|
|
@@ -323,6 +323,28 @@ export const AllVariants = () => {
|
|
|
323
323
|
</Button>
|
|
324
324
|
</div>
|
|
325
325
|
|
|
326
|
+
{/* ── CTA (animated gradient ring) ────────────────────────────────── */}
|
|
327
|
+
<span className={SECTION_HEADER}>CTA — animated</span>
|
|
328
|
+
<p className="type-text-xs text-muted-foreground -mt-2 max-w-md">
|
|
329
|
+
Hover to rotate the conic gradient around the border and ignite the soft halo.
|
|
330
|
+
</p>
|
|
331
|
+
|
|
332
|
+
<div className="flex items-center gap-6">
|
|
333
|
+
<Button variant="cta" iconTrailing={<ArrowRight />}>
|
|
334
|
+
Get started
|
|
335
|
+
</Button>
|
|
336
|
+
<Button variant="cta" icon={<Sparkles />} iconTrailing={<ArrowRight />}>
|
|
337
|
+
Launch server
|
|
338
|
+
</Button>
|
|
339
|
+
<Button variant="cta">Deploy now</Button>
|
|
340
|
+
<Button variant="cta" iconTrailing={<ArrowRight />} disabled>
|
|
341
|
+
Disabled
|
|
342
|
+
</Button>
|
|
343
|
+
<Button variant="cta" iconTrailing={<ArrowRight />} loading>
|
|
344
|
+
Deploying
|
|
345
|
+
</Button>
|
|
346
|
+
</div>
|
|
347
|
+
|
|
326
348
|
{/* ── asChild ─────────────────────────────────────────────────────── */}
|
|
327
349
|
<span className={SECTION_HEADER}>asChild</span>
|
|
328
350
|
|
|
@@ -62,7 +62,7 @@ export const AllVariants: Story = () => (
|
|
|
62
62
|
<Sidebar collapsible="icon">
|
|
63
63
|
<TeamHeader />
|
|
64
64
|
<SidebarContent>
|
|
65
|
-
<SidebarGroup
|
|
65
|
+
<SidebarGroup>
|
|
66
66
|
<SidebarGroupContent>
|
|
67
67
|
<SidebarMenu>
|
|
68
68
|
<SidebarMenuItem>
|
|
@@ -107,7 +107,8 @@ export const AllVariants: Story = () => (
|
|
|
107
107
|
<UserFooter />
|
|
108
108
|
</Sidebar>
|
|
109
109
|
<SidebarInset>
|
|
110
|
-
<div className="p-4">
|
|
110
|
+
<div className="flex items-center gap-2 p-4">
|
|
111
|
+
<SidebarTrigger />
|
|
111
112
|
<span className="type-text-sm text-muted-foreground">Sub-menus expand inline under their parent</span>
|
|
112
113
|
</div>
|
|
113
114
|
</SidebarInset>
|
|
@@ -118,7 +119,7 @@ export const AllVariants: Story = () => (
|
|
|
118
119
|
<Sidebar collapsible="icon">
|
|
119
120
|
<TeamHeader />
|
|
120
121
|
<SidebarContent>
|
|
121
|
-
<SidebarGroup
|
|
122
|
+
<SidebarGroup>
|
|
122
123
|
<SidebarGroupLabel>Workspace</SidebarGroupLabel>
|
|
123
124
|
<SidebarGroupContent>
|
|
124
125
|
<SidebarMenu>
|
|
@@ -146,7 +147,7 @@ export const AllVariants: Story = () => (
|
|
|
146
147
|
</SidebarGroupContent>
|
|
147
148
|
</SidebarGroup>
|
|
148
149
|
<SidebarSeparator />
|
|
149
|
-
<SidebarGroup
|
|
150
|
+
<SidebarGroup>
|
|
150
151
|
<SidebarGroupLabel>Account</SidebarGroupLabel>
|
|
151
152
|
<SidebarGroupContent>
|
|
152
153
|
<SidebarMenu>
|
|
@@ -169,7 +170,8 @@ export const AllVariants: Story = () => (
|
|
|
169
170
|
<UserFooter />
|
|
170
171
|
</Sidebar>
|
|
171
172
|
<SidebarInset>
|
|
172
|
-
<div className="p-4">
|
|
173
|
+
<div className="flex items-center gap-2 p-4">
|
|
174
|
+
<SidebarTrigger />
|
|
173
175
|
<span className="type-text-sm text-muted-foreground">Groups with labels, badges, and separator</span>
|
|
174
176
|
</div>
|
|
175
177
|
</SidebarInset>
|
|
@@ -180,7 +182,7 @@ export const AllVariants: Story = () => (
|
|
|
180
182
|
<Sidebar collapsible="icon">
|
|
181
183
|
<TeamHeader />
|
|
182
184
|
<SidebarContent>
|
|
183
|
-
<SidebarGroup
|
|
185
|
+
<SidebarGroup>
|
|
184
186
|
<SidebarGroupContent>
|
|
185
187
|
<SidebarMenu>
|
|
186
188
|
{["skeleton-1", "skeleton-2", "skeleton-3", "skeleton-4", "skeleton-5"].map((key) => (
|
|
@@ -195,7 +197,8 @@ export const AllVariants: Story = () => (
|
|
|
195
197
|
<UserFooter />
|
|
196
198
|
</Sidebar>
|
|
197
199
|
<SidebarInset>
|
|
198
|
-
<div className="p-4">
|
|
200
|
+
<div className="flex items-center gap-2 p-4">
|
|
201
|
+
<SidebarTrigger />
|
|
199
202
|
<span className="type-text-sm text-muted-foreground">Loading state with skeleton placeholders</span>
|
|
200
203
|
</div>
|
|
201
204
|
</SidebarInset>
|
|
@@ -214,7 +217,7 @@ export const AllVariants: Story = () => (
|
|
|
214
217
|
</div>
|
|
215
218
|
</SidebarHeader>
|
|
216
219
|
<SidebarContent>
|
|
217
|
-
<SidebarGroup
|
|
220
|
+
<SidebarGroup>
|
|
218
221
|
<SidebarGroupContent>
|
|
219
222
|
<SidebarMenu>
|
|
220
223
|
<SidebarMenuItem>
|
|
@@ -190,8 +190,8 @@ export const AllVariants: Story = () => (
|
|
|
190
190
|
</TableRow>
|
|
191
191
|
</TableHeader>
|
|
192
192
|
<TableBody>
|
|
193
|
-
{USERS.slice(0, 3).map((user,
|
|
194
|
-
<TableRow key={user.id} data-state={
|
|
193
|
+
{USERS.slice(0, 3).map((user, index) => (
|
|
194
|
+
<TableRow key={user.id} data-state={index === 1 ? "selected" : undefined}>
|
|
195
195
|
<TableCell className="font-medium text-foreground">{user.name}</TableCell>
|
|
196
196
|
<TableCell className="text-subtle-foreground">{user.role}</TableCell>
|
|
197
197
|
<TableCell className="text-subtle-foreground">{user.email}</TableCell>
|
package/src/styles/tokens.css
CHANGED
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
|
|
40
40
|
--color-ring: #f22b79; /* Figma: focus-ring */
|
|
41
41
|
|
|
42
|
+
/* cta — decorative gradient accent, used with --color-primary in the CTA button ring */
|
|
43
|
+
--color-cta-accent: #6eece7; /* Figma: CTA border accent (cyan) */
|
|
44
|
+
|
|
42
45
|
/* sidebar */
|
|
43
46
|
--color-sidebar: #f8fafa; /* Figma: bg-secondary-subtle */
|
|
44
47
|
--color-sidebar-foreground: #3a4848; /* Figma: fg-secondary */
|
|
@@ -106,6 +109,26 @@
|
|
|
106
109
|
/* animations */
|
|
107
110
|
--animate-accordion-down: accordion-down 200ms ease-out;
|
|
108
111
|
--animate-accordion-up: accordion-up 200ms ease-out;
|
|
112
|
+
--animate-beacon-ring-core: beacon-ring-core 2.2s ease-in-out infinite;
|
|
113
|
+
--animate-beacon-ring-pulse: beacon-ring-pulse 2.2s ease-in-out infinite;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@keyframes shimmer-text {
|
|
117
|
+
from {
|
|
118
|
+
background-position: 100% center;
|
|
119
|
+
}
|
|
120
|
+
to {
|
|
121
|
+
background-position: 0% center;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@keyframes alpic-ride {
|
|
126
|
+
0% {
|
|
127
|
+
transform: translate(0px, 0px);
|
|
128
|
+
}
|
|
129
|
+
100% {
|
|
130
|
+
transform: translate(237px, -64px);
|
|
131
|
+
}
|
|
109
132
|
}
|
|
110
133
|
|
|
111
134
|
@keyframes accordion-down {
|
|
@@ -126,6 +149,184 @@
|
|
|
126
149
|
}
|
|
127
150
|
}
|
|
128
151
|
|
|
152
|
+
@keyframes beacon-ring-core {
|
|
153
|
+
0%,
|
|
154
|
+
100% {
|
|
155
|
+
opacity: 0.55;
|
|
156
|
+
transform: scale(0.98);
|
|
157
|
+
}
|
|
158
|
+
50% {
|
|
159
|
+
opacity: 0.85;
|
|
160
|
+
transform: scale(1.02);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@keyframes beacon-ring-pulse {
|
|
165
|
+
0%,
|
|
166
|
+
100% {
|
|
167
|
+
opacity: 0.55;
|
|
168
|
+
transform: scale(1);
|
|
169
|
+
}
|
|
170
|
+
50% {
|
|
171
|
+
opacity: 0.9;
|
|
172
|
+
transform: scale(1.02);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* ─── CTA button — animated conic gradient ring ───────────────────────────── */
|
|
177
|
+
|
|
178
|
+
@property --cta-angle {
|
|
179
|
+
syntax: "<angle>";
|
|
180
|
+
inherits: false;
|
|
181
|
+
initial-value: 135deg;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@keyframes cta-rotate {
|
|
185
|
+
to {
|
|
186
|
+
--cta-angle: 495deg;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.button-cta {
|
|
191
|
+
position: relative;
|
|
192
|
+
isolation: isolate;
|
|
193
|
+
/* light mode: whisper-of-gradient surface tint + soft rose drop-shadow */
|
|
194
|
+
background-image: linear-gradient(
|
|
195
|
+
135deg,
|
|
196
|
+
color-mix(in oklab, var(--color-primary) 5%, transparent) 0%,
|
|
197
|
+
color-mix(in oklab, var(--color-cta-accent) 5%, transparent) 100%
|
|
198
|
+
);
|
|
199
|
+
box-shadow:
|
|
200
|
+
0 6px 24px -10px color-mix(in oklab, var(--color-primary) 38%, transparent),
|
|
201
|
+
0 2px 6px -4px color-mix(in oklab, var(--color-cta-accent) 30%, transparent);
|
|
202
|
+
transition:
|
|
203
|
+
box-shadow 400ms ease,
|
|
204
|
+
transform 300ms ease,
|
|
205
|
+
filter 300ms ease;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@media (hover: hover) {
|
|
209
|
+
.button-cta:hover {
|
|
210
|
+
box-shadow:
|
|
211
|
+
0 10px 30px -8px color-mix(in oklab, var(--color-primary) 52%, transparent),
|
|
212
|
+
0 3px 10px -3px color-mix(in oklab, var(--color-cta-accent) 40%, transparent);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* dark mode: solid inverted surface, no tint or shadow — let the halo do the work */
|
|
217
|
+
.dark .button-cta {
|
|
218
|
+
background-image: none;
|
|
219
|
+
box-shadow: none;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.button-cta::before,
|
|
223
|
+
.button-cta::after {
|
|
224
|
+
content: "";
|
|
225
|
+
position: absolute;
|
|
226
|
+
inset: 0;
|
|
227
|
+
border-radius: inherit;
|
|
228
|
+
pointer-events: none;
|
|
229
|
+
/* Always "running" in browser terms, but paused at rest — freezes at current
|
|
230
|
+
angle on unhover instead of snapping back. */
|
|
231
|
+
animation: cta-rotate 3.2s linear infinite;
|
|
232
|
+
animation-play-state: paused;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Gradient ring (masked so only the border shows) */
|
|
236
|
+
.button-cta::before {
|
|
237
|
+
padding: 1.5px;
|
|
238
|
+
background: conic-gradient(
|
|
239
|
+
from var(--cta-angle),
|
|
240
|
+
var(--color-cta-accent) 0deg,
|
|
241
|
+
var(--color-primary) 150deg,
|
|
242
|
+
var(--color-cta-accent) 300deg,
|
|
243
|
+
var(--color-cta-accent) 360deg
|
|
244
|
+
);
|
|
245
|
+
-webkit-mask:
|
|
246
|
+
linear-gradient(#000 0 0) content-box,
|
|
247
|
+
linear-gradient(#000 0 0);
|
|
248
|
+
-webkit-mask-composite: xor;
|
|
249
|
+
mask-composite: exclude;
|
|
250
|
+
transition: filter 400ms ease;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* Blurred glow halo behind the button — subtle in light, bolder in dark */
|
|
254
|
+
.button-cta::after {
|
|
255
|
+
z-index: -1;
|
|
256
|
+
background: conic-gradient(
|
|
257
|
+
from var(--cta-angle),
|
|
258
|
+
var(--color-cta-accent) 0deg,
|
|
259
|
+
var(--color-primary) 150deg,
|
|
260
|
+
var(--color-cta-accent) 300deg,
|
|
261
|
+
var(--color-cta-accent) 360deg
|
|
262
|
+
);
|
|
263
|
+
filter: blur(12px);
|
|
264
|
+
opacity: 0.05;
|
|
265
|
+
transition: opacity 400ms ease;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.dark .button-cta::after {
|
|
269
|
+
opacity: 0.14;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
@media (hover: hover) {
|
|
273
|
+
.button-cta:hover::before,
|
|
274
|
+
.button-cta:hover::after {
|
|
275
|
+
animation-play-state: running;
|
|
276
|
+
}
|
|
277
|
+
.button-cta:hover::before {
|
|
278
|
+
filter: saturate(1.15) brightness(1.05);
|
|
279
|
+
}
|
|
280
|
+
.button-cta:hover::after {
|
|
281
|
+
opacity: 0.18;
|
|
282
|
+
}
|
|
283
|
+
.dark .button-cta:hover::after {
|
|
284
|
+
opacity: 0.32;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.button-cta:focus-visible::before,
|
|
289
|
+
.button-cta:focus-visible::after {
|
|
290
|
+
animation-play-state: running;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.button-cta:disabled::before,
|
|
294
|
+
.button-cta:disabled::after,
|
|
295
|
+
[aria-busy="true"].button-cta::before,
|
|
296
|
+
[aria-busy="true"].button-cta::after {
|
|
297
|
+
animation-play-state: paused;
|
|
298
|
+
}
|
|
299
|
+
.button-cta:disabled::after {
|
|
300
|
+
opacity: 0;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
@media (prefers-reduced-motion: reduce) {
|
|
304
|
+
.button-cta::before,
|
|
305
|
+
.button-cta::after {
|
|
306
|
+
animation: none;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* Icon slide on hover (applied to [data-cta-icon-trailing]) */
|
|
311
|
+
.button-cta [data-cta-icon-trailing] {
|
|
312
|
+
transition: transform 300ms cubic-bezier(0.2, 0.8, 0.2, 1);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
@media (hover: hover) {
|
|
316
|
+
.button-cta:hover [data-cta-icon-trailing] {
|
|
317
|
+
transform: translateX(2px);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
@media (prefers-reduced-motion: reduce) {
|
|
322
|
+
.button-cta [data-cta-icon-trailing] {
|
|
323
|
+
transition: none;
|
|
324
|
+
}
|
|
325
|
+
.button-cta:hover [data-cta-icon-trailing] {
|
|
326
|
+
transform: none;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
129
330
|
/* ─── Dark mode ───────────────────────────────────────────────────────────── */
|
|
130
331
|
|
|
131
332
|
.dark {
|
|
@@ -163,6 +364,9 @@
|
|
|
163
364
|
|
|
164
365
|
--color-ring: #f22b79; /* Figma: focus-ring */
|
|
165
366
|
|
|
367
|
+
/* cta — decorative gradient accent, used with --color-primary in the CTA button ring */
|
|
368
|
+
--color-cta-accent: #6eece7; /* Figma: CTA border accent (cyan) */
|
|
369
|
+
|
|
166
370
|
/* sidebar */
|
|
167
371
|
--color-sidebar: #0c1c1c; /* Figma: bg-secondary */
|
|
168
372
|
--color-sidebar-foreground: #90a4a4; /* Figma: fg-secondary */
|
|
@@ -221,6 +425,14 @@
|
|
|
221
425
|
|
|
222
426
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
223
427
|
|
|
428
|
+
:root {
|
|
429
|
+
--gradient-sidebar: linear-gradient(0deg, #c9e2e280 0%, #ffffff 70%); /* Figma: bg-nav-gradiant-light */
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.dark {
|
|
433
|
+
--gradient-sidebar: linear-gradient(0deg, #213535 0%, #121e1e 70%); /* Figma: bg-nav-gradiant-dark */
|
|
434
|
+
}
|
|
435
|
+
|
|
224
436
|
@layer base {
|
|
225
437
|
* {
|
|
226
438
|
@apply border-border shadow-shadow;
|
|
@@ -274,6 +486,11 @@
|
|
|
274
486
|
|
|
275
487
|
/* ─── Type preset utilities ───────────────────────────────────────────────── */
|
|
276
488
|
|
|
489
|
+
@utility bg-sidebar-surface {
|
|
490
|
+
background-color: var(--color-background);
|
|
491
|
+
background-image: var(--gradient-sidebar);
|
|
492
|
+
}
|
|
493
|
+
|
|
277
494
|
@utility type-display-2xl {
|
|
278
495
|
font-family: var(--font-display);
|
|
279
496
|
font-size: var(--font-size-display-2xl);
|