@ids-group-ltd/ids-design-system 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/fesm2022/ids-group-ltd-ids-design-system.mjs +2523 -269
- package/fesm2022/ids-group-ltd-ids-design-system.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/_breakpoints.scss +50 -0
- package/styles/_dropdown-overlay.scss +1 -0
- package/styles/_ds-color.scss +36 -0
- package/styles/_overlay-motion.scss +18 -0
- package/styles/_scrollbar.scss +1 -0
- package/styles/_theme-activation.scss +49 -0
- package/styles/_tokens.scss +54 -17
- package/styles/ds.scss +15 -9
- package/themes/README.md +71 -58
- package/themes/{default/_palette.scss → _base-palette.scss} +35 -18
- package/themes/{default/_theme.scss → _semantic.scss} +77 -64
- package/themes/dark/_palette.scss +39 -0
- package/themes/dark/_theme.scss +122 -0
- package/themes/light/_palette.scss +34 -0
- package/themes/light/_theme.scss +15 -0
- package/types/ids-group-ltd-ids-design-system.d.ts +688 -30
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
// =========================================================================
|
|
2
|
-
//
|
|
2
|
+
// Base palette — Tier 1 theme-independent primitives.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// channels (--blue-h/s/l, --red-h/s/l,
|
|
7
|
-
//
|
|
8
|
-
// colour is "for". The --neutral-* FAMILY SLOT (which gray ramp is active)
|
|
9
|
-
// is semantic, so it lives in the theme (_theme.scss), not here.
|
|
4
|
+
// Emits at :root. Colour ramps and channels that are identical in every
|
|
5
|
+
// theme: hue ramps (--cool-gray-*, --brand-gray-*, --blue-*, --red-*, …),
|
|
6
|
+
// HSL channels (--blue-h/s/l, --red-h/s/l), shadow substrate h/s (NOT -l —
|
|
7
|
+
// that is per-theme), static anchors, and font families.
|
|
10
8
|
//
|
|
11
|
-
// The
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// A sibling palette (e.g. _palette-dark.scss) ships different ramp values; pair
|
|
16
|
-
// it with a matching theme file. Default = "Blue + Slate baseline".
|
|
9
|
+
// The --neutral-* FAMILY SLOT (which gray ramp is active) is per-theme and
|
|
10
|
+
// lives in each theme's _palette.scss mixin. Components consume only semantic
|
|
11
|
+
// roles; they never reference this file directly.
|
|
17
12
|
// =========================================================================
|
|
18
13
|
|
|
19
14
|
:root {
|
|
@@ -95,6 +90,9 @@
|
|
|
95
90
|
// -----------------------------------------------------------------------
|
|
96
91
|
// Green — success
|
|
97
92
|
// -----------------------------------------------------------------------
|
|
93
|
+
// HSL channels (additive — for focus-ring composition + ds-color). The ramp
|
|
94
|
+
// stops below stay hand-picked hex; these reproduce --green-500 ≈ #22A33A.
|
|
95
|
+
--green-h: 132; --green-s: 66%; --green-l: 39%;
|
|
98
96
|
--green-50: #ECFAEE;
|
|
99
97
|
--green-100: #D6F3DB;
|
|
100
98
|
--green-200: #BBE8C2;
|
|
@@ -107,6 +105,9 @@
|
|
|
107
105
|
// -----------------------------------------------------------------------
|
|
108
106
|
// Yellow — attention / warning
|
|
109
107
|
// -----------------------------------------------------------------------
|
|
108
|
+
// HSL channels (additive — for focus-ring composition + ds-color). Reproduce
|
|
109
|
+
// --yellow-400 ≈ #F4D43A; ramp stops below stay hand-picked hex.
|
|
110
|
+
--yellow-h: 47; --yellow-s: 89%; --yellow-l: 59%;
|
|
110
111
|
--yellow-50: #FFFBEA;
|
|
111
112
|
--yellow-100: #FEF8DC;
|
|
112
113
|
--yellow-200: #FCEFA1;
|
|
@@ -148,12 +149,28 @@
|
|
|
148
149
|
--sky-700: #1D4ED8;
|
|
149
150
|
|
|
150
151
|
// -----------------------------------------------------------------------
|
|
151
|
-
// Shadow tint — channel-split substrate.
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
// glows over dark surfaces.
|
|
152
|
+
// Shadow tint — channel-split substrate h/s only. The lightness (-l) is
|
|
153
|
+
// per-theme: light uses 7%, dark uses 95% (so the same alphas read as soft
|
|
154
|
+
// glows over dark surfaces). Each theme's _palette.scss mixin sets -l.
|
|
155
155
|
// -----------------------------------------------------------------------
|
|
156
156
|
--shadow-tint-h: 225;
|
|
157
157
|
--shadow-tint-s: 39%;
|
|
158
|
-
|
|
158
|
+
|
|
159
|
+
// -----------------------------------------------------------------------
|
|
160
|
+
// Theme-stable contrast anchors — never flip with the theme. On-fill text/
|
|
161
|
+
// icon roles point here so a dark theme keeps white-on-coloured-fill correct.
|
|
162
|
+
// -----------------------------------------------------------------------
|
|
163
|
+
--static-white: #FFF;
|
|
164
|
+
--static-ink: #161A28;
|
|
165
|
+
|
|
166
|
+
// -----------------------------------------------------------------------
|
|
167
|
+
// Font families — a theme/brand choice (the size/weight/leading SCALE is
|
|
168
|
+
// theme-independent and lives in styles/_tokens.scss). Display + heading
|
|
169
|
+
// default to body sans; a brand can mix a serif/display family here without
|
|
170
|
+
// touching component code.
|
|
171
|
+
// -----------------------------------------------------------------------
|
|
172
|
+
--font-sans: "Mulish", -apple-system, blinkmacsystemfont, "Segoe UI", roboto, sans-serif;
|
|
173
|
+
--font-mono: "JetBrains Mono", ui-monospace, sfmono-regular, menlo, monospace;
|
|
174
|
+
--font-display: var(--font-sans);
|
|
175
|
+
--font-heading: var(--font-sans);
|
|
159
176
|
}
|
|
@@ -1,40 +1,21 @@
|
|
|
1
1
|
// =========================================================================
|
|
2
|
-
//
|
|
2
|
+
// Shared role structure — Tier 2 semantic role ASSIGNMENTS.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// whole system. A sibling theme (e.g. dark) ships its own palette + this map.
|
|
4
|
+
// Exposes @mixin roles: the role map whose structure is identical across
|
|
5
|
+
// themes and which resolves through the per-theme palette (surfaces →
|
|
6
|
+
// --neutral-*, text/icon/border → --neutral-*, brand channels, status, focus,
|
|
7
|
+
// semantic→palette bridge). These are the LIGHT-DEFAULT values — dark theme
|
|
8
|
+
// overrides only the deltas in its own _theme.scss mixin body.
|
|
10
9
|
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// This mixin is an authoring-DRY device. At runtime, exactly one theme block
|
|
11
|
+
// matches (`:not([data-theme='dark'])` vs `[data-theme='dark']`), and that
|
|
12
|
+
// block declares the complete token set itself (palette + roles + overrides).
|
|
13
13
|
// =========================================================================
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
/* Neutral family slot — semantic pointer at the active gray ramp from the
|
|
17
|
-
palette. Default: hand-drawn cool-gray. <html data-neutrals="brand">
|
|
18
|
-
(ds-docs tweaks panel) repoints it at the brand-derived brand-gray ramp,
|
|
19
|
-
where --primary-h re-tints every gray. Roles below consume --neutral-*
|
|
20
|
-
so the family switch never touches them. */
|
|
21
|
-
--neutral-0: var(--cool-gray-0);
|
|
22
|
-
--neutral-50: var(--cool-gray-50);
|
|
23
|
-
--neutral-100: var(--cool-gray-100);
|
|
24
|
-
--neutral-150: var(--cool-gray-150);
|
|
25
|
-
--neutral-200: var(--cool-gray-200);
|
|
26
|
-
--neutral-300: var(--cool-gray-300);
|
|
27
|
-
--neutral-400: var(--cool-gray-400);
|
|
28
|
-
--neutral-500: var(--cool-gray-500);
|
|
29
|
-
--neutral-600: var(--cool-gray-600);
|
|
30
|
-
--neutral-700: var(--cool-gray-700);
|
|
31
|
-
--neutral-800: var(--cool-gray-800);
|
|
32
|
-
--neutral-900: var(--cool-gray-900);
|
|
33
|
-
--neutral-950: var(--cool-gray-950);
|
|
34
|
-
|
|
15
|
+
@mixin roles {
|
|
35
16
|
/* Surfaces — six-stop scale.
|
|
36
17
|
· canvas : page background
|
|
37
|
-
· default : cards, sheets, toolbars (the
|
|
18
|
+
· default : cards, sheets, toolbars (the "paper")
|
|
38
19
|
· secondary : hover lanes, table heads, addons, code blocks
|
|
39
20
|
· overlay : modals, drawers, popovers (paired with scrim)
|
|
40
21
|
· tint : brand-tinted (active rows, sidenav active item)
|
|
@@ -84,34 +65,25 @@
|
|
|
84
65
|
|
|
85
66
|
/* Text overlaid on arbitrary imagery (camera feeds, photos) — pairs a
|
|
86
67
|
guaranteed-light colour with a contrast shadow. */
|
|
87
|
-
--text-on-media: var(--
|
|
68
|
+
--text-on-media: var(--static-white);
|
|
88
69
|
--text-on-media-shadow: 0 1px 3px hsl(0deg 0% 0% / 70%);
|
|
89
70
|
--text-link: var(--blue-700);
|
|
90
|
-
--text-on-primary: var(--
|
|
91
|
-
--text-on-success: var(--
|
|
71
|
+
--text-on-primary: var(--static-white);
|
|
72
|
+
--text-on-success: var(--static-white);
|
|
92
73
|
|
|
93
74
|
/* Warning fill is yellow (--yellow-400 #F4D43A) — white text on it is only
|
|
94
75
|
~1.5:1 (fails WCAG). On-warning text is the darkest neutral (~10:1). */
|
|
95
|
-
--text-on-warning: var(--
|
|
96
|
-
--text-on-error: var(--
|
|
76
|
+
--text-on-warning: var(--static-ink);
|
|
77
|
+
--text-on-error: var(--static-white);
|
|
97
78
|
|
|
98
79
|
/* Icons */
|
|
99
80
|
--icon-default: var(--neutral-500);
|
|
100
81
|
--icon-strong: var(--neutral-700);
|
|
101
82
|
--icon-muted: var(--neutral-400);
|
|
102
|
-
--icon-on-primary: var(--
|
|
103
|
-
|
|
104
|
-
/* Font families — a theme/brand choice (the size/weight/leading SCALE is
|
|
105
|
-
theme-independent and lives in styles/_tokens.scss). Display + heading
|
|
106
|
-
default to body sans; a brand can mix a serif/display family here without
|
|
107
|
-
touching component code. */
|
|
108
|
-
--font-sans: "Mulish", -apple-system, blinkmacsystemfont, "Segoe UI", roboto, sans-serif;
|
|
109
|
-
--font-mono: "JetBrains Mono", ui-monospace, sfmono-regular, menlo, monospace;
|
|
110
|
-
--font-display: var(--font-sans);
|
|
111
|
-
--font-heading: var(--font-sans);
|
|
83
|
+
--icon-on-primary: var(--static-white);
|
|
112
84
|
|
|
113
85
|
/* Semantic → palette bridge. The lib knows colours by PURPOSE; the theme
|
|
114
|
-
(themes/
|
|
86
|
+
(themes/light/_theme.scss) ships the concrete ramps + HSL channels. This
|
|
115
87
|
is the one place that maps semantic roles onto a concrete palette. A brand
|
|
116
88
|
re-skins by overriding either the palette (--blue-*, --red-*) or these
|
|
117
89
|
role tokens directly.
|
|
@@ -122,6 +94,12 @@
|
|
|
122
94
|
--error-h: var(--red-h);
|
|
123
95
|
--error-s: var(--red-s);
|
|
124
96
|
--error-l: var(--red-l);
|
|
97
|
+
--success-h: var(--green-h);
|
|
98
|
+
--success-s: var(--green-s);
|
|
99
|
+
--success-l: var(--green-l);
|
|
100
|
+
--warning-h: var(--yellow-h);
|
|
101
|
+
--warning-s: var(--yellow-s);
|
|
102
|
+
--warning-l: var(--yellow-l);
|
|
125
103
|
|
|
126
104
|
/* Primary roles.
|
|
127
105
|
Hover / pressed / selected-hover are DERIVED from --primary at runtime via
|
|
@@ -137,7 +115,7 @@
|
|
|
137
115
|
--primary-muted: var(--blue-100);
|
|
138
116
|
--primary-muted-strong: var(--blue-200);
|
|
139
117
|
--primary-strong: var(--blue-700);
|
|
140
|
-
--primary-on: var(--
|
|
118
|
+
--primary-on: var(--static-white);
|
|
141
119
|
|
|
142
120
|
/* Accent / secondary role — composed from --secondary-h/s/l channels.
|
|
143
121
|
Channels default to brand values so unbranded apps render identical to
|
|
@@ -154,6 +132,7 @@
|
|
|
154
132
|
--secondary-strong: hsl(var(--secondary-h) var(--secondary-s) calc(var(--secondary-l) - 11%));
|
|
155
133
|
--secondary-subtitle: hsl(var(--secondary-h) 100% 97%);
|
|
156
134
|
--secondary-muted: hsl(var(--secondary-h) 95% 94%);
|
|
135
|
+
--secondary-muted-strong: hsl(var(--secondary-h) 95% 89%);
|
|
157
136
|
--secondary-on: var(--primary-on);
|
|
158
137
|
|
|
159
138
|
/* Tertiary — third brand hue. Used by the tertiary button variant and
|
|
@@ -173,6 +152,7 @@
|
|
|
173
152
|
--tertiary-strong: hsl(var(--tertiary-h) var(--tertiary-s) calc(var(--tertiary-l) - 11%));
|
|
174
153
|
--tertiary-subtitle: hsl(var(--tertiary-h) 100% 97%);
|
|
175
154
|
--tertiary-muted: hsl(var(--tertiary-h) 95% 94%);
|
|
155
|
+
--tertiary-muted-strong: hsl(var(--tertiary-h) 95% 89%);
|
|
176
156
|
--tertiary-on: var(--primary-on);
|
|
177
157
|
|
|
178
158
|
/* Status roles.
|
|
@@ -184,6 +164,7 @@
|
|
|
184
164
|
--success-hover: color-mix(in srgb, var(--success) 88%, black);
|
|
185
165
|
--success-subtitle: var(--green-50);
|
|
186
166
|
--success-muted: var(--green-100);
|
|
167
|
+
--success-muted-strong: var(--green-200);
|
|
187
168
|
--success-border: var(--green-200);
|
|
188
169
|
--success-text: var(--green-700);
|
|
189
170
|
|
|
@@ -191,6 +172,7 @@
|
|
|
191
172
|
--warning-hover: color-mix(in srgb, var(--warning) 88%, black);
|
|
192
173
|
--warning-subtitle: var(--yellow-50);
|
|
193
174
|
--warning-muted: var(--yellow-100);
|
|
175
|
+
--warning-muted-strong: var(--yellow-200);
|
|
194
176
|
--warning-border: var(--yellow-200);
|
|
195
177
|
--warning-text: var(--yellow-700);
|
|
196
178
|
|
|
@@ -199,9 +181,18 @@
|
|
|
199
181
|
--error-pressed: color-mix(in srgb, var(--error) 76%, black);
|
|
200
182
|
--error-subtitle: var(--red-50);
|
|
201
183
|
--error-muted: var(--red-100);
|
|
184
|
+
--error-muted-strong: var(--red-200);
|
|
202
185
|
--error-border: var(--red-200);
|
|
203
186
|
--error-text: var(--red-600);
|
|
204
187
|
|
|
188
|
+
/* -pressed (success/warning) + -on aliases — added for the --accent-* pointer
|
|
189
|
+
family so every ds-color family resolves --accent-pressed / --accent-on. */
|
|
190
|
+
--success-pressed: color-mix(in srgb, var(--success) 76%, black);
|
|
191
|
+
--warning-pressed: color-mix(in srgb, var(--warning) 76%, black);
|
|
192
|
+
--error-on: var(--text-on-error);
|
|
193
|
+
--success-on: var(--text-on-success);
|
|
194
|
+
--warning-on: var(--text-on-warning);
|
|
195
|
+
|
|
205
196
|
--info: var(--sky-500);
|
|
206
197
|
--info-hover: color-mix(in srgb, var(--info) 88%, black);
|
|
207
198
|
--info-subtitle: var(--sky-50);
|
|
@@ -256,22 +247,44 @@
|
|
|
256
247
|
0 0 0 3px hsl(var(--primary-h) var(--primary-s) var(--primary-l) / var(--focus-field-alpha));
|
|
257
248
|
--focus-field-error:
|
|
258
249
|
0 0 0 3px hsl(var(--error-h) var(--error-s) var(--error-l) / var(--focus-field-alpha));
|
|
259
|
-
}
|
|
260
250
|
|
|
261
|
-
/*
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
--
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
--
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
--
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
--
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
--
|
|
251
|
+
/* Per-family focus rings/fields — pre-composed once from each family's
|
|
252
|
+
channels so ds-color flips a single --accent-focus-* pointer (no :root
|
|
253
|
+
composite re-declaration in the scope). --focus-ring-error exists above. */
|
|
254
|
+
--focus-ring-secondary:
|
|
255
|
+
0 0 0 2px var(--focus-ring-inner),
|
|
256
|
+
0 0 0 4px hsl(var(--secondary-h) var(--secondary-s) var(--secondary-l) / 100%);
|
|
257
|
+
--focus-ring-tertiary:
|
|
258
|
+
0 0 0 2px var(--focus-ring-inner),
|
|
259
|
+
0 0 0 4px hsl(var(--tertiary-h) var(--tertiary-s) var(--tertiary-l) / 100%);
|
|
260
|
+
--focus-ring-success:
|
|
261
|
+
0 0 0 2px var(--focus-ring-inner),
|
|
262
|
+
0 0 0 4px hsl(var(--success-h) var(--success-s) var(--success-l) / 100%);
|
|
263
|
+
--focus-ring-warning:
|
|
264
|
+
0 0 0 2px var(--focus-ring-inner),
|
|
265
|
+
0 0 0 4px hsl(var(--warning-h) var(--warning-s) var(--warning-l) / 100%);
|
|
266
|
+
--focus-field-secondary:
|
|
267
|
+
0 0 0 3px hsl(var(--secondary-h) var(--secondary-s) var(--secondary-l) / var(--focus-field-alpha));
|
|
268
|
+
--focus-field-tertiary:
|
|
269
|
+
0 0 0 3px hsl(var(--tertiary-h) var(--tertiary-s) var(--tertiary-l) / var(--focus-field-alpha));
|
|
270
|
+
--focus-field-success:
|
|
271
|
+
0 0 0 3px hsl(var(--success-h) var(--success-s) var(--success-l) / var(--focus-field-alpha));
|
|
272
|
+
--focus-field-warning:
|
|
273
|
+
0 0 0 3px hsl(var(--warning-h) var(--warning-s) var(--warning-l) / var(--focus-field-alpha));
|
|
274
|
+
|
|
275
|
+
/* Accent pointer layer — the single indirection ds-color flips. Defaults to
|
|
276
|
+
the primary family (+ existing focus/tint tokens) so the unbranded theme is
|
|
277
|
+
pixel-identical. Components read these for their accent instead of
|
|
278
|
+
--primary* / --focus-* / --surface-tint. */
|
|
279
|
+
--accent: var(--primary);
|
|
280
|
+
--accent-hover: var(--primary-hover);
|
|
281
|
+
--accent-pressed: var(--primary-pressed);
|
|
282
|
+
--accent-strong: var(--primary-strong);
|
|
283
|
+
--accent-subtitle: var(--primary-subtitle);
|
|
284
|
+
--accent-muted: var(--primary-muted);
|
|
285
|
+
--accent-muted-strong: var(--primary-muted-strong);
|
|
286
|
+
--accent-on: var(--primary-on);
|
|
287
|
+
--accent-focus-ring: var(--focus-ring);
|
|
288
|
+
--accent-focus-field: var(--focus-field);
|
|
289
|
+
--accent-surface-tint: var(--surface-tint);
|
|
277
290
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// =========================================================================
|
|
2
|
+
// Dark palette — Tier 1b per-theme primitives.
|
|
3
|
+
//
|
|
4
|
+
// Exposes @mixin palette with ONLY the dark-specific primitives:
|
|
5
|
+
// · --neutral-* slot: hand-tuned dark neutrals (NOT a linear inverse —
|
|
6
|
+
// note --neutral-0 is an ELEVATED card surface, LIGHTER than the
|
|
7
|
+
// --neutral-50 canvas — the opposite of light, where 0 (#FFF) is the
|
|
8
|
+
// brightest stop). Brand/status ramps are left to the role layer.
|
|
9
|
+
// · --shadow-tint-l: 95% (flipped so same alphas read as soft glows)
|
|
10
|
+
//
|
|
11
|
+
// Theme-independent ramps (--cool-gray-*, --brand-gray-*, --blue-*, etc.)
|
|
12
|
+
// and HSL channels live in themes/_base-palette.scss and emit at :root.
|
|
13
|
+
//
|
|
14
|
+
// KNOWN LIMITATION — data-neutrals="brand" + dark: this ramp overrides
|
|
15
|
+
// --neutral-* directly, so when both `[data-neutrals='brand']` and
|
|
16
|
+
// `[data-theme='dark']` are set (equal specificity) dark wins by source order —
|
|
17
|
+
// the brand-gray hue-tint is dropped and these fixed dark neutrals apply. Benign
|
|
18
|
+
// (renders correctly dark, just not brand-hue-tinted); a dark brand-gray ramp is
|
|
19
|
+
// a future follow-up, not v1.
|
|
20
|
+
// =========================================================================
|
|
21
|
+
|
|
22
|
+
@mixin palette {
|
|
23
|
+
--neutral-0: #171B24; // surface-default / overlay (cards) — elevated
|
|
24
|
+
--neutral-50: #0F131A; // surface-canvas — darkest (page bg)
|
|
25
|
+
--neutral-100: #1E2330; // surface-secondary / disabled
|
|
26
|
+
--neutral-150: #242A38; // surface-muted, border-subtitle/divider/disabled
|
|
27
|
+
--neutral-200: #2A3040; // border-default
|
|
28
|
+
--neutral-300: #3A4252; // border-strong
|
|
29
|
+
--neutral-400: #6B7388; // text-muted/disabled, icon-muted
|
|
30
|
+
--neutral-500: #8A93A6; // text-tertiary, icon-default
|
|
31
|
+
--neutral-600: #9BA3B4;
|
|
32
|
+
--neutral-700: #B7BFD0; // text-secondary, icon-strong, border-inverted
|
|
33
|
+
--neutral-800: #CDD3E0;
|
|
34
|
+
--neutral-900: #E7EAF2; // text-primary, surface-inverted
|
|
35
|
+
--neutral-950: #F4F6FA;
|
|
36
|
+
|
|
37
|
+
// Shadow substrate flips light so the same alphas read as soft glows on dark.
|
|
38
|
+
--shadow-tint-l: 95%;
|
|
39
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// =========================================================================
|
|
2
|
+
// Dark theme — Tier 2 role overrides.
|
|
3
|
+
//
|
|
4
|
+
// Composes the dark palette (neutral ramp + shadow-l 95%) with the shared
|
|
5
|
+
// role structure, then overrides only the roles whose VALUES differ from
|
|
6
|
+
// the light defaults. The activation selector (:root[data-theme='dark'])
|
|
7
|
+
// lives in styles/_theme-activation.scss. Dark is opt-in — light is the
|
|
8
|
+
// default; there is no automatic prefers-color-scheme switch.
|
|
9
|
+
//
|
|
10
|
+
// Most roles follow the inverted --neutral-* ramp automatically (custom
|
|
11
|
+
// props resolve at use-time). This file overrides ONLY roles that can't
|
|
12
|
+
// follow the flip: tint/subtle surfaces (near-white *-50 picks → dark hue
|
|
13
|
+
// tints), on-tint text (*-text / *-strong → lighter stops), hover/pressed
|
|
14
|
+
// direction, scrim (must stay dark), focus halo alpha, and charts.
|
|
15
|
+
// On-fill text already points at theme-stable --static-white/--static-ink.
|
|
16
|
+
// =========================================================================
|
|
17
|
+
|
|
18
|
+
@use 'palette';
|
|
19
|
+
@use '../semantic';
|
|
20
|
+
|
|
21
|
+
@mixin theme {
|
|
22
|
+
@include palette.palette;
|
|
23
|
+
@include semantic.roles;
|
|
24
|
+
|
|
25
|
+
// Interaction states: on dark, hover/pressed must LIGHTEN. The default theme
|
|
26
|
+
// derives them as color-mix toward black (darkens) — wrong direction here.
|
|
27
|
+
// Mirror the light recipe's 88% / 76% steps, mixed toward white instead.
|
|
28
|
+
--primary-hover: color-mix(in srgb, var(--primary) 88%, white);
|
|
29
|
+
--primary-pressed: color-mix(in srgb, var(--primary) 76%, white);
|
|
30
|
+
--primary-selected-hover: color-mix(in srgb, var(--primary) 88%, white);
|
|
31
|
+
--secondary-hover: color-mix(in srgb, var(--secondary) 88%, white);
|
|
32
|
+
--secondary-pressed: color-mix(in srgb, var(--secondary) 76%, white);
|
|
33
|
+
--tertiary-hover: color-mix(in srgb, var(--tertiary) 88%, white);
|
|
34
|
+
--tertiary-pressed: color-mix(in srgb, var(--tertiary) 76%, white);
|
|
35
|
+
--success-hover: color-mix(in srgb, var(--success) 88%, white);
|
|
36
|
+
--warning-hover: color-mix(in srgb, var(--warning) 88%, white);
|
|
37
|
+
--error-hover: color-mix(in srgb, var(--error) 88%, white);
|
|
38
|
+
--error-pressed: color-mix(in srgb, var(--error) 76%, white);
|
|
39
|
+
--success-pressed: color-mix(in srgb, var(--success) 76%, white);
|
|
40
|
+
--warning-pressed: color-mix(in srgb, var(--warning) 76%, white);
|
|
41
|
+
--info-hover: color-mix(in srgb, var(--info) 88%, white);
|
|
42
|
+
|
|
43
|
+
// Brand tint surfaces + on-tint text (channel-derived → track rebrand).
|
|
44
|
+
--surface-tint: hsl(var(--primary-h) 45% 16%);
|
|
45
|
+
--primary-subtitle: hsl(var(--primary-h) 45% 18%);
|
|
46
|
+
--primary-muted: hsl(var(--primary-h) 40% 26%);
|
|
47
|
+
--primary-muted-strong: hsl(var(--primary-h) 42% 32%);
|
|
48
|
+
--primary-strong: hsl(var(--primary-h) 90% 72%);
|
|
49
|
+
|
|
50
|
+
--secondary-subtitle: hsl(var(--secondary-h) 45% 18%);
|
|
51
|
+
--secondary-muted: hsl(var(--secondary-h) 40% 26%);
|
|
52
|
+
--secondary-muted-strong: hsl(var(--secondary-h) 42% 32%);
|
|
53
|
+
--secondary-strong: hsl(var(--secondary-h) 90% 72%);
|
|
54
|
+
|
|
55
|
+
--tertiary-subtitle: hsl(var(--tertiary-h) 45% 18%);
|
|
56
|
+
--tertiary-muted: hsl(var(--tertiary-h) 40% 26%);
|
|
57
|
+
--tertiary-muted-strong: hsl(var(--tertiary-h) 42% 32%);
|
|
58
|
+
--tertiary-strong: hsl(var(--tertiary-h) 90% 72%);
|
|
59
|
+
|
|
60
|
+
--text-link: hsl(var(--primary-h) 90% 74%);
|
|
61
|
+
--link-visited: hsl(var(--primary-h) 50% 70%);
|
|
62
|
+
|
|
63
|
+
// Status families: dark tint bg + border, lighter text.
|
|
64
|
+
--success-subtitle: hsl(132deg 38% 14%);
|
|
65
|
+
--success-muted: hsl(132deg 34% 20%);
|
|
66
|
+
--success-muted-strong: hsl(132deg 30% 28%);
|
|
67
|
+
--success-border: hsl(132deg 30% 28%);
|
|
68
|
+
--success-text: hsl(132deg 55% 62%);
|
|
69
|
+
|
|
70
|
+
--warning-subtitle: hsl(45deg 42% 14%);
|
|
71
|
+
--warning-muted: hsl(45deg 38% 22%);
|
|
72
|
+
--warning-muted-strong: hsl(45deg 35% 30%);
|
|
73
|
+
--warning-border: hsl(45deg 35% 30%);
|
|
74
|
+
--warning-text: hsl(45deg 90% 62%);
|
|
75
|
+
|
|
76
|
+
--error-subtitle: hsl(0deg 45% 16%);
|
|
77
|
+
--error-muted: hsl(0deg 40% 24%);
|
|
78
|
+
--error-muted-strong: hsl(0deg 38% 32%);
|
|
79
|
+
--error-border: hsl(0deg 38% 32%);
|
|
80
|
+
--error-text: hsl(0deg 85% 74%);
|
|
81
|
+
|
|
82
|
+
--info-subtitle: hsl(217deg 45% 16%);
|
|
83
|
+
--info-muted: hsl(217deg 40% 24%);
|
|
84
|
+
--info-border: hsl(217deg 38% 32%);
|
|
85
|
+
--info-text: hsl(217deg 90% 74%);
|
|
86
|
+
|
|
87
|
+
// Status pills that referenced palette stops directly (green-50/700) — repoint
|
|
88
|
+
// to the dark status roles so the lifecycle pill reads on dark. (planning →
|
|
89
|
+
// neutral, confirmed → primary-*, completed → neutral all follow flips.)
|
|
90
|
+
--status-active-bg-color: var(--success-subtitle);
|
|
91
|
+
--status-active-text-color: var(--success-text);
|
|
92
|
+
|
|
93
|
+
// Scrim stays dark — must NOT follow --shadow-tint-l: 95%.
|
|
94
|
+
--surface-scrim: hsl(225deg 39% 4% / 70%);
|
|
95
|
+
|
|
96
|
+
// Field focus halo — boost alpha for legibility on dark.
|
|
97
|
+
--focus-field-alpha: .35;
|
|
98
|
+
|
|
99
|
+
// Chart / dataviz overrides. Axis/grid/label/title/cursor already flip via the
|
|
100
|
+
// --neutral-* / --text-* roles; only the light-bg-tuned bits move here.
|
|
101
|
+
--chart-hover-bg-color: hsl(0deg 0% 100% / 6%); // light wash (default dark wash is invisible on dark)
|
|
102
|
+
--chart-tooltip-bg-color: var(--surface-overlay); // native dark tooltip, not an inverted light box
|
|
103
|
+
--chart-tooltip-text-color: var(--text-primary);
|
|
104
|
+
--chart-tooltip-border: var(--border-strong);
|
|
105
|
+
|
|
106
|
+
// Sequential — flip so low → high reads dark → bright on a dark canvas.
|
|
107
|
+
--chart-seq-1: var(--blue-800);
|
|
108
|
+
--chart-seq-2: var(--blue-700);
|
|
109
|
+
--chart-seq-3: var(--blue-600);
|
|
110
|
+
--chart-seq-4: var(--blue-500);
|
|
111
|
+
--chart-seq-5: var(--blue-400);
|
|
112
|
+
--chart-seq-6: var(--blue-300);
|
|
113
|
+
|
|
114
|
+
// Divergent — bright red ← dark-neutral zero → bright green (|value| → brightness).
|
|
115
|
+
--chart-div--3: hsl(0deg 70% 62%);
|
|
116
|
+
--chart-div--2: hsl(0deg 55% 46%);
|
|
117
|
+
--chart-div--1: hsl(0deg 45% 32%);
|
|
118
|
+
--chart-div-0: var(--neutral-150);
|
|
119
|
+
--chart-div-1: hsl(140deg 40% 32%);
|
|
120
|
+
--chart-div-2: hsl(140deg 48% 46%);
|
|
121
|
+
--chart-div-3: hsl(140deg 55% 60%);
|
|
122
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// =========================================================================
|
|
2
|
+
// Light palette — Tier 1b per-theme primitives.
|
|
3
|
+
//
|
|
4
|
+
// Exposes @mixin palette with ONLY the light-specific primitives:
|
|
5
|
+
// · --neutral-* slot pointed at the cool-gray ramp
|
|
6
|
+
// · --shadow-tint-l: 7% (light shadow substrate lightness)
|
|
7
|
+
//
|
|
8
|
+
// Theme-independent ramps (--cool-gray-*, --brand-gray-*, --blue-*, etc.)
|
|
9
|
+
// and HSL channels live in themes/_base-palette.scss and emit at :root.
|
|
10
|
+
// =========================================================================
|
|
11
|
+
|
|
12
|
+
@mixin palette {
|
|
13
|
+
/* Neutral family slot — semantic pointer at the active gray ramp from the
|
|
14
|
+
palette. Default: hand-drawn cool-gray. <html data-neutrals="brand">
|
|
15
|
+
(ds-docs tweaks panel) repoints it at the brand-derived brand-gray ramp,
|
|
16
|
+
where --primary-h re-tints every gray. Roles below consume --neutral-*
|
|
17
|
+
so the family switch never touches them. */
|
|
18
|
+
--neutral-0: var(--cool-gray-0);
|
|
19
|
+
--neutral-50: var(--cool-gray-50);
|
|
20
|
+
--neutral-100: var(--cool-gray-100);
|
|
21
|
+
--neutral-150: var(--cool-gray-150);
|
|
22
|
+
--neutral-200: var(--cool-gray-200);
|
|
23
|
+
--neutral-300: var(--cool-gray-300);
|
|
24
|
+
--neutral-400: var(--cool-gray-400);
|
|
25
|
+
--neutral-500: var(--cool-gray-500);
|
|
26
|
+
--neutral-600: var(--cool-gray-600);
|
|
27
|
+
--neutral-700: var(--cool-gray-700);
|
|
28
|
+
--neutral-800: var(--cool-gray-800);
|
|
29
|
+
--neutral-900: var(--cool-gray-900);
|
|
30
|
+
--neutral-950: var(--cool-gray-950);
|
|
31
|
+
|
|
32
|
+
// Shadow substrate lightness for light theme.
|
|
33
|
+
--shadow-tint-l: 7%;
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// =========================================================================
|
|
2
|
+
// Light theme — Tier 2 role assignments (light).
|
|
3
|
+
//
|
|
4
|
+
// Composes the light-specific palette (neutral slot + shadow-l) with the
|
|
5
|
+
// shared role structure. Light needs no extra role overrides — _roles.scss
|
|
6
|
+
// already holds the light-default values.
|
|
7
|
+
// =========================================================================
|
|
8
|
+
|
|
9
|
+
@use 'palette';
|
|
10
|
+
@use '../semantic';
|
|
11
|
+
|
|
12
|
+
@mixin theme {
|
|
13
|
+
@include palette.palette;
|
|
14
|
+
@include semantic.roles;
|
|
15
|
+
}
|