@vegastack/design-tokens 0.2.0 → 0.5.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.
@@ -19,6 +19,91 @@
19
19
  * priority-flag ban, which this file does not trip.
20
20
  */
21
21
 
22
+ /* ---------------------------------------------------------------------------------------------
23
+ * Upstream's CUSTOM VARIANTS, verbatim from `shadcn/tailwind.css` (4.21.0).
24
+ *
25
+ * Upstream's own app imports `shadcn/tailwind.css`, which redefines nine `data-*` variants so they
26
+ * match the attribute shape Base UI actually emits. Without them Tailwind falls back to its default
27
+ * `data-<name>:` rule — a bare `[data-<name>]` attribute — and the ones keyed on `data-orientation`
28
+ * or `data-state` silently stop matching. Measured 2026-09-18 in the Batch 2 review artifact:
29
+ * `<ToggleGroup orientation="vertical">` laid out HORIZONTALLY here and vertically upstream, from
30
+ * the same source file, because `data-vertical:flex-col` compiled to `[data-vertical]` instead of
31
+ * `[data-orientation="vertical"]`. `Separator`'s vertical rule failed the same way.
32
+ *
33
+ * Shipping them here rather than per app is what keeps a copied-in component behaving the same in
34
+ * a consumer's project as it does in ours.
35
+ * ------------------------------------------------------------------------------------------- */
36
+
37
+ @custom-variant data-open {
38
+ &:where([data-state="open"]),
39
+ &:where([data-open]:not([data-open="false"])) {
40
+ @slot;
41
+ }
42
+ }
43
+
44
+ @custom-variant data-closed {
45
+ &:where([data-state="closed"]),
46
+ &:where([data-closed]:not([data-closed="false"])) {
47
+ @slot;
48
+ }
49
+ }
50
+
51
+ @custom-variant data-checked {
52
+ &:where([data-state="checked"]),
53
+ &:where([data-checked]:not([data-checked="false"])) {
54
+ @slot;
55
+ }
56
+ }
57
+
58
+ @custom-variant data-unchecked {
59
+ &:where([data-state="unchecked"]),
60
+ &:where([data-unchecked]:not([data-unchecked="false"])) {
61
+ @slot;
62
+ }
63
+ }
64
+
65
+ @custom-variant data-selected {
66
+ &:where([data-selected="true"]) {
67
+ @slot;
68
+ }
69
+ }
70
+
71
+ @custom-variant data-disabled {
72
+ &:where([data-disabled="true"]),
73
+ &:where([data-disabled]:not([data-disabled="false"])) {
74
+ @slot;
75
+ }
76
+ }
77
+
78
+ @custom-variant data-active {
79
+ &:where([data-state="active"]),
80
+ &:where([data-active]:not([data-active="false"])) {
81
+ @slot;
82
+ }
83
+ }
84
+
85
+ @custom-variant data-horizontal {
86
+ &:where([data-orientation="horizontal"]) {
87
+ @slot;
88
+ }
89
+ }
90
+
91
+ @custom-variant data-vertical {
92
+ &:where([data-orientation="vertical"]) {
93
+ @slot;
94
+ }
95
+ }
96
+
97
+ /* Upstream's one scrollbar utility, which `sidebar` and `command` reach for. */
98
+ @utility no-scrollbar {
99
+ -ms-overflow-style: none;
100
+ scrollbar-width: none;
101
+
102
+ &::-webkit-scrollbar {
103
+ display: none;
104
+ }
105
+ }
106
+
22
107
  /* scroll-fade */
23
108
  @property --scroll-fade-t {
24
109
  syntax: "<length-percentage>";
@@ -601,6 +686,13 @@
601
686
  * - motion-shake : horizontal error jiggle. Replayable: re-trigger by
602
687
  * remounting (key bump) or toggling the class after
603
688
  * `animationend`.
689
+ * - motion-indeterminate : the ONE sanctioned looping utility — the sweeping
690
+ * segment of an indeterminate Progress. Looping motion is
691
+ * otherwise banned; an indeterminate bar has no other way
692
+ * to say "still working" (audit M-06).
693
+ *
694
+ * `motion-dock-in` / `motion-dock-out` below are the one PAIR in this family and
695
+ * the one that is not keyed presence — see their own header.
604
696
  * ------------------------------------------------------------------------- */
605
697
  @keyframes vs-pop-in {
606
698
  from {
@@ -676,6 +768,79 @@
676
768
  animation: vs-flash var(--duration-slow) var(--motion-ease-standard);
677
769
  }
678
770
 
771
+ @keyframes vs-indeterminate {
772
+ /* Indeterminate progress (audit M-06, 2026-09-07): a 35%-wide segment sweeps the
773
+ * track and returns. The 0% and 100% stops are IDENTICAL on purpose — the global
774
+ * prefers-reduced-motion reset in base.css collapses every animation to its `to`
775
+ * state, so a reduced-motion user sees a static 35% segment resting at the start
776
+ * of the track instead of a bar that reads as 100% complete. */
777
+ 0% {
778
+ inset-inline-start: 0%;
779
+ }
780
+ 50% {
781
+ inset-inline-start: 65%;
782
+ }
783
+ 100% {
784
+ inset-inline-start: 0%;
785
+ }
786
+ }
787
+
788
+ @utility motion-indeterminate {
789
+ animation: vs-indeterminate var(--duration-indeterminate)
790
+ var(--motion-ease-standard) infinite;
791
+ }
792
+
793
+ /* ---------------------------------------------------------------------------
794
+ * motion-dock-in / motion-dock-out — the docked-control enter/exit pair
795
+ * (audit D11 amendment #7, 2026-09-07).
796
+ *
797
+ * A docked control — a bottom action bar, a floating scroll-to-end button —
798
+ * stays MOUNTED and flips a `data-active` attribute, so its motion is a
799
+ * transition, not a keyed animation. That is why this is a pair rather than one
800
+ * `@utility`: the two states carry different timing, which is the whole point.
801
+ *
802
+ * The doctrine these encode: **an exit is never slower than its enter.** Both
803
+ * bars previously entered at `duration-base` and left at `duration-slow` with a
804
+ * `scale-95`, so dismissing one took half again as long as summoning it and the
805
+ * bar shrank as it went. Vercel, Linear and Base UI's own defaults all leave at
806
+ * or faster than they arrive. Enter is 150ms `emphasized`; exit is 100ms `exit`;
807
+ * a docked bar translates and fades and does not scale — scale reads as a popup,
808
+ * and a bar sliding off its own edge does not need it.
809
+ *
810
+ * 100ms has exactly one role in the system — this exit — so it lives here, in
811
+ * the utility that names it, rather than becoming a fifth global duration token
812
+ * that would invite reuse D11 did not sanction.
813
+ *
814
+ * These own the timing, the fade and the inert-while-hidden guard. The DISTANCE
815
+ * stays at the call site as ordinary `translate-*` utilities, because it is
816
+ * per-dock geometry (a bottom bar clears its own height plus the safe-area
817
+ * inset; an edge button clears 100%) and because Tailwind composes `translate-x`
818
+ * and `translate-y` through custom properties that a `translate:` declaration
819
+ * here would clobber — a horizontally-centred bar would lose its centring.
820
+ *
821
+ * The global prefers-reduced-motion reset in base.css collapses both to 0.01ms.
822
+ *
823
+ * <div data-active={open}
824
+ * className="data-[active=true]:motion-dock-in data-[active=true]:translate-y-0
825
+ * data-[active=false]:motion-dock-out data-[active=false]:translate-y-full" />
826
+ * ------------------------------------------------------------------------- */
827
+ @utility motion-dock-in {
828
+ transition-property: translate, opacity;
829
+ transition-duration: var(--duration-fast);
830
+ transition-timing-function: var(--motion-ease-emphasized);
831
+ opacity: 1;
832
+ }
833
+
834
+ @utility motion-dock-out {
835
+ transition-property: translate, opacity;
836
+ transition-duration: 100ms;
837
+ transition-timing-function: var(--motion-ease-exit);
838
+ opacity: 0;
839
+ /* A docked-out control is off-screen: it must not swallow clicks on the way
840
+ out, and it must not be a hit target while parked. */
841
+ pointer-events: none;
842
+ }
843
+
679
844
  /* ---------------------------------------------------------------------------
680
845
  * BrandIcon theme-aware artwork swap (`<BrandIcon variant="auto">`).
681
846
  *
@@ -690,9 +855,6 @@
690
855
  * silently never be generated downstream (it wasn't generated in our own docs
691
856
  * either — see the dead `packages/icons` @source). Shipping the rules in the
692
857
  * stylesheet consumers already import makes the swap work everywhere.
693
- *
694
- * `.vs-marketing` is included so a brand mark inside the marketing dark ground
695
- * picks the dark artwork even while the page theme is light.
696
858
  * ------------------------------------------------------------------------- */
697
859
  [data-brand-artwork="light"] {
698
860
  display: contents;
@@ -700,17 +862,9 @@
700
862
  [data-brand-artwork="dark"] {
701
863
  display: none;
702
864
  }
703
- .dark [data-brand-artwork="light"],
704
- .vs-marketing [data-brand-artwork="light"] {
865
+ .dark [data-brand-artwork="light"] {
705
866
  display: none;
706
867
  }
707
- .dark [data-brand-artwork="dark"],
708
- .vs-marketing [data-brand-artwork="dark"] {
868
+ .dark [data-brand-artwork="dark"] {
709
869
  display: contents;
710
870
  }
711
-
712
- /* `.vs-marketing`'s semantic variables and `color-scheme: dark` now live in
713
- * generated theme.css. build-tokens.mjs emits the scope from the SAME resolved
714
- * Style Dictionary dark run as `.dark`, and verify-theme-parity.mjs rejects any
715
- * variable-set or value drift. The artwork selectors above remain here because
716
- * 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.2.0",
3
+ "version": "0.5.0",
4
4
  "description": "VegaStack design tokens (DTCG → Tailwind v4 theme + TS)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -31,17 +31,17 @@
31
31
  "./tokens.json": "./dist/tokens.json",
32
32
  "./package.json": "./package.json"
33
33
  },
34
- "devDependencies": {
35
- "style-dictionary": "5.5.0",
36
- "typescript": "^6.0.3",
37
- "@vegastack/typescript-config": "0.0.0"
38
- },
39
- "publishConfig": {
40
- "access": "public"
41
- },
42
34
  "scripts": {
43
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",
44
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",
45
37
  "typecheck": "tsc --noEmit"
38
+ },
39
+ "devDependencies": {
40
+ "@vegastack/typescript-config": "workspace:*",
41
+ "style-dictionary": "5.5.2",
42
+ "typescript": "catalog:"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
46
  }
47
- }
47
+ }