@skdx/tokens 0.26.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/README.md +439 -0
- package/dist/foundation.css +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -0
- package/dist/themes/AntBrand.cjs +1 -0
- package/dist/themes/AntBrand.d.cts +3 -0
- package/dist/themes/AntBrand.d.ts +3 -0
- package/dist/themes/AntBrand.js +1 -0
- package/dist/themes/AntDark.cjs +1 -0
- package/dist/themes/AntDark.d.cts +12 -0
- package/dist/themes/AntDark.d.ts +12 -0
- package/dist/themes/AntDark.js +1 -0
- package/dist/themes/CatppuccinLatte.cjs +1 -0
- package/dist/themes/CatppuccinLatte.d.cts +9 -0
- package/dist/themes/CatppuccinLatte.d.ts +9 -0
- package/dist/themes/CatppuccinLatte.js +1 -0
- package/dist/themes/CatppuccinMocha.cjs +1 -0
- package/dist/themes/CatppuccinMocha.d.cts +9 -0
- package/dist/themes/CatppuccinMocha.d.ts +9 -0
- package/dist/themes/CatppuccinMocha.js +1 -0
- package/dist/themes/ChakraBrand.cjs +1 -0
- package/dist/themes/ChakraBrand.d.cts +3 -0
- package/dist/themes/ChakraBrand.d.ts +3 -0
- package/dist/themes/ChakraBrand.js +1 -0
- package/dist/themes/ChakraDark.cjs +1 -0
- package/dist/themes/ChakraDark.d.cts +12 -0
- package/dist/themes/ChakraDark.d.ts +12 -0
- package/dist/themes/ChakraDark.js +1 -0
- package/dist/themes/CupcakeDark.cjs +1 -0
- package/dist/themes/CupcakeDark.d.cts +9 -0
- package/dist/themes/CupcakeDark.d.ts +9 -0
- package/dist/themes/CupcakeDark.js +1 -0
- package/dist/themes/CupcakeLight.cjs +1 -0
- package/dist/themes/CupcakeLight.d.cts +10 -0
- package/dist/themes/CupcakeLight.d.ts +10 -0
- package/dist/themes/CupcakeLight.js +1 -0
- package/dist/themes/DefaultTheme.cjs +1 -0
- package/dist/themes/DefaultTheme.d.cts +37 -0
- package/dist/themes/DefaultTheme.d.ts +37 -0
- package/dist/themes/DefaultTheme.js +1 -0
- package/dist/themes/DraculaDark.cjs +1 -0
- package/dist/themes/DraculaDark.d.cts +3 -0
- package/dist/themes/DraculaDark.d.ts +3 -0
- package/dist/themes/DraculaDark.js +1 -0
- package/dist/themes/DraculaLight.cjs +1 -0
- package/dist/themes/DraculaLight.d.cts +14 -0
- package/dist/themes/DraculaLight.d.ts +14 -0
- package/dist/themes/DraculaLight.js +1 -0
- package/dist/themes/EmeraldBrand.cjs +1 -0
- package/dist/themes/EmeraldBrand.d.cts +3 -0
- package/dist/themes/EmeraldBrand.d.ts +3 -0
- package/dist/themes/EmeraldBrand.js +1 -0
- package/dist/themes/EmeraldDark.cjs +1 -0
- package/dist/themes/EmeraldDark.d.cts +8 -0
- package/dist/themes/EmeraldDark.d.ts +8 -0
- package/dist/themes/EmeraldDark.js +1 -0
- package/dist/themes/EverforestDark.cjs +1 -0
- package/dist/themes/EverforestDark.d.cts +9 -0
- package/dist/themes/EverforestDark.d.ts +9 -0
- package/dist/themes/EverforestDark.js +1 -0
- package/dist/themes/EverforestLight.cjs +1 -0
- package/dist/themes/EverforestLight.d.cts +13 -0
- package/dist/themes/EverforestLight.d.ts +13 -0
- package/dist/themes/EverforestLight.js +1 -0
- package/dist/themes/FluentBrand.cjs +1 -0
- package/dist/themes/FluentBrand.d.cts +3 -0
- package/dist/themes/FluentBrand.d.ts +3 -0
- package/dist/themes/FluentBrand.js +1 -0
- package/dist/themes/FluentDark.cjs +1 -0
- package/dist/themes/FluentDark.d.cts +11 -0
- package/dist/themes/FluentDark.d.ts +11 -0
- package/dist/themes/FluentDark.js +1 -0
- package/dist/themes/GraphiteBrand.cjs +1 -0
- package/dist/themes/GraphiteBrand.d.cts +3 -0
- package/dist/themes/GraphiteBrand.d.ts +3 -0
- package/dist/themes/GraphiteBrand.js +1 -0
- package/dist/themes/GraphiteDark.cjs +1 -0
- package/dist/themes/GraphiteDark.d.cts +8 -0
- package/dist/themes/GraphiteDark.d.ts +8 -0
- package/dist/themes/GraphiteDark.js +1 -0
- package/dist/themes/GruvboxDark.cjs +1 -0
- package/dist/themes/GruvboxDark.d.cts +9 -0
- package/dist/themes/GruvboxDark.d.ts +9 -0
- package/dist/themes/GruvboxDark.js +1 -0
- package/dist/themes/GruvboxLight.cjs +1 -0
- package/dist/themes/GruvboxLight.d.cts +13 -0
- package/dist/themes/GruvboxLight.d.ts +13 -0
- package/dist/themes/GruvboxLight.js +1 -0
- package/dist/themes/MaterialBrand.cjs +1 -0
- package/dist/themes/MaterialBrand.d.cts +3 -0
- package/dist/themes/MaterialBrand.d.ts +3 -0
- package/dist/themes/MaterialBrand.js +1 -0
- package/dist/themes/MaterialDark.cjs +1 -0
- package/dist/themes/MaterialDark.d.cts +12 -0
- package/dist/themes/MaterialDark.d.ts +12 -0
- package/dist/themes/MaterialDark.js +1 -0
- package/dist/themes/MidnightBrand.cjs +1 -0
- package/dist/themes/MidnightBrand.d.cts +11 -0
- package/dist/themes/MidnightBrand.d.ts +11 -0
- package/dist/themes/MidnightBrand.js +1 -0
- package/dist/themes/MidnightLight.cjs +1 -0
- package/dist/themes/MidnightLight.d.cts +10 -0
- package/dist/themes/MidnightLight.d.ts +10 -0
- package/dist/themes/MidnightLight.js +1 -0
- package/dist/themes/NordDark.cjs +1 -0
- package/dist/themes/NordDark.d.cts +3 -0
- package/dist/themes/NordDark.d.ts +3 -0
- package/dist/themes/NordDark.js +1 -0
- package/dist/themes/NordLight.cjs +1 -0
- package/dist/themes/NordLight.d.cts +13 -0
- package/dist/themes/NordLight.d.ts +13 -0
- package/dist/themes/NordLight.js +1 -0
- package/dist/themes/OneDark.cjs +1 -0
- package/dist/themes/OneDark.d.cts +9 -0
- package/dist/themes/OneDark.d.ts +9 -0
- package/dist/themes/OneDark.js +1 -0
- package/dist/themes/OneLight.cjs +1 -0
- package/dist/themes/OneLight.d.cts +13 -0
- package/dist/themes/OneLight.d.ts +13 -0
- package/dist/themes/OneLight.js +1 -0
- package/dist/themes/PrimerDark.cjs +1 -0
- package/dist/themes/PrimerDark.d.cts +9 -0
- package/dist/themes/PrimerDark.d.ts +9 -0
- package/dist/themes/PrimerDark.js +1 -0
- package/dist/themes/PrimerLight.cjs +1 -0
- package/dist/themes/PrimerLight.d.cts +9 -0
- package/dist/themes/PrimerLight.d.ts +9 -0
- package/dist/themes/PrimerLight.js +1 -0
- package/dist/themes/RosePine.cjs +1 -0
- package/dist/themes/RosePine.d.cts +9 -0
- package/dist/themes/RosePine.d.ts +9 -0
- package/dist/themes/RosePine.js +1 -0
- package/dist/themes/RosePineDawn.cjs +1 -0
- package/dist/themes/RosePineDawn.d.cts +13 -0
- package/dist/themes/RosePineDawn.d.ts +13 -0
- package/dist/themes/RosePineDawn.js +1 -0
- package/dist/themes/SkandaDark.cjs +1 -0
- package/dist/themes/SkandaDark.d.cts +12 -0
- package/dist/themes/SkandaDark.d.ts +12 -0
- package/dist/themes/SkandaDark.js +1 -0
- package/dist/themes/SkandaLight.cjs +1 -0
- package/dist/themes/SkandaLight.d.cts +3 -0
- package/dist/themes/SkandaLight.d.ts +3 -0
- package/dist/themes/SkandaLight.js +1 -0
- package/dist/themes/SolarizedDark.cjs +1 -0
- package/dist/themes/SolarizedDark.d.cts +9 -0
- package/dist/themes/SolarizedDark.d.ts +9 -0
- package/dist/themes/SolarizedDark.js +1 -0
- package/dist/themes/SolarizedLight.cjs +1 -0
- package/dist/themes/SolarizedLight.d.cts +9 -0
- package/dist/themes/SolarizedLight.d.ts +9 -0
- package/dist/themes/SolarizedLight.js +1 -0
- package/dist/themes/SynthwaveDark.cjs +1 -0
- package/dist/themes/SynthwaveDark.d.cts +9 -0
- package/dist/themes/SynthwaveDark.d.ts +9 -0
- package/dist/themes/SynthwaveDark.js +1 -0
- package/dist/themes/SynthwaveLight.cjs +1 -0
- package/dist/themes/SynthwaveLight.d.cts +12 -0
- package/dist/themes/SynthwaveLight.d.ts +12 -0
- package/dist/themes/SynthwaveLight.js +1 -0
- package/dist/themes/brands.cjs +1 -0
- package/dist/themes/brands.d.cts +41 -0
- package/dist/themes/brands.d.ts +41 -0
- package/dist/themes/brands.js +1 -0
- package/dist/themes/createBrandTheme.cjs +1 -0
- package/dist/themes/createBrandTheme.d.cts +55 -0
- package/dist/themes/createBrandTheme.d.ts +55 -0
- package/dist/themes/createBrandTheme.js +1 -0
- package/dist/themes/index.cjs +1 -0
- package/dist/themes/index.d.cts +41 -0
- package/dist/themes/index.d.ts +41 -0
- package/dist/themes/index.js +1 -0
- package/dist/themes.css +1 -0
- package/dist/tokens.css +1 -0
- package/dist/utils/aliases.cjs +9 -0
- package/dist/utils/aliases.d.cts +121 -0
- package/dist/utils/aliases.d.ts +121 -0
- package/dist/utils/aliases.js +9 -0
- package/dist/utils/contrast.cjs +1 -0
- package/dist/utils/contrast.d.cts +27 -0
- package/dist/utils/contrast.d.ts +27 -0
- package/dist/utils/contrast.js +1 -0
- package/dist/utils/cssVars.cjs +2 -0
- package/dist/utils/cssVars.d.cts +37 -0
- package/dist/utils/cssVars.d.ts +37 -0
- package/dist/utils/cssVars.js +2 -0
- package/dist/utils/foundation.cjs +15 -0
- package/dist/utils/foundation.d.cts +300 -0
- package/dist/utils/foundation.d.ts +300 -0
- package/dist/utils/foundation.js +15 -0
- package/dist/utils/mode.cjs +1 -0
- package/dist/utils/mode.d.cts +89 -0
- package/dist/utils/mode.d.ts +89 -0
- package/dist/utils/mode.js +1 -0
- package/dist/utils/theme.cjs +1 -0
- package/dist/utils/theme.d.cts +503 -0
- package/dist/utils/theme.d.ts +503 -0
- package/dist/utils/theme.js +1 -0
- package/dist/utils/toCss.cjs +10 -0
- package/dist/utils/toCss.d.cts +92 -0
- package/dist/utils/toCss.d.ts +92 -0
- package/dist/utils/toCss.js +10 -0
- package/package.json +70 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SkandaDX theme contract.
|
|
3
|
+
*
|
|
4
|
+
* A theme is a plain JSON-serializable object, which makes it the natural
|
|
5
|
+
* output format for a visual theme builder: the builder edits a `Theme`,
|
|
6
|
+
* and `themeToCss()` turns it into CSS custom properties that the styled
|
|
7
|
+
* (branded) component layer consumes.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The two resolved color modes a theme renders in. A brand pairs one theme
|
|
11
|
+
* per mode (see `brands`); `'system'` is a user *preference* consumers
|
|
12
|
+
* resolve to one of these via `prefers-color-scheme` before picking a theme.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export type ThemeColorMode = 'light' | 'dark';
|
|
17
|
+
/**
|
|
18
|
+
* An 11-step color ramp, 50 (lightest) → 950 (darkest), following the
|
|
19
|
+
* Tailwind/Radix step convention. Each key renders as `--skdx-color-<name>-<step>`,
|
|
20
|
+
* e.g. `primary[600]` → `--skdx-color-primary-600`.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export interface ColorScale {
|
|
25
|
+
50: string;
|
|
26
|
+
100: string;
|
|
27
|
+
200: string;
|
|
28
|
+
300: string;
|
|
29
|
+
400: string;
|
|
30
|
+
500: string;
|
|
31
|
+
600: string;
|
|
32
|
+
700: string;
|
|
33
|
+
800: string;
|
|
34
|
+
900: string;
|
|
35
|
+
950: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Role-based colors resolved from the {@link ThemeColors} scales — reach for
|
|
39
|
+
* these in component styling instead of a raw scale step, so swapping a
|
|
40
|
+
* theme's palette doesn't require touching component CSS.
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
export interface SemanticColors {
|
|
45
|
+
/** Page background. */
|
|
46
|
+
background: string;
|
|
47
|
+
/** Raised surface background (cards, panels). */
|
|
48
|
+
surface: string;
|
|
49
|
+
/** Surface background on hover. */
|
|
50
|
+
surfaceHover: string;
|
|
51
|
+
/** Overlay/scrim behind dialogs and drawers, typically translucent. */
|
|
52
|
+
overlay: string;
|
|
53
|
+
/** Primary body text color. */
|
|
54
|
+
text: string;
|
|
55
|
+
/** Secondary/de-emphasized text color. */
|
|
56
|
+
textMuted: string;
|
|
57
|
+
/** Text color for use on filled/primary backgrounds. */
|
|
58
|
+
textInverted: string;
|
|
59
|
+
/** Default border color. */
|
|
60
|
+
border: string;
|
|
61
|
+
/** Higher-contrast border, e.g. for inputs on hover/focus. */
|
|
62
|
+
borderStrong: string;
|
|
63
|
+
/** Focus ring / outline color. */
|
|
64
|
+
focusRing: string;
|
|
65
|
+
}
|
|
66
|
+
/** The five color scales a theme provides, each rendered as `--skdx-color-<name>-<step>`. @public */
|
|
67
|
+
export interface ThemeColors {
|
|
68
|
+
/** Brand/accent color, e.g. buttons, links, focus states at 500–600. */
|
|
69
|
+
primary: ColorScale;
|
|
70
|
+
/** Grays used for text, borders, and surfaces. */
|
|
71
|
+
neutral: ColorScale;
|
|
72
|
+
/** Positive/confirmation states (e.g. success toasts, valid form fields). */
|
|
73
|
+
success: ColorScale;
|
|
74
|
+
/** Caution states (e.g. warning banners). */
|
|
75
|
+
warning: ColorScale;
|
|
76
|
+
/** Destructive/error states (e.g. delete buttons, invalid form fields). */
|
|
77
|
+
danger: ColorScale;
|
|
78
|
+
/** Role-based colors resolved from the scales above — components should prefer these over raw scale steps. */
|
|
79
|
+
semantic: SemanticColors;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Font stacks, the type scale, and weight/line-height tokens. Rendered as
|
|
83
|
+
* `--skdx-font-*`.
|
|
84
|
+
*
|
|
85
|
+
* **Not part of {@link Theme}** — typography is theme-invariant and lives once
|
|
86
|
+
* in `foundation.ts` (see {@link typography}). A theme selects colors; it does
|
|
87
|
+
* not get to resize the type scale out from under a layout. The two font
|
|
88
|
+
* *stacks* are the sole exception, and only for themes that impersonate a
|
|
89
|
+
* published design language — see {@link ThemeTypographyDeviation}.
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
export interface ThemeTypography {
|
|
94
|
+
/** Body font stack, e.g. `-apple-system, BlinkMacSystemFont, 'Segoe UI', …`. */
|
|
95
|
+
fontFamily: string;
|
|
96
|
+
/** Monospace stack for code, e.g. `'SF Mono', ui-monospace, …`. */
|
|
97
|
+
fontFamilyMono: string;
|
|
98
|
+
/** Type scale from `xs` to `3xl`, e.g. `{ xs: '0.75rem', … }`. */
|
|
99
|
+
fontSize: {
|
|
100
|
+
xs: string;
|
|
101
|
+
sm: string;
|
|
102
|
+
md: string;
|
|
103
|
+
lg: string;
|
|
104
|
+
xl: string;
|
|
105
|
+
'2xl': string;
|
|
106
|
+
'3xl': string;
|
|
107
|
+
};
|
|
108
|
+
/** Numeric font weights, e.g. `{ regular: 400, medium: 500, semibold: 600, bold: 700 }`. */
|
|
109
|
+
fontWeight: {
|
|
110
|
+
regular: number;
|
|
111
|
+
medium: number;
|
|
112
|
+
semibold: number;
|
|
113
|
+
bold: number;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Unitless-or-CSS line-height values. `snug` is the control step — the
|
|
117
|
+
* leading a button, tab or menu label takes, tighter than body copy but not
|
|
118
|
+
* as clipped as `tight`, which is a display-heading value.
|
|
119
|
+
*/
|
|
120
|
+
lineHeight: {
|
|
121
|
+
tight: string;
|
|
122
|
+
snug: string;
|
|
123
|
+
normal: string;
|
|
124
|
+
relaxed: string;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Tracking scale, rendered as `--skdx-font-letter-spacing-<step>`. `tight`
|
|
128
|
+
* suits large display headings (which look loose at their default
|
|
129
|
+
* tracking); `wide`/`wider` suit small-caps, overlines and button labels.
|
|
130
|
+
*/
|
|
131
|
+
letterSpacing: {
|
|
132
|
+
tight: string;
|
|
133
|
+
normal: string;
|
|
134
|
+
wide: string;
|
|
135
|
+
wider: string;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Spacing scale (margin, padding, gap). Rendered as `--skdx-space-<step>`.
|
|
140
|
+
* **Not part of {@link Theme}** — lives once in `foundation.ts` (see {@link space}).
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
export interface ThemeSpace {
|
|
144
|
+
'1': string;
|
|
145
|
+
'2': string;
|
|
146
|
+
'3': string;
|
|
147
|
+
'4': string;
|
|
148
|
+
'5': string;
|
|
149
|
+
'6': string;
|
|
150
|
+
'8': string;
|
|
151
|
+
'10': string;
|
|
152
|
+
'12': string;
|
|
153
|
+
'16': string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Border-radius scale. Rendered as `--skdx-radius-<size>`.
|
|
157
|
+
* **Not part of {@link Theme}** — lives once in `foundation.ts` (see {@link radii}).
|
|
158
|
+
* @public
|
|
159
|
+
*/
|
|
160
|
+
export interface ThemeRadii {
|
|
161
|
+
sm: string;
|
|
162
|
+
/**
|
|
163
|
+
* The radius of a box nested *inside* a larger radiused surface — a menu row
|
|
164
|
+
* inside an overlay, a segment inside its well, a checkbox box. Sits between
|
|
165
|
+
* `sm` and `md` rather than at a ramp position of its own, because it is a
|
|
166
|
+
* relationship (inner to outer) and not a size step.
|
|
167
|
+
*/
|
|
168
|
+
inner: string;
|
|
169
|
+
md: string;
|
|
170
|
+
lg: string;
|
|
171
|
+
xl: string;
|
|
172
|
+
/** Fully round, e.g. `9999px` — for pills and circular avatars. */
|
|
173
|
+
full: string;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Control geometry — the metrics a Button, an Input and a Select at the same
|
|
177
|
+
* size all snap to, so they line up on a form row without each stylesheet
|
|
178
|
+
* re-deciding what "md" means.
|
|
179
|
+
*
|
|
180
|
+
* **Not part of {@link Theme}** — lives once in `foundation.ts` (see
|
|
181
|
+
* {@link controls}), for the same reason {@link space} does: density is a
|
|
182
|
+
* property of the design system, not of the brand painted on top of it. A
|
|
183
|
+
* consumer retunes it by setting the emitted custom properties on a subtree:
|
|
184
|
+
*
|
|
185
|
+
* ```css
|
|
186
|
+
* .compact-form { --skdx-control-height-md: 2rem; }
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* Values may reference other tokens (`var(--skdx-space-3)`) rather than restate
|
|
190
|
+
* a length, and several deliberately do — that is what keeps a control's
|
|
191
|
+
* padding on the spacing scale instead of beside it.
|
|
192
|
+
*
|
|
193
|
+
* @public
|
|
194
|
+
*/
|
|
195
|
+
export interface ThemeControls {
|
|
196
|
+
/** The control itself: the vertical rhythm, and the inline padding and icon gap paired with it. */
|
|
197
|
+
control: {
|
|
198
|
+
/**
|
|
199
|
+
* `compact` is the odd one out and is not a ramp step: it is the square a
|
|
200
|
+
* pagination link or a SegmentedControl segment takes, which sits inside a
|
|
201
|
+
* strip rather than on a form row and is a step under `md` in both
|
|
202
|
+
* reference libraries surveyed.
|
|
203
|
+
*/
|
|
204
|
+
height: {
|
|
205
|
+
sm: string;
|
|
206
|
+
md: string;
|
|
207
|
+
lg: string;
|
|
208
|
+
compact: string;
|
|
209
|
+
};
|
|
210
|
+
padding: {
|
|
211
|
+
sm: string;
|
|
212
|
+
md: string;
|
|
213
|
+
lg: string;
|
|
214
|
+
};
|
|
215
|
+
gap: {
|
|
216
|
+
sm: string;
|
|
217
|
+
md: string;
|
|
218
|
+
lg: string;
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
/** Glyph box inside a control. Proportional to the control, not to the font size, so changing line-height does not resize every icon. */
|
|
222
|
+
iconSize: {
|
|
223
|
+
sm: string;
|
|
224
|
+
md: string;
|
|
225
|
+
lg: string;
|
|
226
|
+
};
|
|
227
|
+
/** Selection indicators — checkbox box, radio dot, slider thumb. Switch pins its own track size; see `switch.css`. */
|
|
228
|
+
indicatorSize: {
|
|
229
|
+
sm: string;
|
|
230
|
+
md: string;
|
|
231
|
+
lg: string;
|
|
232
|
+
};
|
|
233
|
+
/** Collection rows — menu items, listbox options, table rows — and the seam between them. */
|
|
234
|
+
item: {
|
|
235
|
+
height: {
|
|
236
|
+
sm: string;
|
|
237
|
+
md: string;
|
|
238
|
+
lg: string;
|
|
239
|
+
};
|
|
240
|
+
gap: string;
|
|
241
|
+
};
|
|
242
|
+
/** Floating surfaces: menus, popovers, dialogs. */
|
|
243
|
+
overlay: {
|
|
244
|
+
padding: string;
|
|
245
|
+
radius: string;
|
|
246
|
+
minWidth: string;
|
|
247
|
+
};
|
|
248
|
+
/** Field furniture — the vertical step from a label to its control, and from a control to its help text. */
|
|
249
|
+
field: {
|
|
250
|
+
gap: string;
|
|
251
|
+
labelGap: string;
|
|
252
|
+
};
|
|
253
|
+
/** Minimum hit target. WCAG 2.2 §2.5.8 asks for 24×24 CSS px; the coarse-pointer tier raises it to the AAA 44px. */
|
|
254
|
+
target: {
|
|
255
|
+
min: string;
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The subset of {@link ThemeControls} that a coarse pointer overrides.
|
|
260
|
+
*
|
|
261
|
+
* Touch input gets larger targets, and `pointer: coarse` is the honest test —
|
|
262
|
+
* a small window on a desktop is still driven by a mouse, and a large tablet is
|
|
263
|
+
* still driven by a finger. Only sizes that are *hit* are listed: padding,
|
|
264
|
+
* gaps, radii and icon boxes are unchanged by how the user is pointing.
|
|
265
|
+
*
|
|
266
|
+
* @public
|
|
267
|
+
*/
|
|
268
|
+
export interface ThemeControlsCoarse {
|
|
269
|
+
control: {
|
|
270
|
+
height: {
|
|
271
|
+
sm: string;
|
|
272
|
+
md: string;
|
|
273
|
+
lg: string;
|
|
274
|
+
compact: string;
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
item: {
|
|
278
|
+
height: {
|
|
279
|
+
sm: string;
|
|
280
|
+
md: string;
|
|
281
|
+
lg: string;
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
target: {
|
|
285
|
+
min: string;
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Box-shadow scale, including the `overlay` shadow used by dialogs/popovers.
|
|
290
|
+
* Rendered as `--skdx-shadow-<size>`.
|
|
291
|
+
*
|
|
292
|
+
* **Not part of {@link Theme}** — the *geometry* (offsets, blurs, spreads and
|
|
293
|
+
* base alphas) lives once in `foundation.ts` (see {@link shadows}), and each
|
|
294
|
+
* value defers its color to `var(--skdx-shadow-color)` /
|
|
295
|
+
* `var(--skdx-shadow-strength)`, which is what a theme supplies via
|
|
296
|
+
* {@link ThemeShadowColor}. Before this split every theme repeated the same
|
|
297
|
+
* three offsets purely because they were welded to a color literal in the same
|
|
298
|
+
* string.
|
|
299
|
+
*
|
|
300
|
+
* @public
|
|
301
|
+
*/
|
|
302
|
+
export interface ThemeShadows {
|
|
303
|
+
sm: string;
|
|
304
|
+
md: string;
|
|
305
|
+
lg: string;
|
|
306
|
+
/** Shadow for elevated overlay surfaces (dialog, popover, dropdown content). */
|
|
307
|
+
overlay: string;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* The color half of the shadow contract — the only part of a shadow a theme
|
|
311
|
+
* owns. The geometry it tints lives in {@link shadows}.
|
|
312
|
+
*
|
|
313
|
+
* @public
|
|
314
|
+
*/
|
|
315
|
+
export interface ThemeShadowColor {
|
|
316
|
+
/**
|
|
317
|
+
* Space-separated sRGB channels, e.g. `'2 6 23'` — **not** a hex string. It
|
|
318
|
+
* is substituted into `rgb(<color> / <alpha>)`, which has no hex form.
|
|
319
|
+
*/
|
|
320
|
+
color: string;
|
|
321
|
+
/**
|
|
322
|
+
* Unitless multiplier applied to every base alpha in {@link shadows}. `'1'`
|
|
323
|
+
* is the light-theme reference and reproduces the original `skanda-light`
|
|
324
|
+
* shadows exactly; dark themes run around `'5'` because a shadow has to work
|
|
325
|
+
* against a dark surface rather than a white page. This is the calibration
|
|
326
|
+
* knob — it is a look, not a measurement, and is meant to be tuned by eye.
|
|
327
|
+
*/
|
|
328
|
+
strength: string;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* The font stacks a theme may override — the only part of {@link typography}
|
|
332
|
+
* that isn't fixed system-wide.
|
|
333
|
+
*
|
|
334
|
+
* Deliberately just the two stacks. A theme that merely *looks* different has
|
|
335
|
+
* no business resizing the type scale: a layout that reflows when you switch
|
|
336
|
+
* brand was only ever designed against one scale, and every other brand was
|
|
337
|
+
* hoping. Impersonating a design language, though, means impersonating its
|
|
338
|
+
* typeface — which is why `fluent` and `material-you` declare this and nothing
|
|
339
|
+
* else does.
|
|
340
|
+
*
|
|
341
|
+
* Present on a theme = the deviation. There is no wrapper to opt into.
|
|
342
|
+
*
|
|
343
|
+
* @public
|
|
344
|
+
*/
|
|
345
|
+
export type ThemeTypographyDeviation = Partial<Pick<ThemeTypography, 'fontFamily' | 'fontFamilyMono'>>;
|
|
346
|
+
/**
|
|
347
|
+
* The motion tokens a theme may retune — the four originally-required ones.
|
|
348
|
+
* The optional tokens ({@link ThemeMotion.easingExit}, the staggers, …) are
|
|
349
|
+
* deliberately unreachable: they exist to be uniform, and a theme that split
|
|
350
|
+
* an entrance curve from its matching exit would be shipping a mismatch, not a
|
|
351
|
+
* brand.
|
|
352
|
+
*
|
|
353
|
+
* See {@link ThemeMotion} for why motion is otherwise theme-invariant. Only
|
|
354
|
+
* `material-you`, `fluent` and `ant-daybreak` declare this (plus their dark
|
|
355
|
+
* counterparts, which inherit it through `createTheme`).
|
|
356
|
+
*
|
|
357
|
+
* @public
|
|
358
|
+
*/
|
|
359
|
+
export type ThemeMotionDeviation = Partial<Pick<ThemeMotion, 'durationFast' | 'durationNormal' | 'durationSlow' | 'easing'>>;
|
|
360
|
+
/**
|
|
361
|
+
* Animation durations, named easing curves, and stagger intervals shared by
|
|
362
|
+
* all components' transitions. Rendered as `--skdx-motion-*`.
|
|
363
|
+
*
|
|
364
|
+
* **Motion is theme-invariant by default, and that is deliberate.** A theme
|
|
365
|
+
* changes what the product *looks* like; it should not change how long the
|
|
366
|
+
* product makes you wait. Timing that shifts under you between brands reads
|
|
367
|
+
* as a bug, not as branding, and it silently changes the WCAG 2.3.3 surface
|
|
368
|
+
* (a 300ms curve and a 500ms curve are not equally forgiving to a vestibular
|
|
369
|
+
* user). Motion therefore lives once in `foundation.ts` (see {@link motion}),
|
|
370
|
+
* not on {@link Theme}. The three brand themes that *do* retune the base curve
|
|
371
|
+
* — `materialBrand`, `antBrand`, `fluentBrand` — declare it through
|
|
372
|
+
* {@link ThemeMotionDeviation}, the narrow escape hatch: each mirrors the
|
|
373
|
+
* published motion spec of the design language it impersonates, which is the
|
|
374
|
+
* whole point of those themes. Everything added below is left un-overridden by
|
|
375
|
+
* every bundled theme, and `ThemeMotionDeviation` cannot reach it.
|
|
376
|
+
*
|
|
377
|
+
* Every field beyond the original four is optional so that adding a token
|
|
378
|
+
* here never breaks a hand-written motion literal downstream;
|
|
379
|
+
* {@link defaultMotion} supplies the value that is actually emitted when one
|
|
380
|
+
* is omitted.
|
|
381
|
+
*
|
|
382
|
+
* @public
|
|
383
|
+
*/
|
|
384
|
+
export interface ThemeMotion {
|
|
385
|
+
/**
|
|
386
|
+
* Zero — for state changes that must feel like data, not animation (a probe
|
|
387
|
+
* re-rendering, a value updating). Named rather than hardcoded so "this is
|
|
388
|
+
* deliberately not animated" is legible at the call site.
|
|
389
|
+
* @default '0ms'
|
|
390
|
+
*/
|
|
391
|
+
durationInstant?: string;
|
|
392
|
+
/** Hover, focus and press micro-interactions — short enough to feel like direct manipulation. */
|
|
393
|
+
durationFast: string;
|
|
394
|
+
/** Open/close transitions for inline disclosure, e.g. accordion and collapsible panels. */
|
|
395
|
+
durationNormal: string;
|
|
396
|
+
/** Larger overlay enter/exit transitions, e.g. dialogs, drawers and popovers. */
|
|
397
|
+
durationSlow: string;
|
|
398
|
+
/**
|
|
399
|
+
* The default curve: a fast start with a long, soft landing (an expo-style
|
|
400
|
+
* decelerate). Feels like something arriving and settling into place, so
|
|
401
|
+
* use it for anything entering the screen or growing open.
|
|
402
|
+
*/
|
|
403
|
+
easing: string;
|
|
404
|
+
/**
|
|
405
|
+
* Mirror of {@link ThemeMotion.easing} — a slow start that accelerates away.
|
|
406
|
+
* Feels like something leaving rather than retreating, so use it for exits,
|
|
407
|
+
* dismissals and closes, where holding the user's attention on the way out
|
|
408
|
+
* is exactly what you do not want.
|
|
409
|
+
* @default 'cubic-bezier(0.4, 0, 1, 1)'
|
|
410
|
+
*/
|
|
411
|
+
easingExit?: string;
|
|
412
|
+
/**
|
|
413
|
+
* A symmetric ease-in-out with no overshoot and no drama. Feels like a
|
|
414
|
+
* value changing rather than an object moving, so use it for in-place state
|
|
415
|
+
* changes where nothing enters or leaves: colour swaps, toggles, theme
|
|
416
|
+
* changes, a control acknowledging that it was pressed.
|
|
417
|
+
* @default 'cubic-bezier(0.4, 0, 0.2, 1)'
|
|
418
|
+
*/
|
|
419
|
+
easingSteady?: string;
|
|
420
|
+
/**
|
|
421
|
+
* Constant rate, no acceleration at either end. Feels mechanical, which is
|
|
422
|
+
* correct for indeterminate loops — a spinner or a shimmer easing at every
|
|
423
|
+
* cycle boundary reads as a stutter or a stall rather than as progress.
|
|
424
|
+
* @default 'linear'
|
|
425
|
+
*/
|
|
426
|
+
easingLinear?: string;
|
|
427
|
+
/**
|
|
428
|
+
* Per-item delay for a sweep across many elements at once, small enough
|
|
429
|
+
* that the whole set still reads as one gesture rather than as a sequence.
|
|
430
|
+
* Use it when the count is large or unbounded — a page-wide theme change, a
|
|
431
|
+
* grid of icons re-tinting.
|
|
432
|
+
* @default '4ms'
|
|
433
|
+
*/
|
|
434
|
+
staggerTight?: string;
|
|
435
|
+
/**
|
|
436
|
+
* Per-item delay for a sequence you are meant to actually perceive as a
|
|
437
|
+
* sequence, where each item arrives distinctly. Use it only for short,
|
|
438
|
+
* bounded lists — at a dozen items it is already a noticeable wait, and at
|
|
439
|
+
* fifty it is a loading screen.
|
|
440
|
+
* @default '40ms'
|
|
441
|
+
*/
|
|
442
|
+
staggerLoose?: string;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* The canonical motion values, and the fallback {@link themeToCss} merges
|
|
446
|
+
* under a theme's own `motion` so that every theme emits the complete
|
|
447
|
+
* `--skdx-motion-*` surface — including the optional tokens no hand-written
|
|
448
|
+
* `Theme` literal declares. Keeping the values here rather than only in
|
|
449
|
+
* `defaultTheme` is what lets a theme opt out of a token without opting out
|
|
450
|
+
* of the CSS variable.
|
|
451
|
+
*/
|
|
452
|
+
export declare const defaultMotion: Required<ThemeMotion>;
|
|
453
|
+
/**
|
|
454
|
+
* A complete, plain-JSON-serializable theme — the single object that flows
|
|
455
|
+
* through {@link createTheme}, {@link themeToCss}, and {@link applyTheme}.
|
|
456
|
+
*
|
|
457
|
+
* **A theme is colors.** The type scale, weights, line-heights, tracking, the
|
|
458
|
+
* spacing scale, the radius scale, shadow geometry and motion timing are
|
|
459
|
+
* theme-invariant and live once in `foundation.ts`, emitted at `:root` by
|
|
460
|
+
* {@link foundationToCss}. Every bundled theme used to restate all of them
|
|
461
|
+
* identically — 38 copies of the same 62 lines — which made "what does this
|
|
462
|
+
* theme actually change?" unanswerable without a diff, and made adding a token
|
|
463
|
+
* a 38-file edit.
|
|
464
|
+
*
|
|
465
|
+
* The two escape hatches — `typography` and `motion` — are optional and
|
|
466
|
+
* narrow, for the themes that impersonate a published design language.
|
|
467
|
+
* Declaring one *is* the deviation; there is nothing to opt into.
|
|
468
|
+
*
|
|
469
|
+
* @public
|
|
470
|
+
*/
|
|
471
|
+
export interface Theme {
|
|
472
|
+
/** Unique theme name, e.g. `"skanda-light"`. Used as the `[data-skdx-theme="..."]` selector and the `data-skdx-theme` attribute value. */
|
|
473
|
+
name: string;
|
|
474
|
+
/** Which color mode this theme renders — `applyTheme` stamps it as `data-skdx-mode`. */
|
|
475
|
+
mode: ThemeColorMode;
|
|
476
|
+
colors: ThemeColors;
|
|
477
|
+
/** The color half of the shared shadow geometry — see {@link ThemeShadowColor}. */
|
|
478
|
+
shadow: ThemeShadowColor;
|
|
479
|
+
/** Font-stack deviation. Absent on all but two bundled themes — see {@link ThemeTypographyDeviation}. */
|
|
480
|
+
typography?: ThemeTypographyDeviation;
|
|
481
|
+
/** Motion deviation. Absent on all but three bundled themes — see {@link ThemeMotionDeviation}. */
|
|
482
|
+
motion?: ThemeMotionDeviation;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* A partial {@link Theme} for describing only what a brand changes from the
|
|
486
|
+
* default — every leaf value at every level is optional. Passed to
|
|
487
|
+
* {@link createTheme}, which deep-merges it onto a base theme.
|
|
488
|
+
*
|
|
489
|
+
* @example
|
|
490
|
+
* ```ts
|
|
491
|
+
* const override: ThemeOverride = {
|
|
492
|
+
* colors: { primary: { 500: '#7c3aed', 600: '#6d28d9' }, semantic: { focusRing: '#7c3aed' } },
|
|
493
|
+
* shadow: { strength: '5' },
|
|
494
|
+
* };
|
|
495
|
+
* ```
|
|
496
|
+
*
|
|
497
|
+
* @public
|
|
498
|
+
*/
|
|
499
|
+
export type ThemeOverride = {
|
|
500
|
+
[K in keyof Theme]?: Theme[K] extends object ? {
|
|
501
|
+
[K2 in keyof Theme[K]]?: Theme[K][K2] extends object ? Partial<Theme[K][K2]> : Theme[K][K2];
|
|
502
|
+
} : Theme[K];
|
|
503
|
+
};
|