@voltro/ui-shadcn 0.1.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.
- package/CHANGELOG.md +52 -0
- package/LICENSE +57 -0
- package/README.md +26 -0
- package/SECURITY.md +56 -0
- package/THIRD-PARTY-NOTICES.md +3016 -0
- package/dist/brand.d.ts +73 -0
- package/dist/brand.js +177 -0
- package/dist/cn.d.ts +11 -0
- package/dist/cn.js +6 -0
- package/dist/index.d.ts +1183 -0
- package/dist/index.js +2636 -0
- package/dist/tokens.css +532 -0
- package/package.json +64 -0
- package/src/brand/README.md +60 -0
- package/src/brand/assets/voltro-favicon.svg +30 -0
- package/src/brand/assets/voltro-icon-dark.svg +26 -0
- package/src/brand/assets/voltro-icon.svg +14 -0
- package/src/brand/assets/voltro-mark-mono.svg +5 -0
- package/src/brand/assets/voltro-mark.svg +14 -0
- package/src/brand/voltroLogo.tsx +244 -0
- package/src/cn.ts +10 -0
- package/src/compositions/appShell.tsx +72 -0
- package/src/compositions/codeCompare.tsx +88 -0
- package/src/compositions/docShell.tsx +112 -0
- package/src/compositions/docsLayout.tsx +577 -0
- package/src/compositions/featureBento.tsx +103 -0
- package/src/compositions/featureGrid.tsx +41 -0
- package/src/compositions/heroSection.tsx +55 -0
- package/src/compositions/landingCta.tsx +85 -0
- package/src/compositions/landingHero.tsx +174 -0
- package/src/compositions/landingStats.tsx +99 -0
- package/src/compositions/loginCard.tsx +139 -0
- package/src/compositions/pageHeader.tsx +58 -0
- package/src/compositions/profileMenu.tsx +316 -0
- package/src/compositions/siteFooter.tsx +250 -0
- package/src/compositions/themeToggle.tsx +82 -0
- package/src/cookies.ts +109 -0
- package/src/index.ts +160 -0
- package/src/primitives/animatedNumber.tsx +73 -0
- package/src/primitives/avatar.tsx +39 -0
- package/src/primitives/badge.tsx +39 -0
- package/src/primitives/button.tsx +53 -0
- package/src/primitives/callout.tsx +97 -0
- package/src/primitives/card.tsx +68 -0
- package/src/primitives/checkbox.tsx +55 -0
- package/src/primitives/codeBlock.tsx +134 -0
- package/src/primitives/codeWindow.tsx +84 -0
- package/src/primitives/dialog.tsx +43 -0
- package/src/primitives/docCard.tsx +109 -0
- package/src/primitives/docIcons.tsx +268 -0
- package/src/primitives/dropdownMenu.tsx +162 -0
- package/src/primitives/gridOverlay.tsx +51 -0
- package/src/primitives/highlightedCode.tsx +112 -0
- package/src/primitives/input.tsx +25 -0
- package/src/primitives/label.tsx +19 -0
- package/src/primitives/localeSwitcher.tsx +90 -0
- package/src/primitives/meshBackdrop.tsx +62 -0
- package/src/primitives/scrollReveal.tsx +70 -0
- package/src/primitives/searchModal.tsx +304 -0
- package/src/primitives/select.tsx +24 -0
- package/src/primitives/separator.tsx +24 -0
- package/src/primitives/skeleton.tsx +12 -0
- package/src/primitives/sparkles.tsx +105 -0
- package/src/primitives/steps.tsx +55 -0
- package/src/primitives/tabs.tsx +102 -0
- package/src/primitives/textarea.tsx +24 -0
- package/src/primitives/toast.tsx +44 -0
- package/src/primitives/tocScrollSpy.tsx +110 -0
- package/src/primitives/toggle.tsx +50 -0
- package/src/primitives/toggleGroup.tsx +62 -0
- package/src/tokens.css +532 -0
- package/src/widgets.tsx +297 -0
package/src/tokens.css
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
/* @voltro/ui-shadcn design tokens — Tailwind v4 + tw-animate-css + the full
|
|
2
|
+
* shadcn palette (light AND dark values) + the kit's ambient animations.
|
|
3
|
+
*
|
|
4
|
+
* Wiring, in your app's src/globals.css (see the styling docs,
|
|
5
|
+
* `routing/styling`):
|
|
6
|
+
*
|
|
7
|
+
* @import "@voltro/ui-shadcn/tokens.css";
|
|
8
|
+
* @source "./"; (your app's src)
|
|
9
|
+
* @source "../node_modules/@voltro/ui-shadcn/src"; (the kit sources)
|
|
10
|
+
*
|
|
11
|
+
* (Directory form shown — the equivalent glob form ending in
|
|
12
|
+
* "…src/**/*.{tsx,ts,jsx,js}" works too; it just can't be spelled
|
|
13
|
+
* inside this CSS comment.)
|
|
14
|
+
*
|
|
15
|
+
* The SECOND @source (the kit path) is MANDATORY when you render kit
|
|
16
|
+
* components: @source paths resolve relative to the IMPORTING css file, so
|
|
17
|
+
* the kit's own @source below expands to YOUR app's src once imported —
|
|
18
|
+
* kit-only classes are silently dropped without the explicit kit path. The
|
|
19
|
+
* published package ships src/ precisely so this path matches.
|
|
20
|
+
*
|
|
21
|
+
* Keep every @theme block ABOVE any @layer rules in the same stylesheet —
|
|
22
|
+
* a later @theme is silently dropped. */
|
|
23
|
+
|
|
24
|
+
@import "tailwindcss";
|
|
25
|
+
@import "tw-animate-css";
|
|
26
|
+
|
|
27
|
+
/* Tailwind v4 derives content from the Vite module graph; the framework's
|
|
28
|
+
Vite root is `<app>/.framework/`, not the app src — this glob (rebased to
|
|
29
|
+
the importing stylesheet, see the header) points the scanner at the
|
|
30
|
+
consuming app's src/. */
|
|
31
|
+
@source "./**/*.{tsx,ts,jsx,js}";
|
|
32
|
+
|
|
33
|
+
/* Canonical shadcn-style dark-mode trigger: any descendant of an
|
|
34
|
+
element with class `dark` inherits the dark token set. */
|
|
35
|
+
@custom-variant dark (&:is(.dark *));
|
|
36
|
+
|
|
37
|
+
:root {
|
|
38
|
+
--background: oklch(0.99 0 0);
|
|
39
|
+
--foreground: oklch(0 0 0);
|
|
40
|
+
--card: oklch(1 0 0);
|
|
41
|
+
--card-foreground: oklch(0 0 0);
|
|
42
|
+
--popover: oklch(0.99 0 0);
|
|
43
|
+
--popover-foreground: oklch(0 0 0);
|
|
44
|
+
--primary: oklch(0 0 0);
|
|
45
|
+
--primary-foreground: oklch(1 0 0);
|
|
46
|
+
--secondary: oklch(0.94 0 0);
|
|
47
|
+
--secondary-foreground: oklch(0 0 0);
|
|
48
|
+
--muted: oklch(0.97 0 0);
|
|
49
|
+
--muted-foreground: oklch(0.44 0 0);
|
|
50
|
+
--accent: oklch(0.94 0 0);
|
|
51
|
+
--accent-foreground: oklch(0 0 0);
|
|
52
|
+
--destructive: oklch(0.63 0.19 23.03);
|
|
53
|
+
--destructive-foreground: oklch(1 0 0);
|
|
54
|
+
--border: oklch(0.92 0 0);
|
|
55
|
+
--input: oklch(0.94 0 0);
|
|
56
|
+
--ring: oklch(0 0 0);
|
|
57
|
+
--chart-1: oklch(0.81 0.17 75.35);
|
|
58
|
+
--chart-2: oklch(0.55 0.22 264.53);
|
|
59
|
+
--chart-3: oklch(0.72 0 0);
|
|
60
|
+
--chart-4: oklch(0.92 0 0);
|
|
61
|
+
--chart-5: oklch(0.56 0 0);
|
|
62
|
+
--sidebar: oklch(0.99 0 0);
|
|
63
|
+
--sidebar-foreground: oklch(0 0 0);
|
|
64
|
+
--sidebar-primary: oklch(0 0 0);
|
|
65
|
+
--sidebar-primary-foreground: oklch(1 0 0);
|
|
66
|
+
--sidebar-accent: oklch(0.94 0 0);
|
|
67
|
+
--sidebar-accent-foreground: oklch(0 0 0);
|
|
68
|
+
--sidebar-border: oklch(0.94 0 0);
|
|
69
|
+
--sidebar-ring: oklch(0 0 0);
|
|
70
|
+
--font-sans: Geist, sans-serif;
|
|
71
|
+
--font-serif: Georgia, serif;
|
|
72
|
+
--font-mono: Geist Mono, monospace;
|
|
73
|
+
--radius: 0.5rem;
|
|
74
|
+
--shadow-x: 0px;
|
|
75
|
+
--shadow-y: 1px;
|
|
76
|
+
--shadow-blur: 2px;
|
|
77
|
+
--shadow-spread: 0px;
|
|
78
|
+
--shadow-opacity: 0.18;
|
|
79
|
+
--shadow-color: hsl(0 0% 0%);
|
|
80
|
+
--shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
|
|
81
|
+
--shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
|
|
82
|
+
--shadow-sm:
|
|
83
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
|
|
84
|
+
--shadow:
|
|
85
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
|
|
86
|
+
--shadow-md:
|
|
87
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18);
|
|
88
|
+
--shadow-lg:
|
|
89
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18);
|
|
90
|
+
--shadow-xl:
|
|
91
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18);
|
|
92
|
+
--shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45);
|
|
93
|
+
--tracking-normal: 0em;
|
|
94
|
+
--spacing: 0.25rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.dark {
|
|
98
|
+
--background: oklch(0 0 0);
|
|
99
|
+
--foreground: oklch(1 0 0);
|
|
100
|
+
--card: oklch(0.14 0 0);
|
|
101
|
+
--card-foreground: oklch(1 0 0);
|
|
102
|
+
--popover: oklch(0.18 0 0);
|
|
103
|
+
--popover-foreground: oklch(1 0 0);
|
|
104
|
+
--primary: oklch(1 0 0);
|
|
105
|
+
--primary-foreground: oklch(0 0 0);
|
|
106
|
+
--secondary: oklch(0.25 0 0);
|
|
107
|
+
--secondary-foreground: oklch(1 0 0);
|
|
108
|
+
--muted: oklch(0.23 0 0);
|
|
109
|
+
--muted-foreground: oklch(0.72 0 0);
|
|
110
|
+
--accent: oklch(0.32 0 0);
|
|
111
|
+
--accent-foreground: oklch(1 0 0);
|
|
112
|
+
--destructive: oklch(0.69 0.2 23.91);
|
|
113
|
+
--destructive-foreground: oklch(0 0 0);
|
|
114
|
+
--border: oklch(0.26 0 0);
|
|
115
|
+
--input: oklch(0.32 0 0);
|
|
116
|
+
--ring: oklch(0.72 0 0);
|
|
117
|
+
--chart-1: oklch(0.81 0.17 75.35);
|
|
118
|
+
--chart-2: oklch(0.58 0.21 260.84);
|
|
119
|
+
--chart-3: oklch(0.56 0 0);
|
|
120
|
+
--chart-4: oklch(0.44 0 0);
|
|
121
|
+
--chart-5: oklch(0.92 0 0);
|
|
122
|
+
--sidebar: oklch(0.18 0 0);
|
|
123
|
+
--sidebar-foreground: oklch(1 0 0);
|
|
124
|
+
--sidebar-primary: oklch(1 0 0);
|
|
125
|
+
--sidebar-primary-foreground: oklch(0 0 0);
|
|
126
|
+
--sidebar-accent: oklch(0.32 0 0);
|
|
127
|
+
--sidebar-accent-foreground: oklch(1 0 0);
|
|
128
|
+
--sidebar-border: oklch(0.32 0 0);
|
|
129
|
+
--sidebar-ring: oklch(0.72 0 0);
|
|
130
|
+
--font-sans: Geist, sans-serif;
|
|
131
|
+
--font-serif: Georgia, serif;
|
|
132
|
+
--font-mono: Geist Mono, monospace;
|
|
133
|
+
--radius: 0.5rem;
|
|
134
|
+
--shadow-x: 0px;
|
|
135
|
+
--shadow-y: 1px;
|
|
136
|
+
--shadow-blur: 2px;
|
|
137
|
+
--shadow-spread: 0px;
|
|
138
|
+
--shadow-opacity: 0.18;
|
|
139
|
+
--shadow-color: hsl(0 0% 0%);
|
|
140
|
+
--shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
|
|
141
|
+
--shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
|
|
142
|
+
--shadow-sm:
|
|
143
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
|
|
144
|
+
--shadow:
|
|
145
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
|
|
146
|
+
--shadow-md:
|
|
147
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18);
|
|
148
|
+
--shadow-lg:
|
|
149
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18);
|
|
150
|
+
--shadow-xl:
|
|
151
|
+
0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18);
|
|
152
|
+
--shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ---- Map the tokens above into Tailwind v4's @theme so utility
|
|
156
|
+
classes like `bg-background`, `text-muted-foreground`, etc.
|
|
157
|
+
resolve correctly. The `inline` keyword means the values are
|
|
158
|
+
used verbatim — no @media (prefers-color-scheme) inversion. ---- */
|
|
159
|
+
@theme inline {
|
|
160
|
+
--color-background: var(--background);
|
|
161
|
+
--color-foreground: var(--foreground);
|
|
162
|
+
--color-card: var(--card);
|
|
163
|
+
--color-card-foreground: var(--card-foreground);
|
|
164
|
+
--color-popover: var(--popover);
|
|
165
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
166
|
+
--color-primary: var(--primary);
|
|
167
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
168
|
+
--color-secondary: var(--secondary);
|
|
169
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
170
|
+
--color-muted: var(--muted);
|
|
171
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
172
|
+
--color-accent: var(--accent);
|
|
173
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
174
|
+
--color-destructive: var(--destructive);
|
|
175
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
176
|
+
--color-border: var(--border);
|
|
177
|
+
--color-input: var(--input);
|
|
178
|
+
--color-ring: var(--ring);
|
|
179
|
+
--color-chart-1: var(--chart-1);
|
|
180
|
+
--color-chart-2: var(--chart-2);
|
|
181
|
+
--color-chart-3: var(--chart-3);
|
|
182
|
+
--color-chart-4: var(--chart-4);
|
|
183
|
+
--color-chart-5: var(--chart-5);
|
|
184
|
+
--color-sidebar: var(--sidebar);
|
|
185
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
186
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
187
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
188
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
189
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
190
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
191
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
192
|
+
|
|
193
|
+
--font-sans: var(--font-sans);
|
|
194
|
+
--font-mono: var(--font-mono);
|
|
195
|
+
--font-serif: var(--font-serif);
|
|
196
|
+
|
|
197
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
198
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
199
|
+
--radius-lg: var(--radius);
|
|
200
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
201
|
+
|
|
202
|
+
--shadow-2xs: var(--shadow-2xs);
|
|
203
|
+
--shadow-xs: var(--shadow-xs);
|
|
204
|
+
--shadow-sm: var(--shadow-sm);
|
|
205
|
+
--shadow: var(--shadow);
|
|
206
|
+
--shadow-md: var(--shadow-md);
|
|
207
|
+
--shadow-lg: var(--shadow-lg);
|
|
208
|
+
--shadow-xl: var(--shadow-xl);
|
|
209
|
+
--shadow-2xl: var(--shadow-2xl);
|
|
210
|
+
|
|
211
|
+
/* Animation utilities — Tailwind v4 generates `animate-<name>`
|
|
212
|
+
* utilities from `--animate-<name>` registrations here. Keyframe
|
|
213
|
+
* definitions live further down (CSS doesn't care about order between
|
|
214
|
+
* @keyframes and the rule that references them, so the @theme block
|
|
215
|
+
* stays consolidated at the top to avoid the multi-@theme merge bug
|
|
216
|
+
* where blocks after @layer get silently dropped). */
|
|
217
|
+
--animate-mesh-drift-a: ui-mesh-drift-a 70s ease-in-out infinite;
|
|
218
|
+
--animate-mesh-drift-b: ui-mesh-drift-b 90s ease-in-out infinite;
|
|
219
|
+
--animate-mesh-drift-c: ui-mesh-drift-c 60s ease-in-out infinite;
|
|
220
|
+
--animate-caret-blink: ui-caret-blink 1s steps(2) infinite;
|
|
221
|
+
--animate-gradient-pan: ui-gradient-pan 8s ease-in-out infinite;
|
|
222
|
+
--animate-pulse-ring: ui-pulse-ring 2s ease-out infinite;
|
|
223
|
+
--animate-shimmer: ui-shimmer 2.5s linear infinite;
|
|
224
|
+
--animate-twinkle: ui-twinkle 6s ease-in-out infinite;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* Border-color reset in @layer components (NOT @layer base). Under Vite the
|
|
228
|
+
* consuming app's entry `@import "tailwindcss"` AND this kit's own
|
|
229
|
+
* `@import "tailwindcss"` inject Tailwind preflight TWICE; the duplicate
|
|
230
|
+
* `* { border: 0 solid }` (→ currentColor) lands AFTER a reset inside
|
|
231
|
+
* @layer base and wins, so every plain `border` renders as the text color
|
|
232
|
+
* (white in dark mode). @layer components beats @layer base (preflight) yet
|
|
233
|
+
* loses to @layer utilities, so `border-red-500` / `border-destructive` still
|
|
234
|
+
* override. (Bundler-dedup'd builds like Turbopack only ever see one
|
|
235
|
+
* preflight, so this is harmless there.) */
|
|
236
|
+
@layer components {
|
|
237
|
+
*,
|
|
238
|
+
::before,
|
|
239
|
+
::after {
|
|
240
|
+
border-color: var(--border);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@layer base {
|
|
245
|
+
html,
|
|
246
|
+
body {
|
|
247
|
+
background: var(--background);
|
|
248
|
+
color: var(--foreground);
|
|
249
|
+
font-family: var(--font-sans);
|
|
250
|
+
min-height: 100vh;
|
|
251
|
+
font-feature-settings:
|
|
252
|
+
"rlig" 1,
|
|
253
|
+
"calt" 1;
|
|
254
|
+
}
|
|
255
|
+
/* Reserve scrollbar gutter unconditionally. Without this, short
|
|
256
|
+
* pages have no vertical scrollbar and long pages do — the resulting
|
|
257
|
+
* ~15px viewport-width difference shifts every `mx-auto max-w-7xl`
|
|
258
|
+
* container by ~7-8px between page navigations. Centered brand
|
|
259
|
+
* marks and nav rows visibly jump on route change. `stable` reserves
|
|
260
|
+
* the gutter even when no scrollbar is rendered, so layout is
|
|
261
|
+
* page-length-independent. */
|
|
262
|
+
html {
|
|
263
|
+
scrollbar-gutter: stable;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* Pointer cursor on every actionable element. Tailwind v4 dropped
|
|
267
|
+
* the Preflight rule that gave `<button>` `cursor: pointer`,
|
|
268
|
+
* matching macOS/Windows native button behaviour. Most apps in this
|
|
269
|
+
* repo expect web-style pointer affordance on anything clickable
|
|
270
|
+
* (buttons, role="button" divs, summary, label[for]). Re-enable
|
|
271
|
+
* here so every plain `<button>` in a consumer app picks it up
|
|
272
|
+
* without per-component opt-in. `:not(:disabled)` keeps disabled
|
|
273
|
+
* buttons at default (paired with shadcn's `disabled:pointer-events-none`). */
|
|
274
|
+
button:not(:disabled),
|
|
275
|
+
[role="button"]:not([aria-disabled="true"]),
|
|
276
|
+
[role="menuitem"]:not([aria-disabled="true"]),
|
|
277
|
+
summary,
|
|
278
|
+
label[for] {
|
|
279
|
+
cursor: pointer;
|
|
280
|
+
}
|
|
281
|
+
body {
|
|
282
|
+
margin: 0;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* Cross-browser custom scrollbars. Thin, theme-aware, the thumb
|
|
286
|
+
* brightens on hover. Same visual outcome as a Radix ScrollArea
|
|
287
|
+
* but with zero JS + no extra DOM. Applies to every scrollable
|
|
288
|
+
* element (sidebars, code blocks, the page itself); add
|
|
289
|
+
* `.scrollbar-default` on any element to opt out. */
|
|
290
|
+
* {
|
|
291
|
+
/* Firefox */
|
|
292
|
+
scrollbar-width: thin;
|
|
293
|
+
scrollbar-color: var(--border) transparent;
|
|
294
|
+
}
|
|
295
|
+
*::-webkit-scrollbar {
|
|
296
|
+
width: 10px;
|
|
297
|
+
height: 10px;
|
|
298
|
+
}
|
|
299
|
+
*::-webkit-scrollbar-track {
|
|
300
|
+
background: transparent;
|
|
301
|
+
}
|
|
302
|
+
*::-webkit-scrollbar-thumb {
|
|
303
|
+
background: var(--border);
|
|
304
|
+
border-radius: 999px;
|
|
305
|
+
border: 2px solid transparent;
|
|
306
|
+
background-clip: padding-box;
|
|
307
|
+
transition: background-color 120ms ease;
|
|
308
|
+
}
|
|
309
|
+
*::-webkit-scrollbar-thumb:hover {
|
|
310
|
+
background-color: var(--muted-foreground);
|
|
311
|
+
background-clip: padding-box;
|
|
312
|
+
}
|
|
313
|
+
*::-webkit-scrollbar-corner {
|
|
314
|
+
background: transparent;
|
|
315
|
+
}
|
|
316
|
+
.scrollbar-default {
|
|
317
|
+
scrollbar-width: auto;
|
|
318
|
+
scrollbar-color: auto;
|
|
319
|
+
}
|
|
320
|
+
.scrollbar-default::-webkit-scrollbar {
|
|
321
|
+
width: revert;
|
|
322
|
+
height: revert;
|
|
323
|
+
}
|
|
324
|
+
.scrollbar-default::-webkit-scrollbar-thumb {
|
|
325
|
+
background: revert;
|
|
326
|
+
border: revert;
|
|
327
|
+
border-radius: revert;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.font-tabular {
|
|
332
|
+
font-variant-numeric: tabular-nums;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/* ---- Cinematic ambient animations ----
|
|
336
|
+
* Slow drifting blobs, blinking caret, gradient pan. All transform-
|
|
337
|
+
* only (GPU-composited), all motion-safe via the `motion-safe:`
|
|
338
|
+
* Tailwind variant on the consumer. Durations are deliberately long
|
|
339
|
+
* (45–90s) so motion feels ambient, not "loud". */
|
|
340
|
+
|
|
341
|
+
@keyframes ui-mesh-drift-a {
|
|
342
|
+
0%,
|
|
343
|
+
100% {
|
|
344
|
+
transform: translate3d(0, 0, 0) scale(1);
|
|
345
|
+
}
|
|
346
|
+
33% {
|
|
347
|
+
transform: translate3d(8vw, 4vh, 0) scale(1.05);
|
|
348
|
+
}
|
|
349
|
+
66% {
|
|
350
|
+
transform: translate3d(-4vw, 8vh, 0) scale(0.95);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
@keyframes ui-mesh-drift-b {
|
|
354
|
+
0%,
|
|
355
|
+
100% {
|
|
356
|
+
transform: translate3d(0, 0, 0) scale(1);
|
|
357
|
+
}
|
|
358
|
+
33% {
|
|
359
|
+
transform: translate3d(-6vw, -5vh, 0) scale(1.08);
|
|
360
|
+
}
|
|
361
|
+
66% {
|
|
362
|
+
transform: translate3d(4vw, -8vh, 0) scale(0.92);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
@keyframes ui-mesh-drift-c {
|
|
366
|
+
0%,
|
|
367
|
+
100% {
|
|
368
|
+
transform: translate(-50%, 0) scale(1);
|
|
369
|
+
}
|
|
370
|
+
50% {
|
|
371
|
+
transform: translate(-50%, -8vh) scale(1.1);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
@keyframes ui-caret-blink {
|
|
375
|
+
0%,
|
|
376
|
+
50% {
|
|
377
|
+
opacity: 1;
|
|
378
|
+
}
|
|
379
|
+
51%,
|
|
380
|
+
100% {
|
|
381
|
+
opacity: 0;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
@keyframes ui-gradient-pan {
|
|
385
|
+
0%,
|
|
386
|
+
100% {
|
|
387
|
+
background-position: 0% 50%;
|
|
388
|
+
}
|
|
389
|
+
50% {
|
|
390
|
+
background-position: 100% 50%;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
@keyframes ui-pulse-ring {
|
|
394
|
+
0% {
|
|
395
|
+
transform: scale(0.6);
|
|
396
|
+
opacity: 0;
|
|
397
|
+
}
|
|
398
|
+
20% {
|
|
399
|
+
transform: scale(0.7);
|
|
400
|
+
opacity: 0.4;
|
|
401
|
+
}
|
|
402
|
+
100% {
|
|
403
|
+
transform: scale(1.3);
|
|
404
|
+
opacity: 0;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
@keyframes ui-shimmer {
|
|
408
|
+
0% {
|
|
409
|
+
transform: translateX(-100%);
|
|
410
|
+
}
|
|
411
|
+
100% {
|
|
412
|
+
transform: translateX(200%);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
@keyframes ui-twinkle {
|
|
416
|
+
/* Twinkle = restrained opacity ramp + a hint of scale. Caps at
|
|
417
|
+
* opacity 0.7 so the dot never fully solidifies (would read as a
|
|
418
|
+
* UI element, not ambient sparkle). Stays at 0 for 30% of the
|
|
419
|
+
* cycle so different dots feel arrhythmic. */
|
|
420
|
+
0%,
|
|
421
|
+
30%,
|
|
422
|
+
100% {
|
|
423
|
+
opacity: 0;
|
|
424
|
+
transform: scale(0.6);
|
|
425
|
+
}
|
|
426
|
+
55% {
|
|
427
|
+
opacity: 0.7;
|
|
428
|
+
transform: scale(1);
|
|
429
|
+
}
|
|
430
|
+
75% {
|
|
431
|
+
opacity: 0.3;
|
|
432
|
+
transform: scale(0.85);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/* ---- Shiki dual-theme switch ----
|
|
437
|
+
* `HighlightedCode` (and any direct codeToHtml caller using
|
|
438
|
+
* `themes: { light, dark }` + `defaultColor: false`) emits inline
|
|
439
|
+
* styles like `--shiki-light:#xxx; --shiki-dark:#yyy` on every
|
|
440
|
+
* token span. The rules below resolve those CSS vars to the actual
|
|
441
|
+
* color/bg, picking the LIGHT set by default and DARK under `.dark`.
|
|
442
|
+
*
|
|
443
|
+
* Background goes ONLY on the <pre> — putting it on inner spans too
|
|
444
|
+
* paints the per-line `<span class="line">` elements with the theme
|
|
445
|
+
* bg, which then visibly banded against the surrounding wrapper
|
|
446
|
+
* (CodeBlock figure / CodeWindow chrome) because the colours are
|
|
447
|
+
* close-but-not-identical. Spans keep the color rule so per-token
|
|
448
|
+
* syntax highlighting still works. */
|
|
449
|
+
pre.shiki {
|
|
450
|
+
background-color: var(--shiki-light-bg) !important;
|
|
451
|
+
color: var(--shiki-light) !important;
|
|
452
|
+
}
|
|
453
|
+
pre.shiki span {
|
|
454
|
+
color: var(--shiki-light) !important;
|
|
455
|
+
}
|
|
456
|
+
.dark pre.shiki {
|
|
457
|
+
background-color: var(--shiki-dark-bg) !important;
|
|
458
|
+
color: var(--shiki-dark) !important;
|
|
459
|
+
}
|
|
460
|
+
.dark pre.shiki span {
|
|
461
|
+
color: var(--shiki-dark) !important;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/* Heading with hand-painted gradient text. Use on display-size <h1>
|
|
465
|
+
* elements: `<h1 className="text-gradient">…</h1>`. Combines well
|
|
466
|
+
* with motion-safe animate-gradient-pan for the cinematic pan effect. */
|
|
467
|
+
.text-gradient {
|
|
468
|
+
background-image: linear-gradient(
|
|
469
|
+
100deg,
|
|
470
|
+
var(--foreground) 0%,
|
|
471
|
+
oklch(0.75 0.18 290) 50%,
|
|
472
|
+
var(--foreground) 100%
|
|
473
|
+
);
|
|
474
|
+
background-size: 200% auto;
|
|
475
|
+
-webkit-background-clip: text;
|
|
476
|
+
background-clip: text;
|
|
477
|
+
-webkit-text-fill-color: transparent;
|
|
478
|
+
color: transparent;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/* ---- Stagger entrance for grids ----
|
|
482
|
+
* `.stagger-in > *` fades + slides up with a 40ms delay between
|
|
483
|
+
* children. Used by DocCards (and reusable for any grid). Respects
|
|
484
|
+
* prefers-reduced-motion. */
|
|
485
|
+
@keyframes ui-stagger-in {
|
|
486
|
+
from {
|
|
487
|
+
opacity: 0;
|
|
488
|
+
transform: translateY(8px);
|
|
489
|
+
}
|
|
490
|
+
to {
|
|
491
|
+
opacity: 1;
|
|
492
|
+
transform: translateY(0);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
.stagger-in > * {
|
|
496
|
+
animation: ui-stagger-in 320ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
|
|
497
|
+
}
|
|
498
|
+
.stagger-in > *:nth-child(1) {
|
|
499
|
+
animation-delay: 0ms;
|
|
500
|
+
}
|
|
501
|
+
.stagger-in > *:nth-child(2) {
|
|
502
|
+
animation-delay: 40ms;
|
|
503
|
+
}
|
|
504
|
+
.stagger-in > *:nth-child(3) {
|
|
505
|
+
animation-delay: 80ms;
|
|
506
|
+
}
|
|
507
|
+
.stagger-in > *:nth-child(4) {
|
|
508
|
+
animation-delay: 120ms;
|
|
509
|
+
}
|
|
510
|
+
.stagger-in > *:nth-child(5) {
|
|
511
|
+
animation-delay: 160ms;
|
|
512
|
+
}
|
|
513
|
+
.stagger-in > *:nth-child(6) {
|
|
514
|
+
animation-delay: 200ms;
|
|
515
|
+
}
|
|
516
|
+
.stagger-in > *:nth-child(7) {
|
|
517
|
+
animation-delay: 240ms;
|
|
518
|
+
}
|
|
519
|
+
.stagger-in > *:nth-child(8) {
|
|
520
|
+
animation-delay: 280ms;
|
|
521
|
+
}
|
|
522
|
+
.stagger-in > *:nth-child(9) {
|
|
523
|
+
animation-delay: 320ms;
|
|
524
|
+
}
|
|
525
|
+
.stagger-in > *:nth-child(n + 10) {
|
|
526
|
+
animation-delay: 360ms;
|
|
527
|
+
}
|
|
528
|
+
@media (prefers-reduced-motion: reduce) {
|
|
529
|
+
.stagger-in > * {
|
|
530
|
+
animation: none;
|
|
531
|
+
}
|
|
532
|
+
}
|