@nebutra/tokens 0.1.1 → 0.1.2
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/.turbo/turbo-build.log +5 -2
- package/.turbo/turbo-typecheck.log +1 -1
- package/AGENTS.md +5 -2
- package/CHANGELOG.md +23 -0
- package/DESIGN.md +30 -8
- package/LICENSE +21 -676
- package/README.md +41 -8
- package/brands/gsap/brand.json +180 -0
- package/brands/linear/brand.json +202 -0
- package/brands/notion/brand.json +189 -0
- package/brands/raycast/brand.json +167 -0
- package/brands/stripe/brand.json +183 -0
- package/brands/vanta/brand.json +198 -0
- package/brands/vercel/brand.json +207 -0
- package/package.json +17 -8
- package/recipe.css +114 -0
- package/scripts/compile-brand-run.ts +79 -0
- package/scripts/compile-brand.mjs +25 -0
- package/scripts/emit-skins-run.ts +62 -0
- package/scripts/emit-skins.mjs +31 -0
- package/scripts/sync-styles.mjs +29 -0
- package/skins/README.md +151 -0
- package/skins/gsap.css +247 -0
- package/skins/linear.css +282 -0
- package/skins/notion.css +248 -0
- package/skins/raycast.css +272 -0
- package/skins/stripe.css +248 -0
- package/skins/vanta.css +255 -0
- package/skins/vercel.css +283 -0
- package/src/brand-package/__tests__/compile-refero.test.ts +427 -0
- package/src/brand-package/__tests__/emit-css.test.ts +130 -0
- package/src/brand-package/apply-brand.ts +92 -0
- package/src/brand-package/compile-helpers.ts +170 -0
- package/src/brand-package/compile-refero.ts +69 -0
- package/src/brand-package/emit-css.ts +468 -0
- package/src/brand-package/hex-to-hsl.ts +100 -0
- package/src/brand-package/index.ts +71 -0
- package/src/brand-package/infer-recipe.ts +198 -0
- package/src/brand-package/normalize.ts +295 -0
- package/src/brand-package/presets/context.ts +17 -0
- package/src/brand-package/presets/generic.ts +214 -0
- package/src/brand-package/presets/gsap.ts +146 -0
- package/src/brand-package/presets/index.ts +31 -0
- package/src/brand-package/presets/linear.ts +183 -0
- package/src/brand-package/presets/notion.ts +208 -0
- package/src/brand-package/presets/raycast.ts +138 -0
- package/src/brand-package/presets/recipe.ts +61 -0
- package/src/brand-package/presets/stripe.ts +207 -0
- package/src/brand-package/presets/vanta.ts +220 -0
- package/src/brand-package/presets/vercel.ts +187 -0
- package/src/brand-package/types.ts +285 -0
- package/src/brand-package/use-brand.ts +207 -0
- package/src/brand-package/validate.ts +108 -0
- package/src/index.ts +31 -1
- package/src/theme-provider.tsx +5 -3
- package/styles.css +153 -69
- package/turbo.json +15 -0
package/styles.css
CHANGED
|
@@ -69,6 +69,10 @@
|
|
|
69
69
|
--nebutra-gray-800: #262626;
|
|
70
70
|
--nebutra-gray-900: #171717;
|
|
71
71
|
--nebutra-gray-950: #0a0a0a;
|
|
72
|
+
--breakpoint-xs: 26.25rem; /** 420px — narrow-phone grid flip */
|
|
73
|
+
--breakpoint-tight: 67.5rem; /** 1080px — dense dashboard header horizontal */
|
|
74
|
+
--breakpoint-shell: 73.75rem; /** 1180px — three-pane shell threshold */
|
|
75
|
+
--breakpoint-3xl: 112.5rem; /** 1800px — 4K / Studio Display friendliness */
|
|
72
76
|
--radius-none: 0;
|
|
73
77
|
--radius-sm: 0.25rem;
|
|
74
78
|
--radius-md: 0.375rem;
|
|
@@ -95,22 +99,43 @@
|
|
|
95
99
|
--leading-heading: 1.15;
|
|
96
100
|
--ring-hairline: inset 0 0 0 1px rgb(255 255 255 / 0.04); /** Etched-glass hairline (light mode value, dark mode override in themes/dark.json) */
|
|
97
101
|
--overlay-faint: rgb(0 0 0 / 0.06); /** Light-mode faint overlay (6% black) */
|
|
98
|
-
--font-sans:
|
|
102
|
+
--font-sans:
|
|
103
|
+
var(--font-geist-sans), "Geist", "Noto Sans SC", "PingFang SC", "Microsoft YaHei",
|
|
104
|
+
-apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
|
99
105
|
--font-cn: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", "vivo Sans", sans-serif;
|
|
100
|
-
--font-display: "Geist", "Noto Sans SC", sans-serif;
|
|
101
|
-
--font-heading: "Geist", "Noto Sans SC", sans-serif;
|
|
102
|
-
--font-mono:
|
|
106
|
+
--font-display: var(--font-geist-sans), "Geist", "Noto Sans SC", sans-serif;
|
|
107
|
+
--font-heading: var(--font-geist-sans), "Geist", "Noto Sans SC", sans-serif;
|
|
108
|
+
--font-mono:
|
|
109
|
+
var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
103
110
|
--transition-duration: 200ms; /** Default transition duration — 200ms flow rail. */
|
|
104
111
|
--transition-easing: ease-out; /** ease-out keyword form (CSS-friendly). Equivalent to cubic-bezier(0,0,0.2,1). */
|
|
105
112
|
--brand-primary: #0033fe; /** Brand primary — 云毓蓝 */
|
|
106
113
|
--brand-accent: #0bf1c3; /** Brand accent — 云毓青 */
|
|
107
114
|
--brand-tertiary: #8b5cf6;
|
|
108
|
-
--brand-gradient:
|
|
109
|
-
|
|
110
|
-
--
|
|
111
|
-
--brand-gradient-
|
|
112
|
-
|
|
113
|
-
|
|
115
|
+
--brand-gradient-start: hsl(
|
|
116
|
+
var(--primary)
|
|
117
|
+
); /** Legacy alias of --primary (shadcn product blue). Prefer bg-primary / Button default. */
|
|
118
|
+
--brand-gradient-end: hsl(
|
|
119
|
+
var(--primary)
|
|
120
|
+
); /** Legacy alias of --primary. Prefer hover:bg-primary/90. */
|
|
121
|
+
--brand-gradient: hsl(
|
|
122
|
+
var(--primary)
|
|
123
|
+
); /** Legacy --brand-gradient. Same color as --primary — not a second palette. App CTAs should use Button / bg-primary. */
|
|
124
|
+
--brand-gradient-reverse: hsl(var(--primary)); /** Legacy alias of --primary. */
|
|
125
|
+
--brand-gradient-vertical: hsl(var(--primary)); /** Legacy alias of --primary. */
|
|
126
|
+
--brand-gradient-radial: hsl(var(--primary)); /** Legacy alias of --primary. */
|
|
127
|
+
--brand-gradient-logo: linear-gradient(
|
|
128
|
+
135deg,
|
|
129
|
+
#0033fe 0%,
|
|
130
|
+
#00a2e9 50%,
|
|
131
|
+
#0bf1c3 100%
|
|
132
|
+
); /** Logo/VI gradient (云毓蓝→云毓青). Mid stop #00a2e9 is the OKLab perceptual midpoint (avoids sRGB mid-path soft spots). Brand assets only — not product CTAs. */
|
|
133
|
+
--brand-gradient-logo-reverse: linear-gradient(
|
|
134
|
+
135deg,
|
|
135
|
+
#0bf1c3 0%,
|
|
136
|
+
#00a2e9 50%,
|
|
137
|
+
#0033fe 100%
|
|
138
|
+
); /** Logo/VI reverse gradient with same OKLab mid stop. */
|
|
114
139
|
--status-danger: #ef4444;
|
|
115
140
|
--status-warning: #f59e0b;
|
|
116
141
|
--status-success: #22c55e;
|
|
@@ -339,6 +364,10 @@
|
|
|
339
364
|
--nebutra-gray-800: #262626;
|
|
340
365
|
--nebutra-gray-900: #171717;
|
|
341
366
|
--nebutra-gray-950: #0a0a0a;
|
|
367
|
+
--breakpoint-xs: 26.25rem; /** 420px — narrow-phone grid flip */
|
|
368
|
+
--breakpoint-tight: 67.5rem; /** 1080px — dense dashboard header horizontal */
|
|
369
|
+
--breakpoint-shell: 73.75rem; /** 1180px — three-pane shell threshold */
|
|
370
|
+
--breakpoint-3xl: 112.5rem; /** 1800px — 4K / Studio Display friendliness */
|
|
342
371
|
--radius-none: 0;
|
|
343
372
|
--radius-sm: 0.25rem;
|
|
344
373
|
--radius-md: 0.375rem;
|
|
@@ -364,23 +393,46 @@
|
|
|
364
393
|
--leading-display: 1.05;
|
|
365
394
|
--leading-heading: 1.15;
|
|
366
395
|
--ring-hairline: inset 0 0 0 1px rgb(255 255 255 / 0.06); /** Hairline override — more visible on dark background */
|
|
367
|
-
--overlay-faint: rgb(
|
|
368
|
-
|
|
396
|
+
--overlay-faint: rgb(
|
|
397
|
+
255 255 255 / 0.06
|
|
398
|
+
); /** Dark-mode faint overlay (6% white) — inverted from light */
|
|
399
|
+
--font-sans:
|
|
400
|
+
var(--font-geist-sans), "Geist", "Noto Sans SC", "PingFang SC", "Microsoft YaHei",
|
|
401
|
+
-apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
|
369
402
|
--font-cn: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", "vivo Sans", sans-serif;
|
|
370
|
-
--font-display: "Geist", "Noto Sans SC", sans-serif;
|
|
371
|
-
--font-heading: "Geist", "Noto Sans SC", sans-serif;
|
|
372
|
-
--font-mono:
|
|
403
|
+
--font-display: var(--font-geist-sans), "Geist", "Noto Sans SC", sans-serif;
|
|
404
|
+
--font-heading: var(--font-geist-sans), "Geist", "Noto Sans SC", sans-serif;
|
|
405
|
+
--font-mono:
|
|
406
|
+
var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
373
407
|
--transition-duration: 200ms; /** Default transition duration — 200ms flow rail. */
|
|
374
408
|
--transition-easing: ease-out; /** ease-out keyword form (CSS-friendly). Equivalent to cubic-bezier(0,0,0.2,1). */
|
|
375
409
|
--brand-primary: #5c7cfa; /** Dark-mode brand primary — visible against dark surfaces (uses --blue-9 = nebutra-blue-400). */
|
|
376
410
|
--brand-accent: #1af7c8; /** Dark-mode brand accent — visible against dark surfaces (uses --cyan-9 = nebutra-cyan-400). */
|
|
377
411
|
--brand-tertiary: #8b5cf6;
|
|
378
|
-
--brand-gradient:
|
|
379
|
-
|
|
380
|
-
--
|
|
381
|
-
--brand-gradient-
|
|
382
|
-
|
|
383
|
-
|
|
412
|
+
--brand-gradient-start: hsl(
|
|
413
|
+
var(--primary)
|
|
414
|
+
); /** Legacy alias of --primary (shadcn product blue). Prefer bg-primary / Button default. */
|
|
415
|
+
--brand-gradient-end: hsl(
|
|
416
|
+
var(--primary)
|
|
417
|
+
); /** Legacy alias of --primary. Prefer hover:bg-primary/90. */
|
|
418
|
+
--brand-gradient: hsl(
|
|
419
|
+
var(--primary)
|
|
420
|
+
); /** Legacy --brand-gradient. Same color as --primary — not a second palette. App CTAs should use Button / bg-primary. */
|
|
421
|
+
--brand-gradient-reverse: hsl(var(--primary)); /** Legacy alias of --primary. */
|
|
422
|
+
--brand-gradient-vertical: hsl(var(--primary)); /** Legacy alias of --primary. */
|
|
423
|
+
--brand-gradient-radial: hsl(var(--primary)); /** Legacy alias of --primary. */
|
|
424
|
+
--brand-gradient-logo: linear-gradient(
|
|
425
|
+
135deg,
|
|
426
|
+
#0033fe 0%,
|
|
427
|
+
#00a2e9 50%,
|
|
428
|
+
#0bf1c3 100%
|
|
429
|
+
); /** Logo/VI gradient (云毓蓝→云毓青). Mid stop #00a2e9 is the OKLab perceptual midpoint (avoids sRGB mid-path soft spots). Brand assets only — not product CTAs. */
|
|
430
|
+
--brand-gradient-logo-reverse: linear-gradient(
|
|
431
|
+
135deg,
|
|
432
|
+
#0bf1c3 0%,
|
|
433
|
+
#00a2e9 50%,
|
|
434
|
+
#0033fe 100%
|
|
435
|
+
); /** Logo/VI reverse gradient with same OKLab mid stop. */
|
|
384
436
|
--status-danger: #ef4444;
|
|
385
437
|
--status-warning: #f59e0b;
|
|
386
438
|
--status-success: #22c55e;
|
|
@@ -430,39 +482,39 @@
|
|
|
430
482
|
--cyan-10: #4dfcd4;
|
|
431
483
|
--cyan-11: #80ffe0;
|
|
432
484
|
--cyan-12: #b3ffec;
|
|
433
|
-
--background: 222
|
|
434
|
-
--foreground: 210
|
|
435
|
-
--card: 222
|
|
436
|
-
--card-foreground: 210
|
|
437
|
-
--popover: 222
|
|
438
|
-
--popover-foreground: 210
|
|
485
|
+
--background: 222 14% 9%;
|
|
486
|
+
--foreground: 210 18% 96%;
|
|
487
|
+
--card: 222 12% 13%;
|
|
488
|
+
--card-foreground: 210 18% 96%;
|
|
489
|
+
--popover: 222 12% 13%;
|
|
490
|
+
--popover-foreground: 210 18% 96%;
|
|
439
491
|
--primary: 228 90% 72%;
|
|
440
|
-
--primary-foreground: 222
|
|
441
|
-
--secondary:
|
|
442
|
-
--secondary-foreground: 210
|
|
443
|
-
--muted:
|
|
444
|
-
--muted-foreground:
|
|
445
|
-
--accent: 228
|
|
446
|
-
--accent-foreground: 228 95%
|
|
447
|
-
--destructive: 0 63%
|
|
448
|
-
--destructive-foreground: 210
|
|
449
|
-
--success: 142
|
|
450
|
-
--success-foreground: 222
|
|
451
|
-
--warning: 38 80%
|
|
452
|
-
--warning-foreground: 222
|
|
453
|
-
--info: 228 95%
|
|
454
|
-
--info-foreground: 222
|
|
455
|
-
--border:
|
|
456
|
-
--input:
|
|
492
|
+
--primary-foreground: 222 14% 9%;
|
|
493
|
+
--secondary: 222 10% 18%;
|
|
494
|
+
--secondary-foreground: 210 18% 96%;
|
|
495
|
+
--muted: 222 10% 17%;
|
|
496
|
+
--muted-foreground: 220 8% 65%;
|
|
497
|
+
--accent: 228 38% 22%;
|
|
498
|
+
--accent-foreground: 228 95% 80%;
|
|
499
|
+
--destructive: 0 63% 38%;
|
|
500
|
+
--destructive-foreground: 210 18% 96%;
|
|
501
|
+
--success: 142 60% 42%;
|
|
502
|
+
--success-foreground: 222 14% 9%;
|
|
503
|
+
--warning: 38 80% 52%;
|
|
504
|
+
--warning-foreground: 222 14% 9%;
|
|
505
|
+
--info: 228 95% 72%;
|
|
506
|
+
--info-foreground: 222 14% 9%;
|
|
507
|
+
--border: 220 8% 22%;
|
|
508
|
+
--input: 220 8% 22%;
|
|
457
509
|
--ring: 0 0% 88%; /** Focus ring (dark mode) — neutral light gray. Mirrors light-mode neutral foreground choice. */
|
|
458
|
-
--sidebar: 222
|
|
459
|
-
--sidebar-foreground: 210
|
|
460
|
-
--sidebar-primary: 228 95%
|
|
461
|
-
--sidebar-primary-foreground: 222
|
|
462
|
-
--sidebar-accent: 228
|
|
463
|
-
--sidebar-accent-foreground: 228 95%
|
|
464
|
-
--sidebar-border:
|
|
465
|
-
--sidebar-ring: 228 95%
|
|
510
|
+
--sidebar: 222 16% 8%;
|
|
511
|
+
--sidebar-foreground: 210 18% 94%;
|
|
512
|
+
--sidebar-primary: 228 95% 72%;
|
|
513
|
+
--sidebar-primary-foreground: 222 14% 9%;
|
|
514
|
+
--sidebar-accent: 228 38% 22%;
|
|
515
|
+
--sidebar-accent-foreground: 228 95% 80%;
|
|
516
|
+
--sidebar-border: 220 8% 18%;
|
|
517
|
+
--sidebar-ring: 228 95% 72%;
|
|
466
518
|
--chart-1: 228 95% 67%;
|
|
467
519
|
--chart-2: 168 96% 54%;
|
|
468
520
|
--chart-3: 228 100% 82%;
|
|
@@ -737,11 +789,14 @@
|
|
|
737
789
|
--duration-cinematic: 500ms;
|
|
738
790
|
|
|
739
791
|
/* Font family — Geist primary stack with CJK fallbacks */
|
|
740
|
-
--font-sans:
|
|
792
|
+
--font-sans:
|
|
793
|
+
var(--font-geist-sans), "Geist", "Noto Sans SC", "PingFang SC", "Microsoft YaHei",
|
|
794
|
+
-apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
|
741
795
|
--font-cn: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", "vivo Sans", sans-serif;
|
|
742
|
-
--font-display: "Geist", "Noto Sans SC", sans-serif;
|
|
743
|
-
--font-heading: "Geist", "Noto Sans SC", sans-serif;
|
|
744
|
-
--font-mono:
|
|
796
|
+
--font-display: var(--font-geist-sans), "Geist", "Noto Sans SC", sans-serif;
|
|
797
|
+
--font-heading: var(--font-geist-sans), "Geist", "Noto Sans SC", sans-serif;
|
|
798
|
+
--font-mono:
|
|
799
|
+
var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
745
800
|
}
|
|
746
801
|
|
|
747
802
|
/* ============================================
|
|
@@ -749,15 +804,39 @@
|
|
|
749
804
|
This file is concatenated into styles.generated.css after the @theme block.
|
|
750
805
|
============================================ */
|
|
751
806
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
807
|
+
/* ─── Edge tokens (2026-05 perf governance) ─────────────────
|
|
808
|
+
Pre-computed alpha values for borders / hairlines / outer glows.
|
|
809
|
+
Replaces ~70 runtime `color-mix(foreground, transparent N%)` calls per
|
|
810
|
+
page that re-evaluated on every paint. Mode-aware via CSS cascade.
|
|
811
|
+
Lives in static/ so it survives Style Dictionary rebuilds.
|
|
812
|
+
─────────────────────────────────────────────────────────── */
|
|
813
|
+
:root {
|
|
814
|
+
--edge-faint: rgb(0 0 0 / 0.04);
|
|
815
|
+
--edge-soft: rgb(0 0 0 / 0.07);
|
|
816
|
+
--edge-medium: rgb(0 0 0 / 0.12);
|
|
817
|
+
--halo-faint: rgb(0 0 0 / 0.03);
|
|
818
|
+
}
|
|
819
|
+
.dark {
|
|
820
|
+
--edge-faint: rgb(255 255 255 / 0.04);
|
|
821
|
+
--edge-soft: rgb(255 255 255 / 0.06);
|
|
822
|
+
--edge-medium: rgb(255 255 255 / 0.1);
|
|
823
|
+
--halo-faint: rgb(255 255 255 / 0.03);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
@layer base {
|
|
827
|
+
*,
|
|
828
|
+
*::before,
|
|
829
|
+
*::after {
|
|
830
|
+
/* Token-aware default border — resolves via cascade:
|
|
831
|
+
:root → light (hsl 240 5.9% 90% ≈ #e4e4e7)
|
|
832
|
+
.dark → dark (hsl 0 0% 14.9% ≈ #262626)
|
|
833
|
+
Previously hardcoded to the light value, which leaked a near-white border
|
|
834
|
+
into every element in dark mode regardless of component. See ADR 2026-05-11.
|
|
835
|
+
|
|
836
|
+
Keep this in Tailwind's base layer so component utilities such as
|
|
837
|
+
border-r-transparent can override it. */
|
|
838
|
+
border-color: hsl(var(--border));
|
|
839
|
+
}
|
|
761
840
|
}
|
|
762
841
|
|
|
763
842
|
body {
|
|
@@ -773,7 +852,9 @@ html {
|
|
|
773
852
|
scroll-behavior: smooth;
|
|
774
853
|
}
|
|
775
854
|
|
|
776
|
-
:focus-visible
|
|
855
|
+
:focus-visible:not(
|
|
856
|
+
:where(input, textarea, select, [cmdk-input], [role="textbox"], [contenteditable="true"])
|
|
857
|
+
) {
|
|
777
858
|
outline: 2px solid hsl(var(--ring) / 0.5);
|
|
778
859
|
outline-offset: 2px;
|
|
779
860
|
border-radius: inherit;
|
|
@@ -1373,10 +1454,13 @@ html {
|
|
|
1373
1454
|
}
|
|
1374
1455
|
|
|
1375
1456
|
/* ─── Reduced Motion ─────────────────────────────────────── */
|
|
1457
|
+
/* Honors OS preference EXCEPT for functional progress indicators
|
|
1458
|
+
* (spinners / pulses / pings). Per WCAG 2.3.3, those are excluded
|
|
1459
|
+
* from the "animation from interactions" reduction requirement. */
|
|
1376
1460
|
@media (prefers-reduced-motion: reduce) {
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1461
|
+
*:not(.animate-spin):not(.animate-pulse):not(.animate-ping),
|
|
1462
|
+
*:not(.animate-spin):not(.animate-pulse):not(.animate-ping)::before,
|
|
1463
|
+
*:not(.animate-spin):not(.animate-pulse):not(.animate-ping)::after {
|
|
1380
1464
|
animation-duration: 0.01ms;
|
|
1381
1465
|
animation-iteration-count: 1;
|
|
1382
1466
|
transition-duration: 0.01ms;
|
package/turbo.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": ["//"],
|
|
3
|
+
"tasks": {
|
|
4
|
+
"build": {
|
|
5
|
+
"dependsOn": ["@nebutra/design-tokens#build"],
|
|
6
|
+
"inputs": [
|
|
7
|
+
"$TURBO_EXTENDS$",
|
|
8
|
+
"../design-tokens/build/css/styles.generated.css",
|
|
9
|
+
"brands/**",
|
|
10
|
+
"scripts/**"
|
|
11
|
+
],
|
|
12
|
+
"outputs": ["styles.css", "skins/**"]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|