@usetheo/ui 0.35.3 → 0.36.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.
@@ -0,0 +1,315 @@
1
+ /* Theo UI — Design System "Violet Forge" tokens.
2
+ *
3
+ * Tokens normativos. Não edite valores aqui sem revisão do design system.
4
+ * Referência: docs/design-system.md
5
+ *
6
+ * Estratégia:
7
+ * - CSS custom properties para todas as cores, scales e durations.
8
+ * - Default é light. Dark é ativado via [data-theme="dark"] ou .dark.
9
+ * - HSL split (h s l) em vez de hex permite alpha via color-mix() ou hsl(var(--x) / .5).
10
+ *
11
+ * Roxo Theo: #A855F7 → oklch(0.628 0.225 296) (electric violet — unified 2026-06-09)
12
+ * Burnt sienna: #C96442 → hsl(15 54% 53%)
13
+ */
14
+
15
+ /* `:root` and `[data-theme="dark"]` declarations are intentionally NOT wrapped
16
+ * in `@layer base` so they apply at the document level regardless of whether
17
+ * the consumer's CSS pipeline runs Tailwind's preflight. The texture utilities
18
+ * below remain in `@layer utilities` because that layer affects ordering only,
19
+ * not the cascade root.
20
+ */
21
+ :root {
22
+ /* Base palette ------------------------------------------------------- *
23
+ * Neutrals are 100% desaturated (Vercel-style). Color comes from the
24
+ * primary (violet) + accent (burnt sienna) tokens below — never from
25
+ * surface tints.
26
+ */
27
+ --background: oklch(1 0 0); /* #FFFFFF */
28
+ --foreground: oklch(0.146 0 0); /* #0A0A0A */
29
+
30
+ --card: oklch(1 0 0); /* #FFFFFF */
31
+ --card-foreground: oklch(0.146 0 0);
32
+
33
+ --popover: oklch(1 0 0);
34
+ --popover-foreground: oklch(0.146 0 0);
35
+
36
+ /* Primary — Theo violet (equity) ------------------------------------- *
37
+ * Post-T3.1 (ADR-0006): -deep and -glow are derived algorithmically via
38
+ * OKLCH relative-color syntax. Themes that need a per-token override may
39
+ * still declare these explicitly — the cascade resolves the override.
40
+ * `max()`/`min()` clamps protect dark/light themes from L overflow (EC-7).
41
+ */
42
+ --primary: oklch(0.628 0.225 296); /* #A855F7 — Theo violet electric (unified 2026-06-09) */
43
+ --primary-deep: oklch(from var(--primary) max(0.05, calc(l - 0.16)) c h);
44
+ --primary-glow: oklch(from var(--primary) min(0.95, calc(l + 0.18)) c h);
45
+ --primary-foreground: oklch(1 0 0);
46
+
47
+ /* Secondary — neutral muted ----------------------------------------- */
48
+ --secondary: oklch(0.97 0 0); /* #F5F5F5 */
49
+ --secondary-foreground: oklch(0.146 0 0);
50
+
51
+ /* Accent — burnt sienna --------------------------------------------- *
52
+ * T3.1: accent-deep derived. Override path identical to primary.
53
+ */
54
+ --accent: oklch(0.621 0.132 39); /* #C96442 */
55
+ --accent-deep: oklch(from var(--accent) max(0.05, calc(l - 0.13)) c h);
56
+ --accent-foreground: oklch(1 0 0);
57
+
58
+ /* Muted ------------------------------------------------------------- */
59
+ --muted: oklch(0.97 0 0);
60
+ --muted-foreground: oklch(0.555 0 0); /* #737373 */
61
+
62
+ /* Surfaces, borders, inputs ----------------------------------------- */
63
+ --border: oklch(0.931 0 0); /* #E8E8E8 — Vercel-style hairline */
64
+ --input: oklch(0.931 0 0);
65
+ --ring: oklch(0.628 0.225 296); /* matches primary */
66
+
67
+ /* Semantics --------------------------------------------------------- */
68
+ --success: oklch(0.611 0.161 149.7); /* #16A34A */
69
+ --success-foreground: oklch(1 0 0);
70
+ --warning: oklch(0.67 0.154 60.6); /* #D97706 */
71
+ --warning-foreground: oklch(1 0 0);
72
+ --destructive: oklch(0.579 0.214 27.2); /* #DC2626 */
73
+ --destructive-foreground: oklch(1 0 0);
74
+ --info: oklch(0.626 0.186 259.6); /* #3B82F6 */
75
+ --info-foreground: oklch(1 0 0);
76
+
77
+ /* Status (D4 — operational state group) ----------------------------- *
78
+ * Separate from semantic group (success/destructive/warning/info, which
79
+ * are action-result colors). Status describes component liveness:
80
+ * online (alive), offline (dead), degraded (alive-but-slow), info (flag).
81
+ * Defaults mirror semantic counterparts; themes override for distinction.
82
+ */
83
+ --status-online: oklch(0.611 0.161 149.7);
84
+ --status-online-foreground: oklch(1 0 0);
85
+ --status-offline: oklch(0.579 0.214 27.2);
86
+ --status-offline-foreground: oklch(1 0 0);
87
+ --status-degraded: oklch(0.67 0.154 60.6);
88
+ --status-degraded-foreground: oklch(1 0 0);
89
+ --status-info: oklch(0.626 0.186 259.6);
90
+ --status-info-foreground: oklch(1 0 0);
91
+
92
+ /* Radii ------------------------------------------------------------- */
93
+ --radius-none: 0px;
94
+ --radius-sm: 4px;
95
+ --radius-md: 6px;
96
+ --radius-lg: 10px;
97
+ --radius-xl: 14px;
98
+ --radius-2xl: 20px;
99
+ --radius-full: 9999px;
100
+ /* shadcn compat */
101
+ --radius: 14px;
102
+
103
+ /* Spacing scale (4px base) ------------------------------------------ */
104
+ --space-1: 4px;
105
+ --space-2: 8px;
106
+ --space-3: 12px;
107
+ --space-4: 16px;
108
+ --space-5: 20px;
109
+ --space-6: 24px;
110
+ --space-8: 32px;
111
+ --space-10: 40px;
112
+ --space-12: 48px;
113
+ --space-16: 64px;
114
+ --space-20: 80px;
115
+ --space-24: 96px;
116
+ --space-32: 128px;
117
+
118
+ /* Elevation — theme-aware (uses --foreground for shadow ink,
119
+ * --primary for the signature glow, so swapping themes recolors them).
120
+ * Post-T2.5: tokens are OKLCH; we compose alpha via color-mix(in oklch, ...)
121
+ * which is perceptually correct AND works with any color-space variable.
122
+ */
123
+ --shadow-sm: 0 1px 2px 0 color-mix(in oklch, var(--foreground) 6%, transparent);
124
+ --shadow-md: 0 2px 8px -2px color-mix(in oklch, var(--foreground) 8%, transparent), 0 1px 3px
125
+ color-mix(in oklch, var(--foreground) 6%, transparent);
126
+ --shadow-lg: 0 12px 32px -8px color-mix(in oklch, var(--foreground) 12%, transparent), 0 4px 12px
127
+ color-mix(in oklch, var(--foreground) 8%, transparent);
128
+ --shadow-glow: 0 0 24px color-mix(in oklch, var(--primary) 25%, transparent);
129
+ --shadow-glow-strong: 0 0 32px color-mix(in oklch, var(--primary) 40%, transparent);
130
+
131
+ /* Motion ------------------------------------------------------------ */
132
+ --ease-out-soft: cubic-bezier(0.22, 1, 0.36, 1);
133
+ --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
134
+ --ease-snap: cubic-bezier(0.85, 0, 0.15, 1);
135
+ --duration-fast: 120ms;
136
+ --duration-base: 200ms;
137
+ --duration-slow: 360ms;
138
+ --stagger: 60ms;
139
+
140
+ /* Typography (Geist family — Vercel-inspired Violet Forge) ---------- */
141
+ --font-display: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
142
+ --font-body: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
143
+ --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
144
+ }
145
+
146
+ /* Dark mode — dominante --------------------------------------------- *
147
+ * Vercel-aligned grayscale: pure neutrals (0% saturation) for every
148
+ * surface and text layer. Color only in primary (violet), accent (burnt
149
+ * sienna), and semantic tokens (success/warning/destructive/info).
150
+ *
151
+ * Activated exclusively via the `.dark` class on `<html>` (set by
152
+ * `ThemeProvider`, `ThemeScript`, or consumers manually). The previous
153
+ * `[data-theme="dark"]` companion selector was dead — `data-theme` holds
154
+ * the theme NAME, never the literal `"dark"`.
155
+ */
156
+ .dark {
157
+ --background: oklch(0.146 0 0); /* #0A0A0A */
158
+ --foreground: oklch(0.97 0 0); /* #F5F5F5 */
159
+
160
+ --card: oklch(0.182 0 0); /* #121212 */
161
+ --card-foreground: oklch(0.97 0 0);
162
+
163
+ --popover: oklch(0.204 0 0); /* #171717 */
164
+ --popover-foreground: oklch(0.97 0 0);
165
+
166
+ --primary: oklch(0.628 0.225 296);
167
+ --primary-deep: oklch(from var(--primary) max(0.05, calc(l - 0.16)) c h);
168
+ --primary-glow: oklch(from var(--primary) min(0.95, calc(l + 0.18)) c h);
169
+ --primary-foreground: oklch(1 0 0);
170
+
171
+ --secondary: oklch(0.227 0 0); /* #1C1C1C */
172
+ --secondary-foreground: oklch(0.97 0 0);
173
+
174
+ --accent: oklch(0.621 0.132 39);
175
+ --accent-deep: oklch(from var(--accent) max(0.05, calc(l - 0.13)) c h);
176
+ --accent-foreground: oklch(1 0 0);
177
+
178
+ --muted: oklch(0.227 0 0);
179
+ --muted-foreground: oklch(0.683 0 0); /* #999 — Vercel gray-500 */
180
+
181
+ --border: oklch(0.28 0 0); /* #292929 */
182
+ --input: oklch(0.227 0 0);
183
+ --ring: oklch(0.628 0.225 296);
184
+
185
+ --success: oklch(0.814 0.192 155.7); /* #22E58C */
186
+ --success-foreground: oklch(0.146 0 0);
187
+ --warning: oklch(0.77 0.165 70.6); /* #F59E0B */
188
+ --warning-foreground: oklch(0.146 0 0);
189
+ --destructive: oklch(0.677 0.213 15.6); /* #FF4F6D */
190
+ --destructive-foreground: oklch(0.146 0 0);
191
+ --info: oklch(0.732 0.142 254.4); /* #5FB3FF */
192
+ --info-foreground: oklch(0.146 0 0);
193
+
194
+ /* Status (D4 — dark mode mirror of light defaults) ------------------ */
195
+ --status-online: oklch(0.814 0.192 155.7);
196
+ --status-online-foreground: oklch(0.146 0 0);
197
+ --status-offline: oklch(0.677 0.213 15.6);
198
+ --status-offline-foreground: oklch(0.146 0 0);
199
+ --status-degraded: oklch(0.77 0.165 70.6);
200
+ --status-degraded-foreground: oklch(0.146 0 0);
201
+ --status-info: oklch(0.732 0.142 254.4);
202
+ --status-info-foreground: oklch(0.146 0 0);
203
+
204
+ /* In dark mode, shadows are heavier ink (against the dark surface) and
205
+ * the glow brightens. Both still derive from theme tokens.
206
+ * Post-T2.5: OKLCH-aware composition via color-mix() — black ink via
207
+ * the literal oklch(0 0 0) (no theme indirection needed).
208
+ */
209
+ --shadow-sm: 0 1px 2px 0 oklch(0 0 0 / 0.4);
210
+ --shadow-md: 0 2px 8px -2px oklch(0 0 0 / 0.5), 0 1px 3px oklch(0 0 0 / 0.4);
211
+ --shadow-lg: 0 12px 32px -8px oklch(0 0 0 / 0.6), 0 4px 12px oklch(0 0 0 / 0.4);
212
+ --shadow-glow: 0 0 24px color-mix(in oklch, var(--primary-glow) 40%, transparent);
213
+ --shadow-glow-strong: 0 0 36px color-mix(in oklch, var(--primary-glow) 60%, transparent);
214
+ }
215
+
216
+ /* Forced colors (Windows High Contrast Mode) — D7 / ADR-0008 ----------- *
217
+ * Maps Theo's semantic tokens to system colors so the UI remains usable
218
+ * (and required by WCAG 1.4.1) when the OS forces a high-contrast palette.
219
+ * Decorative textures opt out via `forced-color-adjust: none` (the dotted
220
+ * patterns and hero glow would invert into solid blocks otherwise).
221
+ *
222
+ * Reference: MDN forced-colors media query, WCAG 2.2 SC 1.4.1.
223
+ */
224
+ @media (forced-colors: active) {
225
+ :root,
226
+ .dark {
227
+ --background: Canvas;
228
+ --foreground: CanvasText;
229
+ --card: Canvas;
230
+ --card-foreground: CanvasText;
231
+ --popover: Canvas;
232
+ --popover-foreground: CanvasText;
233
+ --primary: Highlight;
234
+ --primary-foreground: HighlightText;
235
+ --secondary: ButtonFace;
236
+ --secondary-foreground: ButtonText;
237
+ --accent: Highlight;
238
+ --accent-foreground: HighlightText;
239
+ --muted: ButtonFace;
240
+ --muted-foreground: GrayText;
241
+ --border: ButtonBorder;
242
+ --input: ButtonBorder;
243
+ --ring: Highlight;
244
+ }
245
+
246
+ /* Texture utilities are decorative — keep them out of the system-color map. */
247
+ .bg-dotted-violet,
248
+ .bg-dotted-violet-strong,
249
+ .bg-hero-glow,
250
+ .bg-paper-grain {
251
+ forced-color-adjust: none;
252
+ }
253
+ }
254
+
255
+ /* Reduced motion — neutralizes durations and transitions for users who
256
+ * request prefers-reduced-motion: reduce. Components that use animation as
257
+ * semantic state (e.g. a spinner on a running step) can opt back in with
258
+ * Tailwind's `motion-safe:` prefix.
259
+ *
260
+ * Reference: WCAG 2.3.3 Animation from Interactions (Level AAA).
261
+ */
262
+ @media (prefers-reduced-motion: reduce) {
263
+ :root {
264
+ --duration-fast: 0ms;
265
+ --duration-base: 0ms;
266
+ --duration-slow: 0ms;
267
+ --stagger: 0ms;
268
+ }
269
+ *,
270
+ *::before,
271
+ *::after {
272
+ animation-duration: 0.001ms !important;
273
+ animation-iteration-count: 1 !important;
274
+ transition-duration: 0.001ms !important;
275
+ scroll-behavior: auto !important;
276
+ }
277
+ }
278
+
279
+ /* Texture utilities (signature) ---------------------------------------- *
280
+ * Post-T2.5: tokens are OKLCH; we compose alpha via color-mix(in oklch, …),
281
+ * which is perceptually correct and works with any color-space variable.
282
+ */
283
+ @layer utilities {
284
+ .bg-dotted-violet {
285
+ background-image: radial-gradient(
286
+ color-mix(in oklch, var(--primary) 8%, transparent) 1px,
287
+ transparent 1px
288
+ );
289
+ background-size: 20px 20px;
290
+ }
291
+
292
+ .bg-dotted-violet-strong {
293
+ background-image: radial-gradient(
294
+ color-mix(in oklch, var(--primary) 16%, transparent) 1px,
295
+ transparent 1px
296
+ );
297
+ background-size: 20px 20px;
298
+ }
299
+
300
+ .bg-hero-glow {
301
+ background-image: radial-gradient(
302
+ ellipse 60% 50% at 70% 0%,
303
+ color-mix(in oklch, var(--primary) 18%, transparent) 0%,
304
+ transparent 60%
305
+ );
306
+ }
307
+
308
+ .bg-paper-grain {
309
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0.06 0 0 0 0 0.04 0 0 0 0 0.08 0 0 0 0.18 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
310
+ }
311
+
312
+ .text-balance {
313
+ text-wrap: balance;
314
+ }
315
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usetheo/ui",
3
- "version": "0.35.3",
3
+ "version": "0.36.0",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "description": "Violet Forge design system — generic React components + primitives (the non-AI foundation of @theokit/ui).",
@@ -40,7 +40,16 @@
40
40
  "./preset": {
41
41
  "types": "./dist/styles/tailwind-preset.d.ts",
42
42
  "import": "./dist/tailwind-preset.js"
43
- }
43
+ },
44
+ "./styles.css": "./dist/styles.css",
45
+ "./styles-v3-legacy.css": "./dist/styles-v3-legacy.css",
46
+ "./components.css": "./dist/components.css",
47
+ "./tokens.css": "./dist/tokens.css",
48
+ "./tokens-v4.css": "./dist/tokens-v4.css",
49
+ "./preset.css": "./dist/preset.css",
50
+ "./fonts.css": "./dist/fonts.css",
51
+ "./fonts-cdn.css": "./dist/fonts-cdn.css",
52
+ "./dist/fonts/*": "./dist/fonts/*"
44
53
  },
45
54
  "engines": {
46
55
  "node": ">=20"
@@ -76,6 +85,7 @@
76
85
  "@biomejs/biome": "^1.9.4",
77
86
  "@changesets/cli": "^2.31.1",
78
87
  "@ladle/react": "^4.1.2",
88
+ "@tailwindcss/cli": "^4.3.3",
79
89
  "@tailwindcss/vite": "^4.3.2",
80
90
  "@testing-library/jest-dom": "^6.6.3",
81
91
  "@testing-library/react": "^16.1.0",
@@ -104,12 +114,13 @@
104
114
  "format:check": "biome format src",
105
115
  "test": "vitest run",
106
116
  "test:run": "vitest run",
107
- "build": "tsup && tsc -p tsconfig.dts.json",
117
+ "build": "tsup && tsc -p tsconfig.dts.json && pnpm run build:css",
108
118
  "registry:build": "tsx scripts/build-registry.ts",
109
119
  "registry:validate": "tsx scripts/validate-registry.ts",
110
120
  "changeset": "changeset",
111
121
  "version-packages": "changeset version && pnpm run sync:readme",
112
122
  "release": "pnpm run build && changeset publish",
113
- "sync:readme": "tsx scripts/sync-readme.ts"
123
+ "sync:readme": "tsx scripts/sync-readme.ts",
124
+ "build:css": "tsx scripts/build-css.ts"
114
125
  }
115
126
  }