@vegastack/design-tokens 0.1.0 → 0.4.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/dist/base.css +62 -10
- package/dist/theme.css +288 -47
- package/dist/tokens.cjs +663 -0
- package/dist/tokens.d.cts +638 -0
- package/dist/tokens.d.ts +156 -46
- package/dist/tokens.js +158 -48
- package/dist/tokens.json +158 -48
- package/dist/utilities.css +152 -68
- package/package.json +19 -14
package/dist/utilities.css
CHANGED
|
@@ -51,12 +51,18 @@
|
|
|
51
51
|
--scroll-fade-t: 0px;
|
|
52
52
|
}
|
|
53
53
|
to {
|
|
54
|
-
--scroll-fade-t: var(
|
|
54
|
+
--scroll-fade-t: var(
|
|
55
|
+
--_scroll-fade-size-t,
|
|
56
|
+
var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
|
|
57
|
+
);
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
@keyframes scroll-fade-reveal-b {
|
|
58
61
|
from {
|
|
59
|
-
--scroll-fade-b: var(
|
|
62
|
+
--scroll-fade-b: var(
|
|
63
|
+
--_scroll-fade-size-b,
|
|
64
|
+
var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
|
|
65
|
+
);
|
|
60
66
|
}
|
|
61
67
|
to {
|
|
62
68
|
--scroll-fade-b: 0px;
|
|
@@ -67,12 +73,18 @@
|
|
|
67
73
|
--scroll-fade-s: 0px;
|
|
68
74
|
}
|
|
69
75
|
to {
|
|
70
|
-
--scroll-fade-s: var(
|
|
76
|
+
--scroll-fade-s: var(
|
|
77
|
+
--_scroll-fade-size-s,
|
|
78
|
+
var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
|
|
79
|
+
);
|
|
71
80
|
}
|
|
72
81
|
}
|
|
73
82
|
@keyframes scroll-fade-reveal-e {
|
|
74
83
|
from {
|
|
75
|
-
--scroll-fade-e: var(
|
|
84
|
+
--scroll-fade-e: var(
|
|
85
|
+
--_scroll-fade-size-e,
|
|
86
|
+
var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
|
|
87
|
+
);
|
|
76
88
|
}
|
|
77
89
|
to {
|
|
78
90
|
--scroll-fade-e: 0px;
|
|
@@ -553,7 +565,6 @@
|
|
|
553
565
|
}
|
|
554
566
|
}
|
|
555
567
|
|
|
556
|
-
|
|
557
568
|
/* ---------------------------------------------------------------------------
|
|
558
569
|
* scrollbar-* — minimal native scrollbar helpers (VegaStack addition; not in
|
|
559
570
|
* upstream shadcn tailwind.css). Used by message-scroller's viewport.
|
|
@@ -573,7 +584,6 @@
|
|
|
573
584
|
scrollbar-gutter: stable;
|
|
574
585
|
}
|
|
575
586
|
|
|
576
|
-
|
|
577
587
|
/* ---------------------------------------------------------------------------
|
|
578
588
|
* motion-* — the state-feedback animation vocabulary (VegaStack addition,
|
|
579
589
|
* Phase M). Mount-triggered CSS animations for the "keyed presence" mechanism:
|
|
@@ -586,9 +596,18 @@
|
|
|
586
596
|
* (the "success bounce" — spring ease, tiny overshoot).
|
|
587
597
|
* - motion-enter-up : fade+rise arrival for content (chat messages,
|
|
588
598
|
* skeleton→content reveal).
|
|
599
|
+
* - motion-flash : highlight-on-change ring pulse (live updates); color
|
|
600
|
+
* via --vs-flash-color, defaults to `ring`.
|
|
589
601
|
* - motion-shake : horizontal error jiggle. Replayable: re-trigger by
|
|
590
602
|
* remounting (key bump) or toggling the class after
|
|
591
603
|
* `animationend`.
|
|
604
|
+
* - motion-indeterminate : the ONE sanctioned looping utility — the sweeping
|
|
605
|
+
* segment of an indeterminate Progress. Looping motion is
|
|
606
|
+
* otherwise banned; an indeterminate bar has no other way
|
|
607
|
+
* to say "still working" (audit M-06).
|
|
608
|
+
*
|
|
609
|
+
* `motion-dock-in` / `motion-dock-out` below are the one PAIR in this family and
|
|
610
|
+
* the one that is not keyed presence — see their own header.
|
|
592
611
|
* ------------------------------------------------------------------------- */
|
|
593
612
|
@keyframes vs-pop-in {
|
|
594
613
|
from {
|
|
@@ -643,70 +662,135 @@
|
|
|
643
662
|
animation: vs-shake var(--duration-slow) var(--motion-ease-standard);
|
|
644
663
|
}
|
|
645
664
|
|
|
665
|
+
@keyframes vs-flash {
|
|
666
|
+
/* Highlight-on-change ring pulse (Wave 1, Attio record-flash adaptation):
|
|
667
|
+
* a 2px ring in the component's own accent (defaults to `ring`) swells and
|
|
668
|
+
* settles. End state = rest, so the base.css reduced-motion collapse renders
|
|
669
|
+
* it invisible. Override the color per call-site via `--vs-flash-color`
|
|
670
|
+
* (e.g. `[--vs-flash-color:var(--info)]` on a live-updating row). */
|
|
671
|
+
0% {
|
|
672
|
+
box-shadow: 0 0 0 0 transparent;
|
|
673
|
+
}
|
|
674
|
+
50% {
|
|
675
|
+
box-shadow: 0 0 0 2px var(--vs-flash-color, var(--ring));
|
|
676
|
+
}
|
|
677
|
+
to {
|
|
678
|
+
box-shadow: 0 0 0 0 transparent;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
@utility motion-flash {
|
|
683
|
+
animation: vs-flash var(--duration-slow) var(--motion-ease-standard);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
@keyframes vs-indeterminate {
|
|
687
|
+
/* Indeterminate progress (audit M-06, 2026-09-07): a 35%-wide segment sweeps the
|
|
688
|
+
* track and returns. The 0% and 100% stops are IDENTICAL on purpose — the global
|
|
689
|
+
* prefers-reduced-motion reset in base.css collapses every animation to its `to`
|
|
690
|
+
* state, so a reduced-motion user sees a static 35% segment resting at the start
|
|
691
|
+
* of the track instead of a bar that reads as 100% complete. */
|
|
692
|
+
0% {
|
|
693
|
+
inset-inline-start: 0%;
|
|
694
|
+
}
|
|
695
|
+
50% {
|
|
696
|
+
inset-inline-start: 65%;
|
|
697
|
+
}
|
|
698
|
+
100% {
|
|
699
|
+
inset-inline-start: 0%;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
@utility motion-indeterminate {
|
|
704
|
+
animation: vs-indeterminate var(--duration-indeterminate)
|
|
705
|
+
var(--motion-ease-standard) infinite;
|
|
706
|
+
}
|
|
707
|
+
|
|
646
708
|
/* ---------------------------------------------------------------------------
|
|
647
|
-
*
|
|
648
|
-
*
|
|
649
|
-
* section bands, the Terminal primitive) render the warm ramp's DARK end
|
|
650
|
-
* regardless of the page/product theme — `.dark` alone can't express "product
|
|
651
|
-
* light + marketing dark on the SAME page," which is exactly the co-existing
|
|
652
|
-
* case this class exists for (docs-home is light by default but its hero is
|
|
653
|
-
* dark-first). Any subtree wrapped in `.vs-marketing` (see the
|
|
654
|
-
* `MarketingSurface` primitive, and `Terminal`, which self-scopes) gets the
|
|
655
|
-
* same semantic custom properties `.dark` sets, scoped LOCALLY instead of
|
|
656
|
-
* gated on the page-root class — every `bg-background` / `text-foreground` /
|
|
657
|
-
* `border-border` / `bg-brand` utility inside it resolves through these, with
|
|
658
|
-
* NO component code changes (any existing token-built component composes
|
|
659
|
-
* correctly, since only the custom-property VALUES change, never the
|
|
660
|
-
* utility-to-var wiring).
|
|
709
|
+
* motion-dock-in / motion-dock-out — the docked-control enter/exit pair
|
|
710
|
+
* (audit D11 amendment #7, 2026-09-07).
|
|
661
711
|
*
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
* a THIRD generated Style Dictionary platform run in `build-tokens.mjs`
|
|
667
|
-
* (source `semantic.dark.tokens.json`, selector `.vs-marketing` instead of
|
|
668
|
-
* `.dark`) so this can never drift silently — that's a tokens-BUILD-PIPELINE
|
|
669
|
-
* change outside this component-level addition; flagged for whoever owns
|
|
670
|
-
* `packages/design-tokens/build-tokens.mjs` next. If `semantic.dark.tokens.json`
|
|
671
|
-
* changes, update this block to match (or land the generated version).
|
|
712
|
+
* A docked control — a bottom action bar, a floating scroll-to-end button —
|
|
713
|
+
* stays MOUNTED and flips a `data-active` attribute, so its motion is a
|
|
714
|
+
* transition, not a keyed animation. That is why this is a pair rather than one
|
|
715
|
+
* `@utility`: the two states carry different timing, which is the whole point.
|
|
672
716
|
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
*
|
|
677
|
-
*
|
|
717
|
+
* The doctrine these encode: **an exit is never slower than its enter.** Both
|
|
718
|
+
* bars previously entered at `duration-base` and left at `duration-slow` with a
|
|
719
|
+
* `scale-95`, so dismissing one took half again as long as summoning it and the
|
|
720
|
+
* bar shrank as it went. Vercel, Linear and Base UI's own defaults all leave at
|
|
721
|
+
* or faster than they arrive. Enter is 150ms `emphasized`; exit is 100ms `exit`;
|
|
722
|
+
* a docked bar translates and fades and does not scale — scale reads as a popup,
|
|
723
|
+
* and a bar sliding off its own edge does not need it.
|
|
724
|
+
*
|
|
725
|
+
* 100ms has exactly one role in the system — this exit — so it lives here, in
|
|
726
|
+
* the utility that names it, rather than becoming a fifth global duration token
|
|
727
|
+
* that would invite reuse D11 did not sanction.
|
|
728
|
+
*
|
|
729
|
+
* These own the timing, the fade and the inert-while-hidden guard. The DISTANCE
|
|
730
|
+
* stays at the call site as ordinary `translate-*` utilities, because it is
|
|
731
|
+
* per-dock geometry (a bottom bar clears its own height plus the safe-area
|
|
732
|
+
* inset; an edge button clears 100%) and because Tailwind composes `translate-x`
|
|
733
|
+
* and `translate-y` through custom properties that a `translate:` declaration
|
|
734
|
+
* here would clobber — a horizontally-centred bar would lose its centring.
|
|
735
|
+
*
|
|
736
|
+
* The global prefers-reduced-motion reset in base.css collapses both to 0.01ms.
|
|
737
|
+
*
|
|
738
|
+
* <div data-active={open}
|
|
739
|
+
* className="data-[active=true]:motion-dock-in data-[active=true]:translate-y-0
|
|
740
|
+
* data-[active=false]:motion-dock-out data-[active=false]:translate-y-full" />
|
|
678
741
|
* ------------------------------------------------------------------------- */
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
--card: oklch(0.205 0.003 75);
|
|
685
|
-
--card-foreground: oklch(0.922 0.003 75);
|
|
686
|
-
--popover: oklch(0.205 0.003 75);
|
|
687
|
-
--popover-foreground: oklch(0.922 0.003 75);
|
|
688
|
-
|
|
689
|
-
--primary: oklch(0.922 0.003 75);
|
|
690
|
-
--primary-foreground: oklch(0.145 0.003 75);
|
|
691
|
-
--primary-hover: oklch(0.97 0.003 75);
|
|
692
|
-
--primary-active: oklch(0.994 0.002 75);
|
|
693
|
-
|
|
694
|
-
--secondary: oklch(0.269 0.003 75);
|
|
695
|
-
--secondary-foreground: oklch(0.922 0.003 75);
|
|
696
|
-
--muted: oklch(0.269 0.003 75);
|
|
697
|
-
--muted-foreground: oklch(0.66 0.003 75);
|
|
698
|
-
--muted-foreground-faint: oklch(0.559 0.003 75);
|
|
699
|
-
--accent: oklch(0.269 0.003 75);
|
|
700
|
-
--accent-foreground: oklch(0.967 0.003 75);
|
|
701
|
-
|
|
702
|
-
--border: oklch(0.269 0.003 75);
|
|
703
|
-
--input: var(--border);
|
|
704
|
-
--ring: var(--primary);
|
|
705
|
-
--overlay: oklch(0 0 0 / 0.55);
|
|
706
|
-
|
|
707
|
-
/* Brand phosphor — DARK half (13.3:1 on this ground, MK's pick), independent
|
|
708
|
-
of whether `.dark` is present anywhere in the ancestor chain. Marker roles
|
|
709
|
-
only (live-state dot, sparkline endpoint, eyebrow highlight, terminal
|
|
710
|
-
prompt glyph) — see design.md §Brand & Marketing. */
|
|
711
|
-
--brand: oklch(0.86 0.21 148);
|
|
742
|
+
@utility motion-dock-in {
|
|
743
|
+
transition-property: translate, opacity;
|
|
744
|
+
transition-duration: var(--duration-fast);
|
|
745
|
+
transition-timing-function: var(--motion-ease-emphasized);
|
|
746
|
+
opacity: 1;
|
|
712
747
|
}
|
|
748
|
+
|
|
749
|
+
@utility motion-dock-out {
|
|
750
|
+
transition-property: translate, opacity;
|
|
751
|
+
transition-duration: 100ms;
|
|
752
|
+
transition-timing-function: var(--motion-ease-exit);
|
|
753
|
+
opacity: 0;
|
|
754
|
+
/* A docked-out control is off-screen: it must not swallow clicks on the way
|
|
755
|
+
out, and it must not be a hit target while parked. */
|
|
756
|
+
pointer-events: none;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/* ---------------------------------------------------------------------------
|
|
760
|
+
* BrandIcon theme-aware artwork swap (`<BrandIcon variant="auto">`).
|
|
761
|
+
*
|
|
762
|
+
* Single-colour brands ship artwork that only reads on ONE surface — GitHub's
|
|
763
|
+
* brand mark is #181717, invisible on a dark canvas. `thesvg` therefore ships
|
|
764
|
+
* `light` (dark ink, FOR light surfaces) and `dark` (white ink, FOR dark
|
|
765
|
+
* surfaces) variants; `auto` renders both and lets CSS reveal the right one.
|
|
766
|
+
*
|
|
767
|
+
* These are plain attribute selectors, NOT Tailwind utilities, on purpose:
|
|
768
|
+
* `@vegastack/design` is a published package, and a consumer's Tailwind build
|
|
769
|
+
* does not scan our `src`. A `dark:` utility authored inside the package would
|
|
770
|
+
* silently never be generated downstream (it wasn't generated in our own docs
|
|
771
|
+
* either — see the dead `packages/icons` @source). Shipping the rules in the
|
|
772
|
+
* stylesheet consumers already import makes the swap work everywhere.
|
|
773
|
+
*
|
|
774
|
+
* `.vs-marketing` is included so a brand mark inside the marketing dark ground
|
|
775
|
+
* picks the dark artwork even while the page theme is light.
|
|
776
|
+
* ------------------------------------------------------------------------- */
|
|
777
|
+
[data-brand-artwork="light"] {
|
|
778
|
+
display: contents;
|
|
779
|
+
}
|
|
780
|
+
[data-brand-artwork="dark"] {
|
|
781
|
+
display: none;
|
|
782
|
+
}
|
|
783
|
+
.dark [data-brand-artwork="light"],
|
|
784
|
+
.vs-marketing [data-brand-artwork="light"] {
|
|
785
|
+
display: none;
|
|
786
|
+
}
|
|
787
|
+
.dark [data-brand-artwork="dark"],
|
|
788
|
+
.vs-marketing [data-brand-artwork="dark"] {
|
|
789
|
+
display: contents;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/* `.vs-marketing`'s semantic variables and `color-scheme: dark` now live in
|
|
793
|
+
* generated theme.css. build-tokens.mjs emits the scope from the SAME resolved
|
|
794
|
+
* Style Dictionary dark run as `.dark`, and verify-theme-parity.mjs rejects any
|
|
795
|
+
* variable-set or value drift. The artwork selectors above remain here because
|
|
796
|
+
* they are presentation behavior, not token data. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vegastack/design-tokens",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "VegaStack design tokens (DTCG → Tailwind v4 theme + TS)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
"url": "git+https://github.com/VegaStack/vegastack-design.git",
|
|
9
9
|
"directory": "packages/design-tokens"
|
|
10
10
|
},
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=24.14.0"
|
|
13
|
+
},
|
|
11
14
|
"type": "module",
|
|
12
15
|
"sideEffects": [
|
|
13
16
|
"**/*.css"
|
|
@@ -18,25 +21,27 @@
|
|
|
18
21
|
"exports": {
|
|
19
22
|
".": {
|
|
20
23
|
"types": "./dist/tokens.d.ts",
|
|
21
|
-
"import": "./dist/tokens.js"
|
|
24
|
+
"import": "./dist/tokens.js",
|
|
25
|
+
"require": "./dist/tokens.cjs",
|
|
26
|
+
"default": "./dist/tokens.js"
|
|
22
27
|
},
|
|
23
28
|
"./theme.css": "./dist/theme.css",
|
|
24
29
|
"./base.css": "./dist/base.css",
|
|
25
30
|
"./utilities.css": "./dist/utilities.css",
|
|
26
|
-
"./tokens.json": "./dist/tokens.json"
|
|
31
|
+
"./tokens.json": "./dist/tokens.json",
|
|
32
|
+
"./package.json": "./package.json"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "node build-tokens.mjs && node ../../tooling/contrast-check.mjs dist/theme.css && tsup src/tokens.ts --format esm,cjs --dts --out-dir dist",
|
|
36
|
+
"lint": "node ../../tooling/verify-theme-parity.mjs dist/theme.css && node ../../tooling/contrast-check.mjs dist/theme.css && node ../../tooling/design-lint.mjs --token-css src",
|
|
37
|
+
"typecheck": "tsc --noEmit"
|
|
27
38
|
},
|
|
28
39
|
"devDependencies": {
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
40
|
+
"@vegastack/typescript-config": "workspace:*",
|
|
41
|
+
"style-dictionary": "5.5.2",
|
|
42
|
+
"typescript": "catalog:"
|
|
32
43
|
},
|
|
33
44
|
"publishConfig": {
|
|
34
|
-
"access": "public"
|
|
35
|
-
"provenance": true
|
|
36
|
-
},
|
|
37
|
-
"scripts": {
|
|
38
|
-
"build": "node build-tokens.mjs && node ../../tooling/contrast-check.mjs dist/theme.css && tsup src/tokens.ts --format esm --dts --out-dir dist",
|
|
39
|
-
"lint": "node ../../tooling/contrast-check.mjs dist/theme.css && node ../../tooling/design-lint.mjs --token-css src",
|
|
40
|
-
"typecheck": "tsc --noEmit"
|
|
45
|
+
"access": "public"
|
|
41
46
|
}
|
|
42
|
-
}
|
|
47
|
+
}
|