@ttoss/fsl-theme 1.1.12 → 1.1.14
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/Types-BiBa17RL.d.cts +1427 -0
- package/dist/Types-BiBa17RL.d.mts +1427 -0
- package/dist/baseBundle-DxvXyhGa.mjs +17 -0
- package/dist/baseBundle-iEFf5nqT.cjs +22 -0
- package/dist/{esm/chunk-SE5Z52RE.js → createTheme-BLNYztZU.mjs} +76 -172
- package/dist/createTheme-Cv6RP9D6.cjs +1825 -0
- package/dist/css.cjs +48 -0
- package/dist/{css.d.ts → css.d.cts} +67 -63
- package/dist/css.d.mts +168 -0
- package/dist/css.mjs +42 -0
- package/dist/dataviz/index.cjs +45 -0
- package/dist/dataviz/{index.d.ts → index.d.cts} +9 -5
- package/dist/dataviz/index.d.mts +66 -0
- package/dist/dataviz/index.mjs +39 -0
- package/dist/dtcg.cjs +115 -0
- package/dist/{dtcg.d.ts → dtcg.d.cts} +9 -7
- package/dist/dtcg.d.mts +51 -0
- package/dist/dtcg.mjs +112 -0
- package/dist/helpers-4p4-QVt_.cjs +258 -0
- package/dist/helpers-CaswNJMy.mjs +211 -0
- package/dist/{index.d.ts → index-CsIjfw86.d.cts} +42 -34
- package/dist/index-nJrjI0BA.d.mts +94 -0
- package/dist/index.cjs +16 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +7 -0
- package/dist/{react.d.ts → react-CGa6FlNL.d.cts} +130 -106
- package/dist/react-DnKxR2gK.d.mts +370 -0
- package/dist/react-EUwpdvY7.cjs +481 -0
- package/dist/react.cjs +12 -0
- package/dist/react.d.cts +4 -0
- package/dist/react.d.mts +4 -0
- package/dist/react.mjs +412 -0
- package/dist/runtime-entry.cjs +9 -0
- package/dist/runtime-entry.d.cts +3 -0
- package/dist/runtime-entry.d.mts +3 -0
- package/dist/runtime-entry.mjs +3 -0
- package/dist/{runtime-entry.d.ts → ssrScript-BVysxDws.d.cts} +26 -23
- package/dist/ssrScript-BVysxDws.d.mts +98 -0
- package/dist/ssrScript-CRfrN8Pm.cjs +202 -0
- package/dist/ssrScript-D3kGPQpi.mjs +179 -0
- package/dist/themes/bruttal.cjs +75 -0
- package/dist/themes/bruttal.d.cts +3 -0
- package/dist/themes/bruttal.d.mts +3 -0
- package/dist/themes/bruttal.mjs +72 -0
- package/dist/themes/corporate.cjs +34 -0
- package/dist/themes/corporate.d.cts +3 -0
- package/dist/themes/corporate.d.mts +3 -0
- package/dist/{esm/chunk-TPMN75JM.js → themes/corporate.mjs} +7 -5
- package/dist/themes/oca.cjs +34 -0
- package/dist/themes/oca.d.cts +3 -0
- package/dist/themes/oca.d.mts +3 -0
- package/dist/{esm/chunk-DU4QDQUC.js → themes/oca.mjs} +7 -5
- package/dist/themes/ventures.cjs +34 -0
- package/dist/themes/ventures.d.cts +3 -0
- package/dist/themes/ventures.d.mts +3 -0
- package/dist/{esm/chunk-BXKVVQEP.js → themes/ventures.mjs} +7 -5
- package/dist/toCssVars-CYZCe-on.mjs +286 -0
- package/dist/toCssVars-DudHKvt2.cjs +297 -0
- package/dist/{esm/chunk-4Q4P3JBB.js → tokenRegistry-DjgSN3oU.mjs} +23 -20
- package/dist/tokenRegistry-OhaJ9sPJ.cjs +199 -0
- package/dist/vars.cjs +127 -0
- package/dist/{vars.d.ts → vars.d.cts} +8 -7
- package/dist/vars.d.mts +128 -0
- package/dist/vars.mjs +123 -0
- package/dist/withDataviz-B4pVsOwV.cjs +192 -0
- package/dist/{esm/chunk-FBVUI2PK.js → withDataviz-DY5s7R51.mjs} +40 -12
- package/package.json +6 -6
- package/dist/Types-6tR0_2Ss.d.ts +0 -1452
- package/dist/esm/chunk-5PWPAQMC.js +0 -9
- package/dist/esm/chunk-HRNXVRS3.js +0 -54
- package/dist/esm/chunk-IJGA42O6.js +0 -141
- package/dist/esm/chunk-PQPQNZ73.js +0 -262
- package/dist/esm/chunk-UMRQ4OTX.js +0 -11
- package/dist/esm/chunk-VL6EGE6Z.js +0 -222
- package/dist/esm/chunk-WVQSTQD5.js +0 -192
- package/dist/esm/css.js +0 -6
- package/dist/esm/dataviz/index.js +0 -19
- package/dist/esm/dtcg.js +0 -65
- package/dist/esm/index.js +0 -10
- package/dist/esm/react.js +0 -8
- package/dist/esm/runtime-entry.js +0 -4
- package/dist/esm/themes/bruttal.js +0 -6
- package/dist/esm/themes/corporate.js +0 -6
- package/dist/esm/themes/oca.js +0 -6
- package/dist/esm/themes/ventures.js +0 -6
- package/dist/esm/vars.js +0 -28
- package/dist/themes/bruttal.d.ts +0 -5
- package/dist/themes/corporate.d.ts +0 -5
- package/dist/themes/oca.d.ts +0 -5
- package/dist/themes/ventures.d.ts +0 -5
|
@@ -0,0 +1,1427 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/dataviz/Types.d.ts
|
|
3
|
+
type Scale1To8 = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
4
|
+
type Scale1To7 = 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
|
5
|
+
type Scale1To6 = 1 | 2 | 3 | 4 | 5 | 6;
|
|
6
|
+
/**
|
|
7
|
+
* Core data visualization token tree.
|
|
8
|
+
*
|
|
9
|
+
* Contains non-color encoding primitives only.
|
|
10
|
+
* Color tokens are sourced directly from `core.colors.*` — no separate dataviz
|
|
11
|
+
* color palette is needed. Semantic dataviz color tokens reference `core.colors.*`.
|
|
12
|
+
*
|
|
13
|
+
* Placed at `theme.core.dataviz` — optional extension of `ThemeTokens`.
|
|
14
|
+
*/
|
|
15
|
+
interface CoreDataviz {
|
|
16
|
+
/** Mark shapes for categorical differentiation (e.g. 'circle', 'square'). */
|
|
17
|
+
shape: Record<Scale1To8, RawValue>;
|
|
18
|
+
/** Fill patterns for area/region differentiation (e.g. 'diagonal-stripes'). */
|
|
19
|
+
pattern: Record<Scale1To6, RawValue>;
|
|
20
|
+
/** Stroke dash patterns as SVG-compatible dash-array strings. */
|
|
21
|
+
stroke: {
|
|
22
|
+
solid: RawValue;
|
|
23
|
+
dashed: RawValue;
|
|
24
|
+
dotted: RawValue;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Analytical opacity primitives.
|
|
28
|
+
* Distinct from foundation opacity — used as encoding channels, not UI effects.
|
|
29
|
+
*/
|
|
30
|
+
opacity: {
|
|
31
|
+
/** Geographic/spatial context reduction behind overlays. */context: NumericValue; /** De-emphasis of non-highlighted data marks. */
|
|
32
|
+
muted: NumericValue; /** Visual signal of estimated or uncertain data. */
|
|
33
|
+
uncertainty: NumericValue;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Semantic categorical and scale color roles.
|
|
38
|
+
*
|
|
39
|
+
* Paths (in code: semantic.dataviz.color.*):
|
|
40
|
+
* dataviz.color.series.1..8
|
|
41
|
+
* dataviz.color.scale.sequential.1..7
|
|
42
|
+
* dataviz.color.scale.diverging.neg3..pos3
|
|
43
|
+
* dataviz.color.reference.baseline / target
|
|
44
|
+
* dataviz.color.state.highlight / muted / selected
|
|
45
|
+
* dataviz.color.status.missing / suppressed / not-applicable
|
|
46
|
+
*/
|
|
47
|
+
interface SemanticDatavizColor {
|
|
48
|
+
/**
|
|
49
|
+
* Categorical series identity — 8 named, unordered roles.
|
|
50
|
+
* Use for nominal categories, named series, distinct groups.
|
|
51
|
+
*/
|
|
52
|
+
series: Record<Scale1To8, TokenRef>;
|
|
53
|
+
scale: {
|
|
54
|
+
/**
|
|
55
|
+
* Ordered magnitude — 7 steps from low (1) to high (7).
|
|
56
|
+
* Use for quantitative ranges and progressive intensity.
|
|
57
|
+
*/
|
|
58
|
+
sequential: Record<Scale1To7, TokenRef>;
|
|
59
|
+
/**
|
|
60
|
+
* Midpoint comparison — 7 named positions around a true center.
|
|
61
|
+
* Only use when the data has a meaningful midpoint (zero, baseline, target).
|
|
62
|
+
*/
|
|
63
|
+
diverging: {
|
|
64
|
+
neg3: TokenRef;
|
|
65
|
+
neg2: TokenRef;
|
|
66
|
+
neg1: TokenRef; /** Neutral midpoint class. */
|
|
67
|
+
neutral: TokenRef;
|
|
68
|
+
pos1: TokenRef;
|
|
69
|
+
pos2: TokenRef;
|
|
70
|
+
pos3: TokenRef;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
reference: {
|
|
74
|
+
/** Color for a baseline or reference level (e.g. average, goal). */baseline: TokenRef; /** Color for a target or objective line. */
|
|
75
|
+
target: TokenRef;
|
|
76
|
+
};
|
|
77
|
+
state: {
|
|
78
|
+
/** Emphasized / highlighted data mark. */highlight: TokenRef; /** De-emphasized / non-highlighted data mark. */
|
|
79
|
+
muted: TokenRef; /** User-selected or actively focused data mark. */
|
|
80
|
+
selected: TokenRef;
|
|
81
|
+
};
|
|
82
|
+
status: {
|
|
83
|
+
/** Value is absent or unavailable. */missing: TokenRef; /** Value is withheld for confidentiality or publication rules. */
|
|
84
|
+
suppressed: TokenRef; /** Value is structurally absent (not measured or not applicable). */
|
|
85
|
+
na: TokenRef;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Semantic non-color encoding roles.
|
|
90
|
+
*
|
|
91
|
+
* Paths: dataviz.encoding.*
|
|
92
|
+
*/
|
|
93
|
+
interface SemanticDatavizEncoding {
|
|
94
|
+
shape: {
|
|
95
|
+
/** Series identity through mark shape — use for redundant differentiation. */series: Record<Scale1To8, TokenRef>;
|
|
96
|
+
};
|
|
97
|
+
pattern: {
|
|
98
|
+
/** Series identity through fill texture — use for filled marks and overlays. */series: Record<Scale1To6, TokenRef>;
|
|
99
|
+
};
|
|
100
|
+
stroke: {
|
|
101
|
+
/** Stroke style for analytical reference guides or baselines. */reference: TokenRef; /** Stroke style for projected or forward-looking data segments. */
|
|
102
|
+
forecast: TokenRef; /** Stroke style for uncertain or estimated bounds. */
|
|
103
|
+
uncertainty: TokenRef;
|
|
104
|
+
};
|
|
105
|
+
opacity: {
|
|
106
|
+
/** Opacity for contextual elements behind overlay data. */context: TokenRef; /** Opacity for de-emphasized (non-highlighted) data marks. */
|
|
107
|
+
muted: TokenRef; /** Opacity for representing estimated or uncertain data visually. */
|
|
108
|
+
uncertainty: TokenRef;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Semantic geospatial overlay roles.
|
|
113
|
+
*
|
|
114
|
+
* Defines only the contextual relationship between overlays and geography.
|
|
115
|
+
* Geospatial overlays use `dataviz.color.*` and `dataviz.encoding.*` for
|
|
116
|
+
* analytical meaning — these tokens cover only spatial context.
|
|
117
|
+
*
|
|
118
|
+
* Paths: dataviz.geo.*
|
|
119
|
+
*/
|
|
120
|
+
interface SemanticDatavizGeo {
|
|
121
|
+
context: {
|
|
122
|
+
/** Reduced background wash for geographic base layer. */muted: TokenRef; /** Color for supportive boundary lines (region outlines, coastlines). */
|
|
123
|
+
boundary: TokenRef; /** Color for contextual geographic labels (city names, region labels). */
|
|
124
|
+
label: TokenRef;
|
|
125
|
+
};
|
|
126
|
+
state: {
|
|
127
|
+
/** Fill or stroke for a spatially selected region. */selection: TokenRef; /** Fill or stroke for spatially focused region (keyboard / pointer focus). */
|
|
128
|
+
focus: TokenRef;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Full semantic data visualization token tree.
|
|
133
|
+
*
|
|
134
|
+
* Placed at `theme.semantic.dataviz` — optional extension of `ThemeTokens`.
|
|
135
|
+
* This is the **public API** of the Data Visualization extension.
|
|
136
|
+
* Components and patterns must consume only these tokens.
|
|
137
|
+
*/
|
|
138
|
+
interface SemanticDataviz {
|
|
139
|
+
color: SemanticDatavizColor;
|
|
140
|
+
encoding: SemanticDatavizEncoding;
|
|
141
|
+
geo: SemanticDatavizGeo;
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/families/primitives.d.ts
|
|
145
|
+
/** A raw CSS value (color hex, px, clamp expression, etc.) */
|
|
146
|
+
type RawValue = string;
|
|
147
|
+
/** A numeric raw value (font weight, opacity, line-height, z-index, etc.) */
|
|
148
|
+
type NumericValue = number;
|
|
149
|
+
/**
|
|
150
|
+
* A reference to a core token, expressed as `{token.path}`.
|
|
151
|
+
*
|
|
152
|
+
* Optionally narrowed to a path prefix family for autocomplete and typo
|
|
153
|
+
* catching at high-leverage positions. Defaults to `string` — fully open —
|
|
154
|
+
* which preserves the original (untyped-path) behavior for any external code
|
|
155
|
+
* importing `TokenRef` directly.
|
|
156
|
+
*
|
|
157
|
+
* Narrowed aliases cover every semantic family. The only remaining open
|
|
158
|
+
* `TokenRef` is `SemanticFocus.ring.color`, which intentionally references a
|
|
159
|
+
* `semantic.*` path rather than a `core.*` one.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* // open — accepts any '{...}' string
|
|
164
|
+
* const ref: TokenRef = '{core.colors.brand.500}';
|
|
165
|
+
*
|
|
166
|
+
* // narrowed — '{core.spacing.|' autocompletes; '{core.colorz.…}' errors
|
|
167
|
+
* const gap: TokenRef<`core.spacing.${string}`> = '{core.spacing.4}';
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
type TokenRef<TPath extends string = string> = `{${TPath}}`;
|
|
171
|
+
/** Reference into the `core.colors.*` namespace. */
|
|
172
|
+
type CoreColorRef = TokenRef<`core.colors.${string}`>;
|
|
173
|
+
/** Reference into the `core.spacing.*` namespace. */
|
|
174
|
+
type CoreSpacingRef = TokenRef<`core.spacing.${string}`>;
|
|
175
|
+
/** Reference into the `core.sizing.*` namespace. */
|
|
176
|
+
type CoreSizingRef = TokenRef<`core.sizing.${string}`>;
|
|
177
|
+
/** Reference into the `core.font.scale.*` namespace (responsive size ramp). */
|
|
178
|
+
type CoreFontScaleRef = TokenRef<`core.font.scale.${string}`>;
|
|
179
|
+
/** Reference into the `core.font.*` namespace (family, weight, leading, tracking, optical, numeric). */
|
|
180
|
+
type CoreFontRef = TokenRef<`core.font.${string}`>;
|
|
181
|
+
/** Reference into the `core.elevation.*` namespace. */
|
|
182
|
+
type CoreElevationRef = TokenRef<`core.elevation.${string}`>;
|
|
183
|
+
/** Reference into the `core.radii.*` namespace. */
|
|
184
|
+
type CoreRadiiRef = TokenRef<`core.radii.${string}`>;
|
|
185
|
+
/** Reference into the `core.border.*` namespace (width and style sub-families). */
|
|
186
|
+
type CoreBorderRef = TokenRef<`core.border.${string}`>;
|
|
187
|
+
/** Reference into the `core.opacity.*` namespace. */
|
|
188
|
+
type CoreOpacityRef = TokenRef<`core.opacity.${string}`>;
|
|
189
|
+
/** Reference into the `core.motion.*` namespace (duration and easing sub-families). */
|
|
190
|
+
type CoreMotionRef = TokenRef<`core.motion.${string}`>;
|
|
191
|
+
/** Reference into the `core.zIndex.*` namespace. */
|
|
192
|
+
type CoreZIndexRef = TokenRef<`core.zIndex.${string}`>;
|
|
193
|
+
/**
|
|
194
|
+
* Recursive partial type. Every nested property becomes optional,
|
|
195
|
+
* enabling selective overrides at any depth.
|
|
196
|
+
*/
|
|
197
|
+
type DeepPartial<T> = T extends object ? { [P in keyof T]?: DeepPartial<T[P]> } : T;
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/families/borders.d.ts
|
|
200
|
+
/**
|
|
201
|
+
* Core line widths — intent-free primitives.
|
|
202
|
+
* `selected` and `focused` must resolve to a width strictly greater than `default`.
|
|
203
|
+
* Never reference these directly from components — use semantic border tokens.
|
|
204
|
+
*/
|
|
205
|
+
interface CoreBorderWidths {
|
|
206
|
+
none: RawValue;
|
|
207
|
+
default: RawValue;
|
|
208
|
+
selected: RawValue;
|
|
209
|
+
focused: RawValue;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Core line styles — intent-free primitives.
|
|
213
|
+
* Default to `solid`; use `dashed` or `dotted` only when the pattern truly requires it.
|
|
214
|
+
*/
|
|
215
|
+
interface CoreBorderStyles {
|
|
216
|
+
solid: RawValue;
|
|
217
|
+
dashed: RawValue;
|
|
218
|
+
dotted: RawValue;
|
|
219
|
+
none: RawValue;
|
|
220
|
+
}
|
|
221
|
+
/** Intent-free line primitives — width and style only. */
|
|
222
|
+
interface CoreBorder {
|
|
223
|
+
width: CoreBorderWidths;
|
|
224
|
+
style: CoreBorderStyles;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Shared shape for every semantic line contract: width + style references only.
|
|
228
|
+
* Color is never part of this contract — pair with semantic color tokens.
|
|
229
|
+
* @see SemanticColors — for border color tokens per UX context.
|
|
230
|
+
*/
|
|
231
|
+
interface SemanticBorderOutline {
|
|
232
|
+
width: CoreBorderRef;
|
|
233
|
+
style: CoreBorderRef;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Semantic line contracts — the stable API consumed by components.
|
|
237
|
+
*
|
|
238
|
+
* Four canonical contracts (borders.md §Canonical semantic set):
|
|
239
|
+
* @see borders.md
|
|
240
|
+
* - `divider` — structural separator between content groups
|
|
241
|
+
* - `outline.surface` — boundary of containing surfaces (cards, panels, dialogs)
|
|
242
|
+
* - `outline.control` — boundary of interactive controls (buttons, inputs, toggles)
|
|
243
|
+
* - `outline.selected` — stronger-thickness indicator for selected/current state
|
|
244
|
+
*
|
|
245
|
+
* Rules:
|
|
246
|
+
* - Components consume these tokens only — never `core.border.*` directly.
|
|
247
|
+
* - `outline.selected` must resolve to a width strictly greater than `outline.{surface,control}`.
|
|
248
|
+
* - Color meaning stays in the color system; these tokens define geometry only.
|
|
249
|
+
* - Do not add component-specific tokens (`border.input`, `border.card`, etc.).
|
|
250
|
+
*
|
|
251
|
+
* @adr ADR-011 — `outline.selected` lives inside `outline.*` (shape grouping); `focus.ring` stays separate (accessibility contract + color field).
|
|
252
|
+
*/
|
|
253
|
+
interface SemanticBorder {
|
|
254
|
+
/**
|
|
255
|
+
* Structural separator between content groups (low emphasis).
|
|
256
|
+
* Use when splitting list rows, sections, toolbar regions, or grouped fields
|
|
257
|
+
* — anywhere the line *separates* without enclosing.
|
|
258
|
+
* Pair with a low-emphasis color (`informational.muted.border.default`); do
|
|
259
|
+
* not use to enclose a surface or control — those are `outline.surface` /
|
|
260
|
+
* `outline.control`.
|
|
261
|
+
*/
|
|
262
|
+
divider: SemanticBorderOutline;
|
|
263
|
+
outline: {
|
|
264
|
+
/**
|
|
265
|
+
* Boundary of a containing surface (card, panel, dialog, menu, grouped region).
|
|
266
|
+
* Use when the element *contains* other content and needs a visible edge.
|
|
267
|
+
* Pair with `informational.{role}.border.{state}` colors and (optionally)
|
|
268
|
+
* `semantic.elevation.surface.*`; do not use for interactive controls — those
|
|
269
|
+
* are `outline.control`.
|
|
270
|
+
*/
|
|
271
|
+
surface: SemanticBorderOutline;
|
|
272
|
+
/**
|
|
273
|
+
* Boundary of an interactive control (button, input, toggle, chip, segmented item).
|
|
274
|
+
* Use when the element is interactive and needs a visible edge at rest.
|
|
275
|
+
* Pair with `{ux}.{role}.border.{state}` colors per FSL UX context; do not
|
|
276
|
+
* use for containing surfaces — those are `outline.surface`.
|
|
277
|
+
*/
|
|
278
|
+
control: SemanticBorderOutline;
|
|
279
|
+
/**
|
|
280
|
+
* Stronger-thickness boundary expressing selected / current state.
|
|
281
|
+
* Use when selection or current-item status is communicated by line weight
|
|
282
|
+
* (active tab, selected row, chosen card).
|
|
283
|
+
* Resolves to a width strictly greater than `outline.{surface,control}`. Do
|
|
284
|
+
* not use for keyboard focus — that is `semantic.focus.ring`.
|
|
285
|
+
*/
|
|
286
|
+
selected: SemanticBorderOutline;
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
//#endregion
|
|
290
|
+
//#region src/families/breakpoints.d.ts
|
|
291
|
+
interface CoreBreakpoints {
|
|
292
|
+
sm: RawValue;
|
|
293
|
+
md: RawValue;
|
|
294
|
+
lg: RawValue;
|
|
295
|
+
xl: RawValue;
|
|
296
|
+
'2xl': RawValue;
|
|
297
|
+
}
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/families/colors.d.ts
|
|
300
|
+
/**
|
|
301
|
+
* Unified color scale steps (0–1000).
|
|
302
|
+
* Themes may use any subset; step 500 is always required as the canonical mid-point.
|
|
303
|
+
*/
|
|
304
|
+
type CoreColorStep = 0 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000;
|
|
305
|
+
/**
|
|
306
|
+
* Palette scale — partial record over CoreColorStep with 500 required.
|
|
307
|
+
* Sparse palettes (100/300/500/700/900) and dense palettes (0–1000) both conform.
|
|
308
|
+
*/
|
|
309
|
+
type CoreColorScale = Partial<Record<CoreColorStep, RawValue>> & {
|
|
310
|
+
500: RawValue;
|
|
311
|
+
};
|
|
312
|
+
/**
|
|
313
|
+
* Core color tokens — intent-free palette primitives.
|
|
314
|
+
*
|
|
315
|
+
* Rules:
|
|
316
|
+
* - Core names define palette families and scale positions, never usage.
|
|
317
|
+
* - No semantic naming (no `danger`, `warning`, `link`, `surface`, etc.).
|
|
318
|
+
* - No mode naming (core values are immutable across modes).
|
|
319
|
+
* - No component naming (no `cardBg`, `inputBorder`, etc.).
|
|
320
|
+
*
|
|
321
|
+
* @see colors.md
|
|
322
|
+
*/
|
|
323
|
+
interface CoreColors {
|
|
324
|
+
/** Primary brand identity color scale. */
|
|
325
|
+
brand: CoreColorScale;
|
|
326
|
+
/**
|
|
327
|
+
* Zero-saturation anchor scale (greyscale/slate).
|
|
328
|
+
* Provides surfaces, text contrast, dividers, and subdued UI.
|
|
329
|
+
* Named `neutral` by convention — not a semantic role, purely a palette family.
|
|
330
|
+
* Use step 0 for white-end and step 1000 for black-end.
|
|
331
|
+
*/
|
|
332
|
+
neutral: CoreColorScale;
|
|
333
|
+
/**
|
|
334
|
+
* Open hue families. Themes define which they need (red, green, yellow, blue, etc.).
|
|
335
|
+
* No fixed set is required beyond `brand` and `neutral`.
|
|
336
|
+
*/
|
|
337
|
+
[hue: string]: CoreColorScale;
|
|
338
|
+
}
|
|
339
|
+
/** Base interaction states — available in every UX context.
|
|
340
|
+
* `selected` is NOT included here — it is added only by the UX contexts
|
|
341
|
+
* where set-membership semantics apply (input, navigation, informational).
|
|
342
|
+
* Action context uses `pressed` for toggle state instead (FSL Lexicon §7).
|
|
343
|
+
*/
|
|
344
|
+
interface BaseColorStates {
|
|
345
|
+
/** Resting / base state. The colour rendered when no other state asserts. */
|
|
346
|
+
default: CoreColorRef;
|
|
347
|
+
/** Pointer is currently over the element. Do not use for keyboard focus — that is `focused`. */
|
|
348
|
+
hover?: CoreColorRef;
|
|
349
|
+
/** Pointer or key is currently *down* on the element — transient, lasts only while held. Releases back to `default` / `hover`. Do not use for persistent toggle state — that is `pressed`. */
|
|
350
|
+
active?: CoreColorRef;
|
|
351
|
+
/** Element has keyboard or programmatic focus. Pair with `semantic.focus.ring.color` when no `{ux}.{role}` context applies. */
|
|
352
|
+
focused?: CoreColorRef;
|
|
353
|
+
/** Element is non-interactive. Carries the contrast guarantees that `semantic.opacity.disabled` cannot — prefer this for controls and text over opacity. */
|
|
354
|
+
disabled?: CoreColorRef;
|
|
355
|
+
/**
|
|
356
|
+
* Valid drag-and-drop destination during an active drag (FSL Lexicon §7).
|
|
357
|
+
* Applies wherever drop-target semantics are valid: file inputs, collection rows,
|
|
358
|
+
* informational surfaces, and any other entity that accepts dropped items.
|
|
359
|
+
*/
|
|
360
|
+
droptarget?: CoreColorRef;
|
|
361
|
+
}
|
|
362
|
+
/** `action` context: adds `pressed` for toggle controls and `expanded` for disclosure triggers and open menus. */
|
|
363
|
+
interface ActionColorStates extends BaseColorStates {
|
|
364
|
+
/** Toggle button is currently engaged — *persistent*, not transient. Use for toolbar toggles ("Bold" pressed). Do not confuse with `active` (the brief moment of clicking). */
|
|
365
|
+
pressed?: CoreColorRef;
|
|
366
|
+
/** Disclosure trigger or menu button is currently open. Use for buttons that own an open popup, menu, or panel. */
|
|
367
|
+
expanded?: CoreColorRef;
|
|
368
|
+
}
|
|
369
|
+
/** `input` context: adds `checked`, `indeterminate`, `pressed`, `expanded` for form controls.
|
|
370
|
+
*
|
|
371
|
+
* Validation failure is *not* a state — it is an Evaluation (FSL Lexicon §5).
|
|
372
|
+
* Components that fail validation render with the `input.negative.*` role,
|
|
373
|
+
* not with an `invalid` state on `input.primary.*`. This avoids dual
|
|
374
|
+
* representation of the same semantic concept and keeps FSL §7 State Law
|
|
375
|
+
* intact ("States are not free-form"). React Aria's `isInvalid` flag maps
|
|
376
|
+
* to selecting the `negative` role, not to a new state.
|
|
377
|
+
*
|
|
378
|
+
* Structural Role → token mapping (FSL Lexicon §2): a part declared with
|
|
379
|
+
* Structural Role `validationMessage` consumes `input.negative.text.*` for
|
|
380
|
+
* its text dimension (and `input.negative.{background,border}.*` if it
|
|
381
|
+
* carries those dimensions). `validationMessage` is anatomy (which part);
|
|
382
|
+
* `input.negative.*` is the visual contract (which value). The same
|
|
383
|
+
* Evaluation token lawfully serves multiple Structural Roles — this is the
|
|
384
|
+
* intended single-source semantics, not duplication. */
|
|
385
|
+
interface InputColorStates extends BaseColorStates {
|
|
386
|
+
/** Element is **one of many** in a set and the user picked it (segment in a segmented control, picker option). Do not use for two-state controls — those are `checked`. */
|
|
387
|
+
selected?: CoreColorRef;
|
|
388
|
+
/** **Two-state control** that is currently on — checkbox, radio, switch. Do not use for selection from a set — that is `selected`. */
|
|
389
|
+
checked?: CoreColorRef;
|
|
390
|
+
/** Boolean control in a mixed / unknown state — e.g. parent checkbox over partially-checked children. */
|
|
391
|
+
indeterminate?: CoreColorRef;
|
|
392
|
+
/** Persistent engaged state of a toggle-style input (e.g. a switch rendered as a button). See `ActionColorStates.pressed` for the disambiguation against `active`. */
|
|
393
|
+
pressed?: CoreColorRef;
|
|
394
|
+
/** Combobox / select / disclosure-style input is currently open. */
|
|
395
|
+
expanded?: CoreColorRef;
|
|
396
|
+
}
|
|
397
|
+
/** `navigation` context: adds `selected`, `current`, `visited`, `expanded`. */
|
|
398
|
+
interface NavigationColorStates extends BaseColorStates {
|
|
399
|
+
/** Tab / item is **one of many** in the set and the user picked it. May coexist with `current` when the selected item also represents the live route. */
|
|
400
|
+
selected?: CoreColorRef;
|
|
401
|
+
/** Element is the user's **current location** in the navigation set — active route, current step in a wizard. Do not use for set-membership without a routing meaning — that is `selected`. */
|
|
402
|
+
current?: CoreColorRef;
|
|
403
|
+
/** Link points to a URL the user has visited. */
|
|
404
|
+
visited?: CoreColorRef;
|
|
405
|
+
/** Disclosure-style nav item (collapsible section, expandable submenu) is currently open. */
|
|
406
|
+
expanded?: CoreColorRef;
|
|
407
|
+
}
|
|
408
|
+
/** `informational` context: adds `selected`, `visited`, `expanded`.
|
|
409
|
+
*
|
|
410
|
+
* `expanded` covers in-place disclosure on presentational surfaces (accordions,
|
|
411
|
+
* collapsible panels, expandable cards). `Disclosure` Entity Kinds project to
|
|
412
|
+
* `informational` per FSL identity (in-place reveal, not movement across
|
|
413
|
+
* destinations — FSL Lexicon §1). */
|
|
414
|
+
interface InformationalColorStates extends BaseColorStates {
|
|
415
|
+
/** Presentational element is **one of many** and the user picked it (selectable list row, focused card in a deck). */
|
|
416
|
+
selected?: CoreColorRef;
|
|
417
|
+
/** Visited link rendered inside informational content. */
|
|
418
|
+
visited?: CoreColorRef;
|
|
419
|
+
/** Accordion / collapsible panel / `<details>` is currently open — in-place reveal (FSL Lexicon §1). */
|
|
420
|
+
expanded?: CoreColorRef;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* `feedback` context state set — feedback components are not interactive triggers (FSL §7).
|
|
424
|
+
* Legal states: `default`, `focused` (focusable wrapper or close button), `disabled`.
|
|
425
|
+
* `hover`, `active`, `selected`, `pressed`, `expanded`, `droptarget` are illegal.
|
|
426
|
+
*/
|
|
427
|
+
interface FeedbackColorStates {
|
|
428
|
+
/** Resting / base state. The colour rendered when no other state asserts. */
|
|
429
|
+
default: CoreColorRef;
|
|
430
|
+
/** Element has keyboard or programmatic focus — e.g. a focusable close button inside the feedback component. */
|
|
431
|
+
focused?: CoreColorRef;
|
|
432
|
+
/** Element is non-interactive. Prefer this over `opacity.disabled` for controls and text that carry colour contrast guarantees. */
|
|
433
|
+
disabled?: CoreColorRef;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Color dimensions for a given UX context.
|
|
437
|
+
* Each dimension is optional — components choose which they consume.
|
|
438
|
+
* (e.g. a text link uses only `text`; a ghost button uses `text` + `border`)
|
|
439
|
+
*/
|
|
440
|
+
interface ColorDimensionOf<S extends BaseColorStates> {
|
|
441
|
+
/** Fills and surface backgrounds. Use for any colored area larger than a line. */
|
|
442
|
+
background?: S;
|
|
443
|
+
/** Outlines, separators, rings, and other line-color pairings. For line *geometry* (width, style) consume `semantic.borders.*` instead — this dimension is colour only. */
|
|
444
|
+
border?: S;
|
|
445
|
+
/** Readable foreground — labels, paragraphs, and text-like icons that inherit `currentColor`. */
|
|
446
|
+
text?: S;
|
|
447
|
+
}
|
|
448
|
+
/** `action`: triggers actions or changes state. Roles: primary | secondary | accent | muted | negative */
|
|
449
|
+
interface ActionColorRoles {
|
|
450
|
+
/** The single most important action on the view. Only one `primary` per `{ux}` per view — if two compete, the loser is `secondary`. */
|
|
451
|
+
primary: ColorDimensionOf<ActionColorStates>;
|
|
452
|
+
/** Alternative action that coexists with the primary one. Use when two actions share the surface and neither dominates. */
|
|
453
|
+
secondary: ColorDimensionOf<ActionColorStates>;
|
|
454
|
+
/** Highlighted action that draws attention without being the main path ("Try the new…" promo button). */
|
|
455
|
+
accent: ColorDimensionOf<ActionColorStates>;
|
|
456
|
+
/** Low-priority action — helper button, optional control, dismiss / cancel ghost. */
|
|
457
|
+
muted: ColorDimensionOf<ActionColorStates>;
|
|
458
|
+
/** Action whose intent is adverse: failure, invalid result, or destructive consequence (delete, cancel paid plan). Outcome (success / warning) lives in `feedback.*`, not here. */
|
|
459
|
+
negative: ColorDimensionOf<ActionColorStates>;
|
|
460
|
+
}
|
|
461
|
+
/** `input`: data entry, selection, form controls. Roles: primary | secondary | muted | positive | caution | negative */
|
|
462
|
+
interface InputColorRoles {
|
|
463
|
+
/** Default input role — the brand-influenced active style for the canonical control on the form. */
|
|
464
|
+
primary: ColorDimensionOf<InputColorStates>;
|
|
465
|
+
/** Alternative input role coexisting with `primary` — e.g. a secondary search field on the same surface. */
|
|
466
|
+
secondary: ColorDimensionOf<InputColorStates>;
|
|
467
|
+
/** Low-priority input — quiet text field, ghost search, optional metadata input. */
|
|
468
|
+
muted: ColorDimensionOf<InputColorStates>;
|
|
469
|
+
/** Input whose value reports success / completion / validity confirmed (e.g. "available" username field after async check). */
|
|
470
|
+
positive: ColorDimensionOf<InputColorStates>;
|
|
471
|
+
/** Input whose value carries risk that needs attention but does not block submission. */
|
|
472
|
+
caution: ColorDimensionOf<InputColorStates>;
|
|
473
|
+
/** Input whose value failed validation — maps from React Aria `isInvalid`. Validation failure is *not* a state on `primary`; it selects this role (FSL Lexicon §5). */
|
|
474
|
+
negative: ColorDimensionOf<InputColorStates>;
|
|
475
|
+
}
|
|
476
|
+
/** `navigation`: movement and orientation. Roles: primary | secondary | accent | muted */
|
|
477
|
+
interface NavigationColorRoles {
|
|
478
|
+
/** The dominant navigation surface on the view — main top nav, primary sidebar. */
|
|
479
|
+
primary: ColorDimensionOf<NavigationColorStates>;
|
|
480
|
+
/** Secondary navigation that coexists with the primary one — sub-nav, in-page tabs. */
|
|
481
|
+
secondary: ColorDimensionOf<NavigationColorStates>;
|
|
482
|
+
/** Highlighted nav item that draws attention without being the main path — "What's new", featured destination. */
|
|
483
|
+
accent: ColorDimensionOf<NavigationColorStates>;
|
|
484
|
+
/** Low-priority nav — footer links, breadcrumb separators, optional sub-items. */
|
|
485
|
+
muted: ColorDimensionOf<NavigationColorStates>;
|
|
486
|
+
}
|
|
487
|
+
/** `feedback`: reactive system/user-result messages. Roles: primary | muted | positive | caution | negative */
|
|
488
|
+
interface FeedbackColorRoles {
|
|
489
|
+
/** Neutral / informational feedback that carries no valence — "Auto-saved", "Connected". */
|
|
490
|
+
primary: ColorDimensionOf<FeedbackColorStates>;
|
|
491
|
+
/** Quiet feedback that should not steal attention — inline hints, low-priority status text. */
|
|
492
|
+
muted: ColorDimensionOf<FeedbackColorStates>;
|
|
493
|
+
/** Feedback reporting success, completion, or validity confirmed. */
|
|
494
|
+
positive: ColorDimensionOf<FeedbackColorStates>;
|
|
495
|
+
/** Feedback reporting risk that needs attention but does not block the user. */
|
|
496
|
+
caution: ColorDimensionOf<FeedbackColorStates>;
|
|
497
|
+
/** Feedback reporting failure or an invalid system state. */
|
|
498
|
+
negative: ColorDimensionOf<FeedbackColorStates>;
|
|
499
|
+
}
|
|
500
|
+
/** `informational`: informational surfaces and readable content. Roles: primary | secondary | accent | muted | positive | caution | negative */
|
|
501
|
+
interface InformationalColorRoles {
|
|
502
|
+
/** Dominant content / surface on the view — page background, main panel, the card the user is reading. */
|
|
503
|
+
primary: ColorDimensionOf<InformationalColorStates>;
|
|
504
|
+
/** Supporting content / surface coexisting with `primary` — sidebar panel, secondary card. */
|
|
505
|
+
secondary: ColorDimensionOf<InformationalColorStates>;
|
|
506
|
+
/** Highlighted content that draws attention without being the main path — featured callout, promo tile. */
|
|
507
|
+
accent: ColorDimensionOf<InformationalColorStates>;
|
|
508
|
+
/** Low-priority content — helper text, dividers, captions, metadata. */
|
|
509
|
+
muted: ColorDimensionOf<InformationalColorStates>;
|
|
510
|
+
/** Informational surface or text reporting success / completion (e.g. "All up to date" empty state). */
|
|
511
|
+
positive: ColorDimensionOf<InformationalColorStates>;
|
|
512
|
+
/** Informational surface or text carrying caution — warning panel, advisory note. */
|
|
513
|
+
caution: ColorDimensionOf<InformationalColorStates>;
|
|
514
|
+
/** Informational surface or text reporting failure or invalid state — error empty state, broken-state panel. */
|
|
515
|
+
negative: ColorDimensionOf<InformationalColorStates>;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Semantic colour API — the only colour contract components consume.
|
|
519
|
+
*
|
|
520
|
+
* Pick the UX context by asking *what kind of UI is this?* (colors.md §"UX contexts in 60 seconds"):
|
|
521
|
+
* is the user about to **act**, **type**, **move**, **hear back**, or just **see / contain** something?
|
|
522
|
+
*
|
|
523
|
+
* Token grammar: `{ux}.{role}.{dimension}.{state}`. Legal combinations are
|
|
524
|
+
* enforced by the type system; see colors.md §Legal Combinations.
|
|
525
|
+
*
|
|
526
|
+
* @see colors.md
|
|
527
|
+
*/
|
|
528
|
+
interface SemanticColors {
|
|
529
|
+
/** Anything the user **triggers** — buttons, toggles, menu items, action icons. Pick when the user is about to *act*. */
|
|
530
|
+
action: ActionColorRoles;
|
|
531
|
+
/** Anything the user **enters or selects data into** — text fields, selects, checkboxes, radios. Pick when the user is about to *type / pick a value*. */
|
|
532
|
+
input: InputColorRoles;
|
|
533
|
+
/** Anything that **moves the user** between views or sections — links, tabs, breadcrumbs, pagination. Pick when the user is about to *go somewhere*. */
|
|
534
|
+
navigation: NavigationColorRoles;
|
|
535
|
+
/** Surfaces that **report the outcome** of an action or system event — toasts, alerts, banners, inline validation. Pick when the system is *reporting back*. */
|
|
536
|
+
feedback: FeedbackColorRoles;
|
|
537
|
+
/**
|
|
538
|
+
* **Presentational surfaces** — hold, group, layer, frame, or display content; never drive a transaction.
|
|
539
|
+
* Body text, page backgrounds, cards, panels, dialogs, dividers, list rows, accordions.
|
|
540
|
+
* Interactivity is not a tiebreaker: a focusable Card or expandable accordion is still `informational` —
|
|
541
|
+
* its purpose is presentational. Focusability is covered by `semantic.focus.ring.*`; disclosure by the `expanded` state.
|
|
542
|
+
*/
|
|
543
|
+
informational: InformationalColorRoles;
|
|
544
|
+
}
|
|
545
|
+
//#endregion
|
|
546
|
+
//#region src/families/elevation.d.ts
|
|
547
|
+
/**
|
|
548
|
+
* Open shadow recipe ramp — themes define as many levels as needed.
|
|
549
|
+
* Every key referenced by a semantic token must resolve to a defined entry here.
|
|
550
|
+
*/
|
|
551
|
+
type CoreElevationLevels = Record<string, RawValue>;
|
|
552
|
+
/**
|
|
553
|
+
* Core elevation primitives — shadow recipe ramps.
|
|
554
|
+
*
|
|
555
|
+
* - `level` — base recipes (standard opacity), used by default in light themes
|
|
556
|
+
* - `emphatic` — high-opacity recipes for surfaces needing stronger depth contrast
|
|
557
|
+
* (e.g., on dark or heavily-colored backgrounds)
|
|
558
|
+
*
|
|
559
|
+
* Both ramps are open `Record<string, RawValue>` — themes define as many levels as
|
|
560
|
+
* needed. Every key referenced by a semantic token must be defined here.
|
|
561
|
+
*
|
|
562
|
+
* Future expansion (non-breaking): add optional sibling ramps as needed.
|
|
563
|
+
* @see elevation.md
|
|
564
|
+
*/
|
|
565
|
+
interface CoreElevation {
|
|
566
|
+
/** Base shadow recipes — standard opacity, light-surface defaults. */
|
|
567
|
+
level: CoreElevationLevels;
|
|
568
|
+
/**
|
|
569
|
+
* High-opacity shadow recipes for surfaces needing stronger depth contrast.
|
|
570
|
+
* Mode-agnostic: expresses shadow weight, not a mode label.
|
|
571
|
+
* Themes include this ramp when a dark alternate requires higher-opacity recipes.
|
|
572
|
+
*/
|
|
573
|
+
emphatic?: CoreElevationLevels;
|
|
574
|
+
}
|
|
575
|
+
interface SemanticElevation {
|
|
576
|
+
/**
|
|
577
|
+
* Shadow-based surface strata — the primary depth contract.
|
|
578
|
+
* Maps each stratum to a shadow recipe (core elevation reference).
|
|
579
|
+
*/
|
|
580
|
+
surface: {
|
|
581
|
+
/** Surfaces flush with the page */flat: CoreElevationRef; /** Cards and panels */
|
|
582
|
+
raised: CoreElevationRef; /** Dropdowns, popovers, floating surfaces */
|
|
583
|
+
overlay: CoreElevationRef; /** Dialogs and blocking sheets */
|
|
584
|
+
blocking: CoreElevationRef;
|
|
585
|
+
};
|
|
586
|
+
/**
|
|
587
|
+
* Tonal overlay tokens — optional surface color treatments paired with shadows
|
|
588
|
+
* to preserve depth perception in dark or heavily-colored themes.
|
|
589
|
+
*
|
|
590
|
+
* Each token typically resolves to a color overlay (e.g., `color-mix`, rgba surface).
|
|
591
|
+
* Omit when the product does not use tonal elevation.
|
|
592
|
+
* When present, must cover the same strata that carry visible shadows.
|
|
593
|
+
* @see elevation.md — "Surface + Shadow"
|
|
594
|
+
*/
|
|
595
|
+
tonal?: {
|
|
596
|
+
/**
|
|
597
|
+
* Tonal surface treatment paired with `surface.raised`.
|
|
598
|
+
* Use when the raised stratum needs an additional color overlay (typical in
|
|
599
|
+
* dark themes where shadow alone is insufficient).
|
|
600
|
+
* Pair with `surface.raised`; do not use without the matching shadow contract.
|
|
601
|
+
*/
|
|
602
|
+
raised: CoreColorRef;
|
|
603
|
+
/**
|
|
604
|
+
* Tonal surface treatment paired with `surface.overlay`.
|
|
605
|
+
* Use when the overlay stratum (dropdowns, popovers) needs reinforced
|
|
606
|
+
* tonal lift over the page beneath.
|
|
607
|
+
* Pair with `surface.overlay`; resolves to a stronger overlay than `tonal.raised`.
|
|
608
|
+
*/
|
|
609
|
+
overlay: CoreColorRef;
|
|
610
|
+
/**
|
|
611
|
+
* Tonal surface treatment paired with `surface.blocking`.
|
|
612
|
+
* Use when the blocking stratum (dialogs, sheets) needs the strongest
|
|
613
|
+
* tonal separation from the page beneath the scrim.
|
|
614
|
+
* Pair with `surface.blocking` and `semantic.overlay.scrim`; resolves to
|
|
615
|
+
* the strongest tonal overlay in the contract.
|
|
616
|
+
*/
|
|
617
|
+
blocking: CoreColorRef;
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
//#endregion
|
|
621
|
+
//#region src/families/focus.d.ts
|
|
622
|
+
interface SemanticFocus {
|
|
623
|
+
ring: SemanticBorderOutline & {
|
|
624
|
+
/**
|
|
625
|
+
* System-wide focus ring colour — cross-cutting infrastructure (model.md §6).
|
|
626
|
+
*
|
|
627
|
+
* Use this when the component has no obvious FSL Entity Kind
|
|
628
|
+
* (focusable Card, profile chip, custom widget). For components with a clear
|
|
629
|
+
* `{ux}`, prefer `{ux}.{role}.border.focused` instead.
|
|
630
|
+
*
|
|
631
|
+
* Must reference a semantic token so mode overrides remap it automatically.
|
|
632
|
+
*/
|
|
633
|
+
color: TokenRef<`semantic.${string}`>;
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
//#endregion
|
|
637
|
+
//#region src/families/motion.d.ts
|
|
638
|
+
interface CoreMotionDurations {
|
|
639
|
+
none: RawValue;
|
|
640
|
+
xs: RawValue;
|
|
641
|
+
sm: RawValue;
|
|
642
|
+
md: RawValue;
|
|
643
|
+
lg: RawValue;
|
|
644
|
+
xl: RawValue;
|
|
645
|
+
}
|
|
646
|
+
interface CoreMotionEasings {
|
|
647
|
+
standard: RawValue;
|
|
648
|
+
enter: RawValue;
|
|
649
|
+
exit: RawValue;
|
|
650
|
+
linear: RawValue;
|
|
651
|
+
}
|
|
652
|
+
/** Core motion primitives — duration steps and easing curves. Components consume only semantic motion tokens. */
|
|
653
|
+
interface CoreMotion {
|
|
654
|
+
duration: CoreMotionDurations;
|
|
655
|
+
easing: CoreMotionEasings;
|
|
656
|
+
}
|
|
657
|
+
/** A duration + easing pair that fully specifies motion for one use-case. */
|
|
658
|
+
interface SemanticMotionSpec {
|
|
659
|
+
duration: CoreMotionRef;
|
|
660
|
+
easing: CoreMotionRef;
|
|
661
|
+
}
|
|
662
|
+
interface SemanticMotion {
|
|
663
|
+
/**
|
|
664
|
+
* Immediate response to a discrete user input on a single element.
|
|
665
|
+
* Use when animating hover, press, toggle, or small confirmation tweaks
|
|
666
|
+
* (color/scale/opacity changes on the element itself).
|
|
667
|
+
* Do not use for elements entering or leaving the layout — those are
|
|
668
|
+
* `transition.enter` / `transition.exit`.
|
|
669
|
+
*/
|
|
670
|
+
feedback: SemanticMotionSpec;
|
|
671
|
+
transition: {
|
|
672
|
+
/**
|
|
673
|
+
* Element appearing into rest position (overlay, surface, revealed content).
|
|
674
|
+
* Use when an element transitions *from* hidden/absent *to* visible.
|
|
675
|
+
* Pair with `transition.exit` on the inverse phase; do not use for the
|
|
676
|
+
* resting element's response to input — that is `feedback`.
|
|
677
|
+
*/
|
|
678
|
+
enter: SemanticMotionSpec;
|
|
679
|
+
/**
|
|
680
|
+
* Element leaving rest position (overlay closing, content dismissing).
|
|
681
|
+
* Use when an element transitions *from* visible *to* hidden/absent.
|
|
682
|
+
* Symmetric counterpart of `transition.enter`; the exit phase is shorter
|
|
683
|
+
* by default to keep dismissal feeling responsive.
|
|
684
|
+
*/
|
|
685
|
+
exit: SemanticMotionSpec;
|
|
686
|
+
};
|
|
687
|
+
/**
|
|
688
|
+
* Attention-drawing motion for a relevant in-place change.
|
|
689
|
+
* Use when the user must notice that something changed (status update,
|
|
690
|
+
* value reconciliation, error appearing on a field).
|
|
691
|
+
* Stronger than `feedback`; do not use for routine state changes — that is
|
|
692
|
+
* `feedback`. May collapse to minimal motion in static themes.
|
|
693
|
+
*/
|
|
694
|
+
emphasis: SemanticMotionSpec;
|
|
695
|
+
/**
|
|
696
|
+
* Ambient, non-essential motion (loops, parallax, idle flourishes).
|
|
697
|
+
* Use only when motion is never required for understanding the UI.
|
|
698
|
+
* Always disabled by default in static or reduced-motion themes; do not use
|
|
699
|
+
* for any motion the user must perceive to operate the interface.
|
|
700
|
+
*/
|
|
701
|
+
decorative: SemanticMotionSpec;
|
|
702
|
+
}
|
|
703
|
+
//#endregion
|
|
704
|
+
//#region src/families/opacity.d.ts
|
|
705
|
+
/** Intent-free opacity scale. Components must use `SemanticOpacity` — never this directly.
|
|
706
|
+
* Invariant: `0 ≤ 25 ≤ 50 ≤ 75 ≤ 100`, all in `[0, 1]`, no two adjacent steps equal. */
|
|
707
|
+
interface CoreOpacity {
|
|
708
|
+
100: NumericValue;
|
|
709
|
+
75: NumericValue;
|
|
710
|
+
50: NumericValue;
|
|
711
|
+
25: NumericValue;
|
|
712
|
+
0: NumericValue;
|
|
713
|
+
}
|
|
714
|
+
/** Stable opacity contracts for components. Each must resolve to `(0, 1)` exclusive.
|
|
715
|
+
*
|
|
716
|
+
* Opacity is a whole-element modifier — never a substitute for a semantic
|
|
717
|
+
* color, state, or hierarchy token (opacity.md §"What Opacity Should Not Do").
|
|
718
|
+
* If only one dimension (background, text, border) should become translucent,
|
|
719
|
+
* use a semantic color with alpha instead.
|
|
720
|
+
*/
|
|
721
|
+
interface SemanticOpacity {
|
|
722
|
+
/**
|
|
723
|
+
* Backdrop dimming for a blocking foreground layer.
|
|
724
|
+
* Use when rendering the layer that sits *behind* a modal, dialog, drawer, or sheet
|
|
725
|
+
* to attenuate the page underneath.
|
|
726
|
+
* Pair with `semantic.overlay.scrim` (the colored backdrop fill); do not use on the
|
|
727
|
+
* foreground surface itself — that surface stays fully opaque.
|
|
728
|
+
*/
|
|
729
|
+
scrim: CoreOpacityRef;
|
|
730
|
+
/**
|
|
731
|
+
* De-emphasis veil for content during in-flight asynchronous work.
|
|
732
|
+
* Use when content must remain visible (so the user keeps spatial context) while a
|
|
733
|
+
* fetch / mutation / long task is pending.
|
|
734
|
+
* Do not use for permanent disabled state — that is `disabled`. Remove the moment
|
|
735
|
+
* the work resolves.
|
|
736
|
+
*/
|
|
737
|
+
loading: CoreOpacityRef;
|
|
738
|
+
/**
|
|
739
|
+
* Dimming for image-like media in a disabled state (avatars, thumbnails, illustrations).
|
|
740
|
+
* Use when the disabled element has no semantic color contract that can carry the state
|
|
741
|
+
* (i.e. it is a visual asset, not a control).
|
|
742
|
+
* Do not use for disabled controls or text — those consume `{ux}.{role}.{dimension}.disabled`
|
|
743
|
+
* color tokens, which carry the contrast guarantees opacity cannot.
|
|
744
|
+
*/
|
|
745
|
+
disabled: CoreOpacityRef;
|
|
746
|
+
}
|
|
747
|
+
//#endregion
|
|
748
|
+
//#region src/families/overlay.d.ts
|
|
749
|
+
interface SemanticOverlay {
|
|
750
|
+
/** Modal backdrop color — full CSS color including alpha. */
|
|
751
|
+
scrim: RawValue;
|
|
752
|
+
}
|
|
753
|
+
//#endregion
|
|
754
|
+
//#region src/families/radii.d.ts
|
|
755
|
+
/**
|
|
756
|
+
* Core radius scale — intent-free corner curvature primitives.
|
|
757
|
+
* Ordered: none < sm < md < lg < xl << full.
|
|
758
|
+
*
|
|
759
|
+
* **Never reference core radii directly from components.**
|
|
760
|
+
* Components consume only semantic radii (`radii.control`, `radii.surface`, `radii.round`).
|
|
761
|
+
*/
|
|
762
|
+
interface CoreRadii {
|
|
763
|
+
none: RawValue;
|
|
764
|
+
sm: RawValue;
|
|
765
|
+
md: RawValue;
|
|
766
|
+
lg: RawValue;
|
|
767
|
+
xl: RawValue;
|
|
768
|
+
/**
|
|
769
|
+
* Fully-rounded intent (`9999px`).
|
|
770
|
+
* Expresses shape intent — perfect circles still depend on element dimensions.
|
|
771
|
+
*/
|
|
772
|
+
full: RawValue;
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Semantic radius contracts — stable shape API consumed by components.
|
|
776
|
+
*
|
|
777
|
+
* Pick by structural role:
|
|
778
|
+
* - `control` → interactive element (button, input, toggle, chip)
|
|
779
|
+
* - `surface` → containing surface (card, panel, dialog, menu)
|
|
780
|
+
* - `round` → explicitly fully-rounded shape intent (pill, capsule, avatar)
|
|
781
|
+
*
|
|
782
|
+
* @see radii.md — Decision Matrix and Rules of Engagement.
|
|
783
|
+
*/
|
|
784
|
+
interface SemanticRadii {
|
|
785
|
+
/** Radius for interactive controls and touchable UI elements. */
|
|
786
|
+
control: CoreRadiiRef;
|
|
787
|
+
/** Radius for surfaces that contain or group content. */
|
|
788
|
+
surface: CoreRadiiRef;
|
|
789
|
+
/** Full-round shape intent for pills, capsules, and circular affordances. */
|
|
790
|
+
round: CoreRadiiRef;
|
|
791
|
+
}
|
|
792
|
+
//#endregion
|
|
793
|
+
//#region src/families/sizing.d.ts
|
|
794
|
+
type CoreSizeRampUI = Record<1 | 2 | 3 | 4 | 5 | 6 | 7 | 8, RawValue>;
|
|
795
|
+
type CoreSizeRampLayout = Record<1 | 2 | 3 | 4 | 5 | 6, RawValue>;
|
|
796
|
+
interface CoreSizeRelative {
|
|
797
|
+
em: RawValue;
|
|
798
|
+
rem: RawValue;
|
|
799
|
+
}
|
|
800
|
+
interface CoreSizeBehavior {
|
|
801
|
+
auto: RawValue;
|
|
802
|
+
full: RawValue;
|
|
803
|
+
fit: RawValue;
|
|
804
|
+
min: RawValue;
|
|
805
|
+
max: RawValue;
|
|
806
|
+
}
|
|
807
|
+
interface CoreSizeViewport {
|
|
808
|
+
height: {
|
|
809
|
+
full: RawValue;
|
|
810
|
+
};
|
|
811
|
+
width: {
|
|
812
|
+
full: RawValue;
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
/** Three-step hit target size ramp (min / base / prominent). */
|
|
816
|
+
interface CoreSizeHitScale {
|
|
817
|
+
min: RawValue;
|
|
818
|
+
base: RawValue;
|
|
819
|
+
prominent: RawValue;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Hit target sizes split by pointer type.
|
|
823
|
+
* `toCssVars` automatically injects the `coarse` values under `@media (any-pointer: coarse)`.
|
|
824
|
+
*/
|
|
825
|
+
interface CoreSizeHit {
|
|
826
|
+
/** Fine pointer (mouse/trackpad) hit targets */
|
|
827
|
+
fine: CoreSizeHitScale;
|
|
828
|
+
/** Coarse pointer (touch) hit targets */
|
|
829
|
+
coarse: CoreSizeHitScale;
|
|
830
|
+
}
|
|
831
|
+
interface CoreSizing {
|
|
832
|
+
ramp: {
|
|
833
|
+
ui: CoreSizeRampUI;
|
|
834
|
+
layout: CoreSizeRampLayout;
|
|
835
|
+
};
|
|
836
|
+
relative: CoreSizeRelative;
|
|
837
|
+
behavior: CoreSizeBehavior;
|
|
838
|
+
viewport: CoreSizeViewport;
|
|
839
|
+
hit: CoreSizeHit;
|
|
840
|
+
}
|
|
841
|
+
interface SemanticSizing {
|
|
842
|
+
/**
|
|
843
|
+
* Ergonomic hit targets. Each token resolves to the **fine-pointer** value.
|
|
844
|
+
* The CSS output layer (`toCssVars`) automatically injects coarse-pointer
|
|
845
|
+
* overrides inside `@media (any-pointer: coarse)` — no component code needed.
|
|
846
|
+
*
|
|
847
|
+
* Fine-pointer values (`core.sizing.hit.fine.*`) may use `clamp(floor, preferred, max)`
|
|
848
|
+
* where `floor` is a fixed `Npx` ergonomic minimum — this guarantees accessibility
|
|
849
|
+
* while allowing themes to express density preferences (e.g. via the rem scale).
|
|
850
|
+
* Coarse-pointer values (`core.sizing.hit.coarse.*`) are always fixed `px`.
|
|
851
|
+
*/
|
|
852
|
+
hit: {
|
|
853
|
+
/** Minimum interactive area for small / secondary targets (icon-only buttons, toolbar items). Enforce via `min-width` / `min-height`; not a visual size. */min: CoreSizingRef; /** Default interactive area for standard buttons, inputs, and toggles. Pick when no other step applies. */
|
|
854
|
+
base: CoreSizingRef; /** Prominent interactive area for high-emphasis or low-density targets (CTAs, dialog actions). */
|
|
855
|
+
prominent: CoreSizingRef;
|
|
856
|
+
};
|
|
857
|
+
/**
|
|
858
|
+
* Visual glyph dimensions. Set on the icon element itself; never used to
|
|
859
|
+
* gate the hit target that wraps it (that is `hit.*`).
|
|
860
|
+
*/
|
|
861
|
+
icon: {
|
|
862
|
+
/** Compact glyph — dense UI, inline indicators, list-row icons. */sm: CoreSizingRef; /** Default glyph — pick this when no other step applies. */
|
|
863
|
+
md: CoreSizingRef; /** Prominent glyph — emphasis or feature icons. */
|
|
864
|
+
lg: CoreSizingRef;
|
|
865
|
+
};
|
|
866
|
+
/**
|
|
867
|
+
* Visual identity object dimensions (avatars, profile photos, brand marks,
|
|
868
|
+
* entity logos). Carries the *visual* size only — the surrounding hit target,
|
|
869
|
+
* if any, is sized via `hit.*`.
|
|
870
|
+
*/
|
|
871
|
+
identity: {
|
|
872
|
+
/** Compact identity — list rows, dense lists, mention chips. */sm: CoreSizingRef; /** Default identity — toolbar, navigation, standard avatar slots. */
|
|
873
|
+
md: CoreSizingRef; /** Prominent identity — profile cards, feature surfaces. */
|
|
874
|
+
lg: CoreSizingRef; /** Hero identity — landing surfaces, brand-leading sections. */
|
|
875
|
+
xl: CoreSizingRef;
|
|
876
|
+
};
|
|
877
|
+
measure: {
|
|
878
|
+
/**
|
|
879
|
+
* Typed as `RawValue` by design: `ch` units cannot be expressed as a core
|
|
880
|
+
* token reference. Override with a validated character-based `clamp()`
|
|
881
|
+
* expression only — never px or rem.
|
|
882
|
+
*/
|
|
883
|
+
reading: RawValue;
|
|
884
|
+
};
|
|
885
|
+
surface: {
|
|
886
|
+
/**
|
|
887
|
+
* Maximum width of a structural surface (page shell, content column,
|
|
888
|
+
* card / panel / dialog wrapper).
|
|
889
|
+
* Use as `max-width` on the *outer* surface wrapper.
|
|
890
|
+
* Pair with `gutter.page` for inline padding; do not use for line-length
|
|
891
|
+
* readability — that is `measure.reading`.
|
|
892
|
+
*/
|
|
893
|
+
maxWidth: CoreSizingRef;
|
|
894
|
+
};
|
|
895
|
+
viewport: {
|
|
896
|
+
height: {
|
|
897
|
+
/**
|
|
898
|
+
* Full-height layouts using dynamic viewport units (`100dvh`).
|
|
899
|
+
* Use intentionally — only when a region must occupy the full viewport
|
|
900
|
+
* height (app shells, full-screen modals, mobile splash regions).
|
|
901
|
+
* Do not use `100vh` directly — dynamic units handle mobile chrome correctly.
|
|
902
|
+
*/
|
|
903
|
+
full: CoreSizingRef;
|
|
904
|
+
};
|
|
905
|
+
width: {
|
|
906
|
+
/**
|
|
907
|
+
* Full-width layouts using dynamic viewport units (`100dvw`).
|
|
908
|
+
* Use intentionally — only when a region must span the full viewport
|
|
909
|
+
* width (full-bleed banners, edge-to-edge surfaces).
|
|
910
|
+
* Do not use `100vw` directly — dynamic units avoid scrollbar overflow.
|
|
911
|
+
*/
|
|
912
|
+
full: CoreSizingRef;
|
|
913
|
+
};
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
//#endregion
|
|
917
|
+
//#region src/families/spacing.d.ts
|
|
918
|
+
interface CoreSpacingEngine {
|
|
919
|
+
/** Responsive base unit — container-first clamp formula */
|
|
920
|
+
unit: RawValue;
|
|
921
|
+
/** Optional container-aware variant */
|
|
922
|
+
unitCq?: RawValue;
|
|
923
|
+
}
|
|
924
|
+
interface CoreSpacingSteps {
|
|
925
|
+
/** Responsive engine primitives — internal, not for direct component use */
|
|
926
|
+
engine: CoreSpacingEngine;
|
|
927
|
+
0: RawValue;
|
|
928
|
+
1: RawValue;
|
|
929
|
+
2: RawValue;
|
|
930
|
+
3: RawValue;
|
|
931
|
+
4: RawValue;
|
|
932
|
+
6: RawValue;
|
|
933
|
+
8: RawValue;
|
|
934
|
+
12: RawValue;
|
|
935
|
+
16: RawValue;
|
|
936
|
+
}
|
|
937
|
+
interface InsetSteps {
|
|
938
|
+
/** Compact step — tight controls / dense surfaces. */
|
|
939
|
+
sm: CoreSpacingRef;
|
|
940
|
+
/** Default step — standard controls and surfaces. Pick this when no other step applies. */
|
|
941
|
+
md: CoreSpacingRef;
|
|
942
|
+
/** Roomy step — prominent controls / spacious surfaces. */
|
|
943
|
+
lg: CoreSpacingRef;
|
|
944
|
+
}
|
|
945
|
+
interface GapStackSteps {
|
|
946
|
+
/** Tight vertical rhythm — micro-clusters within a single field. */
|
|
947
|
+
xs: CoreSpacingRef;
|
|
948
|
+
/** Medium vertical rhythm — sibling lines inside a form group. */
|
|
949
|
+
sm: CoreSpacingRef;
|
|
950
|
+
/** Default vertical rhythm — pick this when no other step applies. */
|
|
951
|
+
md: CoreSpacingRef;
|
|
952
|
+
/** Roomy vertical rhythm — separating distinct content clusters within a surface. */
|
|
953
|
+
lg: CoreSpacingRef;
|
|
954
|
+
/** Section-level rhythm — separating major sections of a page. */
|
|
955
|
+
xl: CoreSpacingRef;
|
|
956
|
+
}
|
|
957
|
+
interface GapInlineSteps {
|
|
958
|
+
/** Visual-only tight grouping (icon + label inside a single target). Never between focusable targets — use `separation.interactive.min`. */
|
|
959
|
+
xs: CoreSpacingRef;
|
|
960
|
+
/** Inline grouping — same magnitude as `gap.stack.xs`. */
|
|
961
|
+
sm: CoreSpacingRef;
|
|
962
|
+
/** Looser inline grouping — same magnitude as `gap.stack.sm`. */
|
|
963
|
+
md: CoreSpacingRef;
|
|
964
|
+
/** Spacious inline grouping — same magnitude as `gap.stack.md`. */
|
|
965
|
+
lg: CoreSpacingRef;
|
|
966
|
+
/** Wide inline grouping — same magnitude as `gap.stack.lg`. */
|
|
967
|
+
xl: CoreSpacingRef;
|
|
968
|
+
}
|
|
969
|
+
interface SemanticSpacing {
|
|
970
|
+
/**
|
|
971
|
+
* Internal padding *inside* an element (CSS `padding`).
|
|
972
|
+
* Use when the spacing lives between an element's edge and its own content;
|
|
973
|
+
* never for the distance between siblings — that is `gap.*`.
|
|
974
|
+
*/
|
|
975
|
+
inset: {
|
|
976
|
+
/**
|
|
977
|
+
* Padding inside an interactive control (button, input, chip, toggle).
|
|
978
|
+
* Use on elements with a hit target and a single inner content cluster.
|
|
979
|
+
* Pair with `inset.surface` on the containing surface; do not use for
|
|
980
|
+
* containing surfaces — those are `inset.surface`.
|
|
981
|
+
*/
|
|
982
|
+
control: InsetSteps;
|
|
983
|
+
/**
|
|
984
|
+
* Padding inside a containing surface (card, panel, dialog, menu, section).
|
|
985
|
+
* Use on elements that *contain* other content blocks and need a margin
|
|
986
|
+
* between their edge and the inner cluster.
|
|
987
|
+
* Must be ≥ `inset.control` at the same step (validation rule); do not use
|
|
988
|
+
* for the inner controls themselves — those are `inset.control`.
|
|
989
|
+
*/
|
|
990
|
+
surface: InsetSteps;
|
|
991
|
+
};
|
|
992
|
+
/**
|
|
993
|
+
* Distance *between* siblings (CSS `gap` on Flex/Grid containers).
|
|
994
|
+
* Use when laying out a sequence of sibling elements; never for internal
|
|
995
|
+
* padding (that is `inset.*`) and never for page/section structural padding
|
|
996
|
+
* (that is `gutter.*`).
|
|
997
|
+
*/
|
|
998
|
+
gap: {
|
|
999
|
+
/**
|
|
1000
|
+
* Vertical rhythm between stacked siblings (column layouts, lists, form fields).
|
|
1001
|
+
* Use when items flow along the block axis and rhythm carries hierarchy.
|
|
1002
|
+
* Pair with `gap.inline` for horizontal groupings; do not use for items
|
|
1003
|
+
* arranged along the inline axis — those are `gap.inline`.
|
|
1004
|
+
*/
|
|
1005
|
+
stack: GapStackSteps;
|
|
1006
|
+
/**
|
|
1007
|
+
* Horizontal grouping between inline siblings (icon + label, toolbar items, chip rows).
|
|
1008
|
+
* Use when items flow along the inline axis as a visual group.
|
|
1009
|
+
* `gap.inline.xs` is *visual-only* — never use it between independently
|
|
1010
|
+
* focusable interactive targets (use `separation.interactive.min` instead).
|
|
1011
|
+
*/
|
|
1012
|
+
inline: GapInlineSteps;
|
|
1013
|
+
};
|
|
1014
|
+
/**
|
|
1015
|
+
* Structural outer padding for page-level and section-level layout regions.
|
|
1016
|
+
* `page` and `section` may use a `clamp()` expression with embedded `{token.path}` refs
|
|
1017
|
+
* (e.g. `clamp({core.space.4}, {core.space.6}, {core.space.12})`).
|
|
1018
|
+
* Typed as `RawValue` to allow both simple refs and responsive clamp expressions.
|
|
1019
|
+
*/
|
|
1020
|
+
gutter: {
|
|
1021
|
+
/**
|
|
1022
|
+
* Outer padding bounding the page's content column.
|
|
1023
|
+
* Use as inline padding on the top-level page container.
|
|
1024
|
+
* Bounded `clamp()` contract by spec; do not use for inner sections — that
|
|
1025
|
+
* is `gutter.section`.
|
|
1026
|
+
*/
|
|
1027
|
+
page: RawValue;
|
|
1028
|
+
/**
|
|
1029
|
+
* Outer padding separating a section's content from its parent's gutter.
|
|
1030
|
+
* Use on inner section wrappers nested inside a `gutter.page` container.
|
|
1031
|
+
* Bounded `clamp()` contract by spec; resolves tighter than `gutter.page`.
|
|
1032
|
+
*/
|
|
1033
|
+
section: RawValue;
|
|
1034
|
+
};
|
|
1035
|
+
/**
|
|
1036
|
+
* Ergonomic separation between independently actionable targets in dense clusters.
|
|
1037
|
+
* May use a `clamp()` expression with an embedded `{token.path}` ref
|
|
1038
|
+
* (e.g. `clamp(8px, {core.space.2}, 12px)`).
|
|
1039
|
+
*/
|
|
1040
|
+
separation: {
|
|
1041
|
+
interactive: {
|
|
1042
|
+
/**
|
|
1043
|
+
* Minimum gap between adjacent interactive targets (toolbar buttons,
|
|
1044
|
+
* paginator arrows, segmented controls, dense menu items).
|
|
1045
|
+
* Use only between elements the user can click/tap/focus independently.
|
|
1046
|
+
* Do not use for visual-only groupings — that is `gap.inline.xs`.
|
|
1047
|
+
*/
|
|
1048
|
+
min: RawValue;
|
|
1049
|
+
};
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
//#endregion
|
|
1053
|
+
//#region src/families/typography.d.ts
|
|
1054
|
+
interface CoreFontFamilies {
|
|
1055
|
+
sans: RawValue;
|
|
1056
|
+
mono: RawValue;
|
|
1057
|
+
serif?: RawValue;
|
|
1058
|
+
}
|
|
1059
|
+
interface CoreFontWeights {
|
|
1060
|
+
regular: NumericValue;
|
|
1061
|
+
medium: NumericValue;
|
|
1062
|
+
semibold: NumericValue;
|
|
1063
|
+
bold: NumericValue;
|
|
1064
|
+
}
|
|
1065
|
+
interface CoreFontLeading {
|
|
1066
|
+
tight: NumericValue;
|
|
1067
|
+
snug: NumericValue;
|
|
1068
|
+
normal: NumericValue;
|
|
1069
|
+
relaxed: NumericValue;
|
|
1070
|
+
}
|
|
1071
|
+
interface CoreFontTracking {
|
|
1072
|
+
tight: RawValue;
|
|
1073
|
+
normal: RawValue;
|
|
1074
|
+
wide: RawValue;
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Core font optical sizing primitives — exhaustive enumeration of the CSS
|
|
1078
|
+
* `font-optical-sizing` property values. Closed set by spec, not by choice.
|
|
1079
|
+
*
|
|
1080
|
+
* Mapping (token → CSS keyword):
|
|
1081
|
+
* - `auto` → `auto` (let the UA opt into optical sizing for variable fonts)
|
|
1082
|
+
* - `none` → `none` (disable optical adjustments)
|
|
1083
|
+
*
|
|
1084
|
+
* The wrapper exists to satisfy the `CoreFontRef` invariant of `TextStyle`
|
|
1085
|
+
* (semantic styles reference core tokens only) and to register entries in the
|
|
1086
|
+
* CSS variable pipeline — not to enable per-theme variation, which the CSS
|
|
1087
|
+
* spec does not permit.
|
|
1088
|
+
*/
|
|
1089
|
+
interface CoreFontOptical {
|
|
1090
|
+
auto: RawValue;
|
|
1091
|
+
none: RawValue;
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Core font numeric variant primitives — figure shape, alignment, and special glyph
|
|
1095
|
+
* features exposed by the CSS `font-variant-numeric` property.
|
|
1096
|
+
*
|
|
1097
|
+
* The set covers the standalone keyword values of the CSS spec; combinations
|
|
1098
|
+
* (e.g. `tabular-nums slashed-zero`) are composed at the consumer site by
|
|
1099
|
+
* concatenating these values, not encoded as additional tokens.
|
|
1100
|
+
*
|
|
1101
|
+
* Mapping (token → CSS keyword):
|
|
1102
|
+
* - `proportional` → `proportional-nums` (default figure widths)
|
|
1103
|
+
* - `tabular` → `tabular-nums` (uniform-width figures; dashboards, tables)
|
|
1104
|
+
* - `lining` → `lining-nums` (cap-height figures)
|
|
1105
|
+
* - `oldstyle` → `oldstyle-nums` (text-figure variants for body copy)
|
|
1106
|
+
* - `slashedZero` → `slashed-zero` (zero disambiguation; financial/code contexts)
|
|
1107
|
+
* - `ordinal` → `ordinal` (1st, 2nd, 3rd ordinal markers)
|
|
1108
|
+
* - `normal` → `normal` (reset to UA defaults)
|
|
1109
|
+
*
|
|
1110
|
+
* The wrapper exists to satisfy the `CoreFontRef` invariant of `TextStyle`
|
|
1111
|
+
* (semantic styles reference core tokens only) and to register entries in the
|
|
1112
|
+
* CSS variable pipeline — not to enable per-theme variation of the keyword
|
|
1113
|
+
* values themselves, which are fixed by the CSS spec.
|
|
1114
|
+
*/
|
|
1115
|
+
interface CoreFontNumeric {
|
|
1116
|
+
proportional: RawValue;
|
|
1117
|
+
tabular: RawValue;
|
|
1118
|
+
lining: RawValue;
|
|
1119
|
+
oldstyle: RawValue;
|
|
1120
|
+
slashedZero: RawValue;
|
|
1121
|
+
ordinal: RawValue;
|
|
1122
|
+
normal: RawValue;
|
|
1123
|
+
}
|
|
1124
|
+
type RampScale6 = Record<1 | 2 | 3 | 4 | 5 | 6, RawValue>;
|
|
1125
|
+
/**
|
|
1126
|
+
* Responsive font size scale — text and display size ramps.
|
|
1127
|
+
* Both ramps use `clamp()` expressions with container query units (cqi) as the
|
|
1128
|
+
* preferred fluid step, with viewport-safe fallbacks emitted by `toCssVars`.
|
|
1129
|
+
*/
|
|
1130
|
+
interface CoreFontScale {
|
|
1131
|
+
/** Body text, labels, and dense UI typography */
|
|
1132
|
+
text: RampScale6;
|
|
1133
|
+
/** Headings, titles, and high-hierarchy display text */
|
|
1134
|
+
display: RampScale6;
|
|
1135
|
+
}
|
|
1136
|
+
/** Core font primitive set — family, weight, leading (line height), tracking (letter spacing), optical sizing, numeric variant references, and the responsive size scale. */
|
|
1137
|
+
interface CoreFont {
|
|
1138
|
+
family: CoreFontFamilies;
|
|
1139
|
+
weight: CoreFontWeights;
|
|
1140
|
+
leading: CoreFontLeading;
|
|
1141
|
+
tracking: CoreFontTracking;
|
|
1142
|
+
optical: CoreFontOptical;
|
|
1143
|
+
numeric: CoreFontNumeric;
|
|
1144
|
+
/** Responsive font size scale. @see CoreFontScale */
|
|
1145
|
+
scale: CoreFontScale;
|
|
1146
|
+
}
|
|
1147
|
+
/** Composite text style — groups 5–7 font token references that define a single typographic role. References core tokens only. */
|
|
1148
|
+
interface TextStyle {
|
|
1149
|
+
fontFamily: CoreFontRef;
|
|
1150
|
+
fontSize: CoreFontScaleRef;
|
|
1151
|
+
fontWeight: CoreFontRef;
|
|
1152
|
+
lineHeight: CoreFontRef;
|
|
1153
|
+
letterSpacing: CoreFontRef;
|
|
1154
|
+
fontOpticalSizing?: CoreFontRef;
|
|
1155
|
+
fontVariantNumeric?: CoreFontRef;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Three-step size scale within a single text family.
|
|
1159
|
+
* Step is the *relative* hierarchy inside the family — never an absolute size.
|
|
1160
|
+
* Same step across families is not interchangeable: `display.md` and `body.md`
|
|
1161
|
+
* share only the step name, not the role.
|
|
1162
|
+
*/
|
|
1163
|
+
interface TextStyleLgMdSm {
|
|
1164
|
+
/** Largest step of this family — strongest hierarchy *within* the family. Use for the most prominent instance of this role on the surface. */
|
|
1165
|
+
lg: TextStyle;
|
|
1166
|
+
/** Default step of this family — the unmarked choice. Use unless the surface explicitly calls for `lg` or `sm`. */
|
|
1167
|
+
md: TextStyle;
|
|
1168
|
+
/** Smallest step of this family — compact / dense usage. Use when space is constrained or when the text is secondary within the role. */
|
|
1169
|
+
sm: TextStyle;
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Two-step size scale (no `lg`) for families where a hero step is not meaningful.
|
|
1173
|
+
* @see TextStyleLgMdSm — for the rationale of step semantics.
|
|
1174
|
+
*/
|
|
1175
|
+
interface TextStyleMdSm {
|
|
1176
|
+
/** Default step of this family — the unmarked choice. */
|
|
1177
|
+
md: TextStyle;
|
|
1178
|
+
/** Smallest step of this family — compact / dense usage. */
|
|
1179
|
+
sm: TextStyle;
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Semantic text styles — the only typography API consumed by components.
|
|
1183
|
+
*
|
|
1184
|
+
* Family is the typographic *role* (where in the interface this text sits);
|
|
1185
|
+
* step (`lg`/`md`/`sm`) is the relative size *within* the role. The pair
|
|
1186
|
+
* `family × step` selects one composite style; never mix `display.sm` with
|
|
1187
|
+
* `headline.lg` to "shrink a display" — pick the family whose role matches.
|
|
1188
|
+
*
|
|
1189
|
+
* HTML semantics (`h1…h6`, `p`, `label`) and visual style are decoupled —
|
|
1190
|
+
* `as="h2"` carries document structure; `text.title.md` carries appearance.
|
|
1191
|
+
*
|
|
1192
|
+
* @see typography.md — Text Families table.
|
|
1193
|
+
*/
|
|
1194
|
+
interface SemanticText {
|
|
1195
|
+
/**
|
|
1196
|
+
* High-impact hero text — landing surfaces and prominent page headers.
|
|
1197
|
+
* Use sparingly; reserved for the single most important text on a page.
|
|
1198
|
+
* Pair with `headline` for the next hierarchy step; do not use for section
|
|
1199
|
+
* headings inside content — those are `headline`.
|
|
1200
|
+
*/
|
|
1201
|
+
display: TextStyleLgMdSm;
|
|
1202
|
+
/**
|
|
1203
|
+
* Section or page headings that structure scanning of the document.
|
|
1204
|
+
* Use for the primary headings inside content (page title, major section breaks).
|
|
1205
|
+
* Below `display` in hierarchy, above `title`. Do not use for surface chrome
|
|
1206
|
+
* (card / panel / dialog headers) — those are `title`.
|
|
1207
|
+
*/
|
|
1208
|
+
headline: TextStyleLgMdSm;
|
|
1209
|
+
/**
|
|
1210
|
+
* Titles for *surfaces* — cards, panels, dialogs, sheets, menus, structured sections.
|
|
1211
|
+
* Use as the heading of a contained surface, not the heading of a content section.
|
|
1212
|
+
* Pair with `body` / `label` inside the same surface; do not use for top-level
|
|
1213
|
+
* page or document headings — those are `headline` / `display`.
|
|
1214
|
+
*/
|
|
1215
|
+
title: TextStyleLgMdSm;
|
|
1216
|
+
/**
|
|
1217
|
+
* Default reading text — paragraphs, descriptions, long-form content.
|
|
1218
|
+
* Use for any text the user will *read* rather than *scan* or *select*.
|
|
1219
|
+
* Optimized for readability; do not use for short UI strings or labels —
|
|
1220
|
+
* those are `label`.
|
|
1221
|
+
*/
|
|
1222
|
+
body: TextStyleLgMdSm;
|
|
1223
|
+
/**
|
|
1224
|
+
* Short UI strings — field labels, button text, badges, metadata, captions.
|
|
1225
|
+
* Use for compact, scan-only text that names or describes adjacent UI.
|
|
1226
|
+
* Do not use for prose the user must read in sequence — that is `body`.
|
|
1227
|
+
*/
|
|
1228
|
+
label: TextStyleLgMdSm;
|
|
1229
|
+
/**
|
|
1230
|
+
* Monospaced text for code snippets, logs, identifiers, or technical data.
|
|
1231
|
+
* Use whenever the text must align by character cell or distinguish similar
|
|
1232
|
+
* glyphs (`Il1O0`).
|
|
1233
|
+
* Do not use for UI strings that merely *look* technical — that is `body` or `label`.
|
|
1234
|
+
*/
|
|
1235
|
+
code: TextStyleMdSm;
|
|
1236
|
+
}
|
|
1237
|
+
//#endregion
|
|
1238
|
+
//#region src/families/z-index.d.ts
|
|
1239
|
+
/**
|
|
1240
|
+
* Intent-free z-index level scale. Components must use `SemanticZIndex` — never this directly.
|
|
1241
|
+
* Ordering invariant (strictly ascending): `level.0 < level.1 < level.2 < level.3 < level.4`.
|
|
1242
|
+
* `level.0` must be ≥ 0. Adjacent levels must differ by ≥ 10.
|
|
1243
|
+
*/
|
|
1244
|
+
type CoreZIndexLevels = Record<0 | 1 | 2 | 3 | 4, NumericValue>;
|
|
1245
|
+
interface CoreZIndex {
|
|
1246
|
+
level: CoreZIndexLevels;
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Stable application strata consumed by components. Top-layer browser elements
|
|
1250
|
+
* (modal dialogs / popovers promoted by the platform) are out of scope.
|
|
1251
|
+
*
|
|
1252
|
+
* Tokens express *cross-component layer relationships* only — never local
|
|
1253
|
+
* layering inside a single component, never visual depth (that is `elevation`).
|
|
1254
|
+
* Stratum picked must match the element's *blocking behaviour* and *persistence*,
|
|
1255
|
+
* not its component name (no `z.dropdown`, `z.toast`, etc.).
|
|
1256
|
+
*/
|
|
1257
|
+
interface SemanticZIndex {
|
|
1258
|
+
layer: {
|
|
1259
|
+
/**
|
|
1260
|
+
* Page content in normal document flow.
|
|
1261
|
+
* Use when the element participates in the default application stratum and
|
|
1262
|
+
* has no claim above sibling content.
|
|
1263
|
+
* Do not use to "reset" stacking inside a component — local layering is
|
|
1264
|
+
* the component's own concern.
|
|
1265
|
+
*/
|
|
1266
|
+
base: CoreZIndexRef;
|
|
1267
|
+
/**
|
|
1268
|
+
* Anchored bars that follow scroll while staying inside the app stack.
|
|
1269
|
+
* Use when building sticky headers, sticky navigation, or persistent
|
|
1270
|
+
* anchored toolbars.
|
|
1271
|
+
* Pair with `position: sticky`; do not use for non-anchored floating
|
|
1272
|
+
* surfaces — those are `overlay`.
|
|
1273
|
+
*/
|
|
1274
|
+
sticky: CoreZIndexRef;
|
|
1275
|
+
/**
|
|
1276
|
+
* Non-blocking floating surfaces above sticky and base content.
|
|
1277
|
+
* Use when building dropdowns, menus, popovers, or floating panels that
|
|
1278
|
+
* the user can dismiss by interacting elsewhere.
|
|
1279
|
+
* Do not use for surfaces that block the page behind them — those are
|
|
1280
|
+
* `blocking`.
|
|
1281
|
+
*/
|
|
1282
|
+
overlay: CoreZIndexRef;
|
|
1283
|
+
/**
|
|
1284
|
+
* Surfaces that sit above other overlays and prevent interaction behind them.
|
|
1285
|
+
* Use when building dialogs, sheets, or blocking drawers paired with a scrim.
|
|
1286
|
+
* Pair with `semantic.overlay.scrim` and `semantic.opacity.scrim`; do not
|
|
1287
|
+
* use for non-blocking floating panels — those are `overlay`.
|
|
1288
|
+
*/
|
|
1289
|
+
blocking: CoreZIndexRef;
|
|
1290
|
+
/**
|
|
1291
|
+
* Highest application-controlled stratum before the browser top layer.
|
|
1292
|
+
* Use when building transient notifications that must surface above any
|
|
1293
|
+
* other app stratum (toasts, tooltip-like transient overlays).
|
|
1294
|
+
* Do not use for persistent UI — `transient` implies the element is
|
|
1295
|
+
* short-lived and self-dismissing.
|
|
1296
|
+
*/
|
|
1297
|
+
transient: CoreZIndexRef;
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
//#endregion
|
|
1301
|
+
//#region src/Types.d.ts
|
|
1302
|
+
/**
|
|
1303
|
+
* Full ttoss Design Tokens Theme contract.
|
|
1304
|
+
*
|
|
1305
|
+
* Two layers:
|
|
1306
|
+
* - `core` — raw primitives and responsive engines (immutable across modes)
|
|
1307
|
+
* - `semantic` — stable aliases consumed by components (remapped per mode)
|
|
1308
|
+
*
|
|
1309
|
+
* Extensions are optional properties inside `core` and `semantic`.
|
|
1310
|
+
* When present they follow the same `core → semantic` contract.
|
|
1311
|
+
*/
|
|
1312
|
+
interface ThemeTokens {
|
|
1313
|
+
core: {
|
|
1314
|
+
colors: CoreColors;
|
|
1315
|
+
elevation: CoreElevation;
|
|
1316
|
+
font: CoreFont;
|
|
1317
|
+
spacing: CoreSpacingSteps;
|
|
1318
|
+
sizing: CoreSizing;
|
|
1319
|
+
radii: CoreRadii;
|
|
1320
|
+
border: CoreBorder;
|
|
1321
|
+
opacity: CoreOpacity;
|
|
1322
|
+
motion: CoreMotion;
|
|
1323
|
+
zIndex: CoreZIndex; /** Viewport threshold scale. Core-only — no semantic layer. @see CoreBreakpoints */
|
|
1324
|
+
breakpoints: CoreBreakpoints;
|
|
1325
|
+
/**
|
|
1326
|
+
* Data Visualization extension — analytical color palettes and non-color
|
|
1327
|
+
* encoding primitives. Optional: omit when the theme does not support dataviz.
|
|
1328
|
+
*/
|
|
1329
|
+
dataviz?: CoreDataviz;
|
|
1330
|
+
};
|
|
1331
|
+
semantic: {
|
|
1332
|
+
colors: SemanticColors;
|
|
1333
|
+
elevation: SemanticElevation;
|
|
1334
|
+
text: SemanticText;
|
|
1335
|
+
spacing: SemanticSpacing;
|
|
1336
|
+
sizing: SemanticSizing;
|
|
1337
|
+
radii: SemanticRadii;
|
|
1338
|
+
border: SemanticBorder;
|
|
1339
|
+
focus: SemanticFocus;
|
|
1340
|
+
overlay: SemanticOverlay;
|
|
1341
|
+
opacity: SemanticOpacity;
|
|
1342
|
+
motion: SemanticMotion;
|
|
1343
|
+
zIndex: SemanticZIndex;
|
|
1344
|
+
/**
|
|
1345
|
+
* Data Visualization extension — semantic roles for analytical color,
|
|
1346
|
+
* non-color encodings, and geospatial overlays.
|
|
1347
|
+
* Optional: omit when the theme does not support dataviz.
|
|
1348
|
+
*
|
|
1349
|
+
* This is the **public API** of the dataviz extension.
|
|
1350
|
+
* Components consume these tokens; never `core.dataviz.*` directly.
|
|
1351
|
+
*/
|
|
1352
|
+
dataviz?: SemanticDataviz;
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* Semantic-only overrides for the alternate color mode.
|
|
1357
|
+
*
|
|
1358
|
+
* Core tokens are immutable across modes. Only semantic token references
|
|
1359
|
+
* may change — remapping to different core tokens for the alternate mode.
|
|
1360
|
+
*
|
|
1361
|
+
* Uses `DeepPartial`: every nested key is optional. Omitting a key inherits
|
|
1362
|
+
* the value from the base theme (see `deepMerge` in `roots/helpers.ts`,
|
|
1363
|
+
* which treats `undefined` and absent keys identically). An alternate
|
|
1364
|
+
* supplies only the leaves that differ from the base.
|
|
1365
|
+
*
|
|
1366
|
+
* @see {@link modes.md} — "Modes remap semantic references, not core values."
|
|
1367
|
+
*/
|
|
1368
|
+
interface ModeOverride {
|
|
1369
|
+
semantic: DeepPartial<ThemeTokens['semantic']>;
|
|
1370
|
+
}
|
|
1371
|
+
/**
|
|
1372
|
+
* A theme bundle packages a complete `ThemeTokens` (the base)
|
|
1373
|
+
* with an optional semantic-only override for the alternate color mode.
|
|
1374
|
+
*
|
|
1375
|
+
* - `baseMode` declares which mode the `base` theme represents.
|
|
1376
|
+
* - `alternate` remaps only semantic token references that differ in the
|
|
1377
|
+
* opposite mode. Core token values stay immutable.
|
|
1378
|
+
*
|
|
1379
|
+
* **Why only two modes?** `prefers-color-scheme` is binary (`light` / `dark`);
|
|
1380
|
+
* that is the only axis `ThemeBundle` addresses. High-contrast, reduced-motion,
|
|
1381
|
+
* and coarse-pointer are orthogonal CSS `@media` axes — they are handled by
|
|
1382
|
+
* the dedicated blocks emitted by `toCssVars` and are not additional modes.
|
|
1383
|
+
* Proposals to generalize to `Record<ModeName, ModeOverride>` conflate these
|
|
1384
|
+
* independent axes and should be rejected.
|
|
1385
|
+
*
|
|
1386
|
+
* When no `alternate` is provided, the theme is single-mode.
|
|
1387
|
+
*
|
|
1388
|
+
* @example
|
|
1389
|
+
* ```ts
|
|
1390
|
+
* const bundle: ThemeBundle = {
|
|
1391
|
+
* baseMode: 'light',
|
|
1392
|
+
* base: baseTheme,
|
|
1393
|
+
* alternate: {
|
|
1394
|
+
* semantic: {
|
|
1395
|
+
* colors: {
|
|
1396
|
+
* informational: { primary: { background: { default: '{core.colors.neutral.900}' } } },
|
|
1397
|
+
* },
|
|
1398
|
+
* },
|
|
1399
|
+
* },
|
|
1400
|
+
* };
|
|
1401
|
+
* ```
|
|
1402
|
+
*/
|
|
1403
|
+
interface ThemeBundle {
|
|
1404
|
+
/**
|
|
1405
|
+
* Which color mode the `base` theme represents.
|
|
1406
|
+
* Constrained to `'light' | 'dark'` because `prefers-color-scheme` is binary.
|
|
1407
|
+
*/
|
|
1408
|
+
baseMode: 'light' | 'dark';
|
|
1409
|
+
/** Complete theme for the base mode. */
|
|
1410
|
+
base: ThemeTokens;
|
|
1411
|
+
/**
|
|
1412
|
+
* Semantic remapping overrides for the opposite mode.
|
|
1413
|
+
* Only semantic references that differ need to be listed — core tokens are shared.
|
|
1414
|
+
*/
|
|
1415
|
+
alternate?: ModeOverride;
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* The semantic token layer of a theme. This is the **only** part of the token
|
|
1419
|
+
* system that components should consume — never `core.*` tokens directly.
|
|
1420
|
+
*
|
|
1421
|
+
* Obtain via `useTokens()` inside a `<ThemeProvider theme={...}>`.
|
|
1422
|
+
*
|
|
1423
|
+
* @see {@link useTokens}
|
|
1424
|
+
*/
|
|
1425
|
+
type SemanticTokens = ThemeTokens['semantic'];
|
|
1426
|
+
//#endregion
|
|
1427
|
+
export { DeepPartial as a, ThemeTokens as i, SemanticTokens as n, CoreDataviz as o, ThemeBundle as r, SemanticDataviz as s, ModeOverride as t };
|