@webority/theme 0.36.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/purge-safelist.json +1 -0
- package/dist/webority-theme.css +1 -1
- package/package.json +5 -7
- package/scss/_components.scss +1 -1
- package/scss/_tokens.scss +18 -6
- package/scss/_variables.scss +2 -0
- package/scss/_wui-aliases.scss +33 -17
- package/scss/wui/_choice.scss +8 -8
- package/scss/wui/_controls.scss +14 -11
- package/scss/wui/_data.scss +39 -0
- package/scss/wui/_flow.scss +79 -25
- package/scss/wui/_media.scss +5 -5
- package/scss/wui/_rich-text.scss +2 -2
- package/scss/wui/_shell.scss +16 -3
- package/scss/wui/_utilities.scss +49 -14
package/package.json
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Webority shared design system — Bootstrap 5.3 SCSS overrides, --wui-* tokens, and shared component CSS. The single source of brand chrome for React portals and Razor sites.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public",
|
|
8
8
|
"registry": "https://registry.npmjs.org/"
|
|
9
9
|
},
|
|
10
|
-
"repository": {
|
|
11
|
-
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/Webority/webority-ui.git",
|
|
13
|
-
"directory": "packages/theme"
|
|
14
|
-
},
|
|
15
10
|
"files": [
|
|
16
11
|
"index.scss",
|
|
17
12
|
"scss",
|
|
18
13
|
"fonts",
|
|
19
|
-
"dist"
|
|
14
|
+
"dist",
|
|
15
|
+
"!dist/**/__tests__",
|
|
16
|
+
"!dist/**/*.test.*",
|
|
17
|
+
"!dist/**/*.map"
|
|
20
18
|
],
|
|
21
19
|
"exports": {
|
|
22
20
|
".": {
|
package/scss/_components.scss
CHANGED
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
|
|
83
83
|
.btn-danger {
|
|
84
84
|
// White-on-red destructive look via the --wui-danger-strong token: white fails AA on the
|
|
85
|
-
// brighter danger
|
|
85
|
+
// brighter danger fill (#E82646 → 4.38:1), so the button uses the
|
|
86
86
|
// deepened fill (5.80:1) that carries white cleanly. Token-driven so a rebrand tracks it;
|
|
87
87
|
// the brighter --wui-danger stays for badges/dots that never carry white text.
|
|
88
88
|
--bs-btn-color: #fff;
|
package/scss/_tokens.scss
CHANGED
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
// combobox/phone/date/number wrappers) — a touch lighter than --wui-bg-muted so fields read
|
|
42
42
|
// as their own surface. Change here to restyle every field's background at once.
|
|
43
43
|
--wui-field-bg: #F9FBFC;
|
|
44
|
+
// Resting and hover border of every input-like control. They clear WCAG 1.4.11's 3:1
|
|
45
|
+
// against the field fill and the surface, so a field's edge is visible without focus.
|
|
46
|
+
--wui-field-border: #80899F;
|
|
47
|
+
--wui-field-border-hover: #687088;
|
|
44
48
|
--wui-border-light: #EBEDF3;
|
|
45
49
|
--wui-border-soft: #F4F6F8;
|
|
46
50
|
// The unfilled part of a progress bar / meter. Darker than every surface it can sit on
|
|
@@ -144,16 +148,16 @@
|
|
|
144
148
|
// Shared by the portal (aliased to --color-*) and marketing alerts/badges.
|
|
145
149
|
--wui-info-text: #1460ba;
|
|
146
150
|
--wui-info-active: #056EE9;
|
|
147
|
-
--wui-info: #
|
|
151
|
+
--wui-info: #056EE9;
|
|
148
152
|
--wui-info-50: #8DC2FF;
|
|
149
153
|
--wui-info-30: #BBDBFF;
|
|
150
154
|
--wui-info-20: #D1E6FF;
|
|
151
155
|
--wui-info-10: #E9F3FF;
|
|
152
156
|
--wui-info-5: #F3F9FF;
|
|
153
157
|
|
|
154
|
-
// `-text` variants exist because the status colours are FILLS. #
|
|
158
|
+
// `-text` variants exist because the status colours are FILLS. #E82646 and #04B440
|
|
155
159
|
// are correct on a button or a badge, and both fail AA as text on a light surface
|
|
156
|
-
// (
|
|
160
|
+
// (4.4:1 and 2.8:1) — which is how a validation error message, of all things, came
|
|
157
161
|
// to be unreadable. Darkening the base tokens would change every red button and
|
|
158
162
|
// green badge in the system, so text gets its own value and the fills keep theirs.
|
|
159
163
|
--wui-success-text: #0e7531;
|
|
@@ -163,7 +167,7 @@
|
|
|
163
167
|
// the other tokens so buttons/badges keep the vibrant fill.
|
|
164
168
|
--wui-success-strong: #0e7531;
|
|
165
169
|
--wui-success-active: #04B440;
|
|
166
|
-
--wui-success: #
|
|
170
|
+
--wui-success: #04B440;
|
|
167
171
|
--wui-success-50: #8BE3A9;
|
|
168
172
|
--wui-success-30: #BAEECC;
|
|
169
173
|
--wui-success-20: #D1F4DD;
|
|
@@ -172,7 +176,7 @@
|
|
|
172
176
|
|
|
173
177
|
--wui-warning-text: #876100;
|
|
174
178
|
--wui-warning-active: #DFA000;
|
|
175
|
-
--wui-warning: #
|
|
179
|
+
--wui-warning: #DFA000;
|
|
176
180
|
--wui-warning-50: #FBD880;
|
|
177
181
|
--wui-warning-30: #FDE8B3;
|
|
178
182
|
--wui-warning-20: #FDEFCC;
|
|
@@ -192,7 +196,7 @@
|
|
|
192
196
|
--wui-danger-strong: #C81340;
|
|
193
197
|
--wui-danger-strong-hover: #AB1036;
|
|
194
198
|
--wui-danger-active: #E82646;
|
|
195
|
-
--wui-danger: #
|
|
199
|
+
--wui-danger: #E82646;
|
|
196
200
|
--wui-danger-50: #FC94AD;
|
|
197
201
|
--wui-danger-30: #FDBFCE;
|
|
198
202
|
--wui-danger-20: #FED4DE;
|
|
@@ -253,6 +257,9 @@
|
|
|
253
257
|
--wui-dark-bg-surface: #181b23;
|
|
254
258
|
--wui-dark-border: #2a2f3a;
|
|
255
259
|
--wui-dark-border-strong:#3a414f;
|
|
260
|
+
// Field borders on the dark fills: 3:1 or better against the dark field fill and surface.
|
|
261
|
+
--wui-dark-field-border: #6E7586;
|
|
262
|
+
--wui-dark-field-border-hover: #8a90a0;
|
|
256
263
|
// Lighter than the dark page, surface and muted fill, so the empty track shows on all three.
|
|
257
264
|
--wui-dark-progress-track: #323845;
|
|
258
265
|
--wui-dark-text: #e6e8ee;
|
|
@@ -336,6 +343,11 @@
|
|
|
336
343
|
--wui-z-popover: 1600; // same rung as --wui-z-menu (above modal)
|
|
337
344
|
--wui-z-tooltip: 1650;
|
|
338
345
|
--wui-z-toast: 1700;
|
|
346
|
+
|
|
347
|
+
// The weekday every calendar's week starts on: the date picker, the date range and the event
|
|
348
|
+
// calendar. 0 = Sunday, 1 = Monday, through 6 = Saturday. A product sets it once here, a page or
|
|
349
|
+
// a section can set it on an ancestor, and a control's own first-day attribute wins over both.
|
|
350
|
+
--wui-first-day: 1;
|
|
339
351
|
}
|
|
340
352
|
|
|
341
353
|
// Bootstrap md / xl (not invented px)
|
package/scss/_variables.scss
CHANGED
|
@@ -20,6 +20,8 @@ $primary: #4F46E5 !default;
|
|
|
20
20
|
// second brand colour should use a custom utility or token — do not repurpose
|
|
21
21
|
// $secondary without a coordinated migration.
|
|
22
22
|
$secondary: #4B5675 !default;
|
|
23
|
+
// The status colours match the base --wui-success/-info/-warning/-danger tokens, so a
|
|
24
|
+
// Bootstrap utility (.bg-success, .btn-info, --bs-danger) paints the same fill as the library.
|
|
23
25
|
$success: #04B440 !default;
|
|
24
26
|
$info: #056EE9 !default;
|
|
25
27
|
$warning: #DFA000 !default;
|
package/scss/_wui-aliases.scss
CHANGED
|
@@ -18,12 +18,20 @@
|
|
|
18
18
|
--color-border: var(--wui-border-light);
|
|
19
19
|
--color-border-light: var(--wui-border-soft);
|
|
20
20
|
--color-border-strong: var(--wui-text-5);
|
|
21
|
+
// The resting and hover border of an input-like control (3:1 against the field and surface).
|
|
22
|
+
// Decorative card and table borders stay on --color-border.
|
|
23
|
+
--color-field-border: var(--wui-field-border);
|
|
24
|
+
--color-field-border-hover: var(--wui-field-border-hover);
|
|
21
25
|
--color-progress-track: var(--wui-progress-track);
|
|
22
26
|
// Label text inside a progress bar fill.
|
|
23
27
|
--color-progress-label: var(--wui-bg-light);
|
|
24
28
|
// Ink on a solid status fill (success, warning, danger, info): near-black in both modes, since
|
|
25
29
|
// white fails AA on the bright fills.
|
|
26
30
|
--color-on-status-fill: #0F0F0F;
|
|
31
|
+
// Ink on a DEEP status fill (the -text tokens, used as a fill the way primary is): white in
|
|
32
|
+
// light mode, where those shades measure 5.5 to 6.2:1; near-black in dark mode, where -text is
|
|
33
|
+
// the bright fill.
|
|
34
|
+
--color-on-status-strong: #FFFFFF;
|
|
27
35
|
|
|
28
36
|
// Text ramp
|
|
29
37
|
--color-text: var(--wui-text-heading);
|
|
@@ -32,7 +40,9 @@
|
|
|
32
40
|
// A dark-ink glyph such as Bootstrap's .btn-close needs no filter on a light surface.
|
|
33
41
|
--color-close-filter: none;
|
|
34
42
|
// The border of a focused / open / active control (input, select, OTP slot, dropzone).
|
|
35
|
-
|
|
43
|
+
// It is the only focus cue on a field, so it must clear 3:1 against the field and surface
|
|
44
|
+
// (WCAG 1.4.11): the full primary, not a tint.
|
|
45
|
+
--color-focus-border: var(--wui-primary);
|
|
36
46
|
--color-text-muted: var(--wui-text-2);
|
|
37
47
|
--color-text-subtle: var(--wui-text-3);
|
|
38
48
|
|
|
@@ -153,6 +163,8 @@
|
|
|
153
163
|
--color-border: var(--wui-dark-border);
|
|
154
164
|
--color-border-light: color-mix(in srgb, var(--wui-dark-border) 50%, transparent);
|
|
155
165
|
--color-border-strong: var(--wui-dark-border-strong);
|
|
166
|
+
--color-field-border: var(--wui-dark-field-border);
|
|
167
|
+
--color-field-border-hover: var(--wui-dark-field-border-hover);
|
|
156
168
|
--color-progress-track: var(--wui-dark-progress-track);
|
|
157
169
|
// Same near-black as --color-primary-text below: 4.97:1 or better on every bright fill.
|
|
158
170
|
--color-progress-label: #0F0F0F;
|
|
@@ -199,29 +211,33 @@
|
|
|
199
211
|
// Dark mode primary text: #fff on #6B83EC measures 3.5:1, below WCAG AA (4.5:1).
|
|
200
212
|
// Map to a near-black for safe contrast (6.9:1 on --wui-dark-primary) when text sits on primary fill.
|
|
201
213
|
--color-primary-text: #0F0F0F;
|
|
214
|
+
--color-on-status-strong: #0F0F0F;
|
|
202
215
|
|
|
203
|
-
// On a dark surface the
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
--color-
|
|
208
|
-
--color-
|
|
209
|
-
--color-
|
|
216
|
+
// On a dark surface the darkened `-text` values would sink into the background, so dark
|
|
217
|
+
// mode builds text from the fill instead, lifted with 25% white: the info and danger fills
|
|
218
|
+
// alone reach only 3.1:1 and 3.4:1 on the muted fill, and the lift clears 4.5:1 on every
|
|
219
|
+
// dark surface for all four tones.
|
|
220
|
+
--color-success-text: color-mix(in srgb, var(--wui-success) 75%, white);
|
|
221
|
+
--color-danger-text: color-mix(in srgb, var(--wui-danger) 75%, white);
|
|
222
|
+
--color-warning-text: color-mix(in srgb, var(--wui-warning) 75%, white);
|
|
223
|
+
--color-info-text: color-mix(in srgb, var(--wui-info) 75%, white);
|
|
210
224
|
|
|
211
225
|
// Text ON a soft tint (an alert heading). The bright tone alone falls under WCAG AA on its own
|
|
212
226
|
// 18% tint over the dark page (info and danger reach only ~3.8:1), so it is lifted with 30%
|
|
213
227
|
// white: every tone then clears 4.5:1 on the dark page, surface and muted fill.
|
|
214
|
-
--color-success-text-on-soft: color-mix(in srgb, var(--wui-success)
|
|
215
|
-
--color-danger-text-on-soft: color-mix(in srgb, var(--wui-danger)
|
|
216
|
-
--color-warning-text-on-soft: color-mix(in srgb, var(--wui-warning)
|
|
217
|
-
--color-info-text-on-soft: color-mix(in srgb, var(--wui-info)
|
|
228
|
+
--color-success-text-on-soft: color-mix(in srgb, var(--wui-success) 65%, white);
|
|
229
|
+
--color-danger-text-on-soft: color-mix(in srgb, var(--wui-danger) 65%, white);
|
|
230
|
+
--color-warning-text-on-soft: color-mix(in srgb, var(--wui-warning) 65%, white);
|
|
231
|
+
--color-info-text-on-soft: color-mix(in srgb, var(--wui-info) 65%, white);
|
|
218
232
|
|
|
219
233
|
// Light mode maps -strong to deep AA fills; on dark surfaces those sink into the page.
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
--color-
|
|
224
|
-
--color-
|
|
234
|
+
// Dark mode uses the lifted -text tone, since -strong is a fill that carries near-black text
|
|
235
|
+
// (progress label, bell count): the bare danger and info fills reach only 4.4:1 and 4.0:1
|
|
236
|
+
// under that ink, the lifted ones 5.7:1 or better.
|
|
237
|
+
--color-success-strong: var(--color-success-text);
|
|
238
|
+
--color-danger-strong: var(--color-danger-text);
|
|
239
|
+
--color-info-strong: var(--color-info-text);
|
|
240
|
+
--color-warning-strong: var(--color-warning-text);
|
|
225
241
|
|
|
226
242
|
--color-success-soft: color-mix(in srgb, var(--wui-success) 18%, transparent);
|
|
227
243
|
--color-warning-soft: color-mix(in srgb, var(--wui-warning) 18%, transparent);
|
package/scss/wui/_choice.scss
CHANGED
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
// Not while open — an open control keeps its active (primary) border, not the grey hover one.
|
|
245
245
|
// Not while invalid — an errored control (aria-invalid mirrored from the host) holds its red
|
|
246
246
|
// border on hover rather than reverting to the grey hover one.
|
|
247
|
-
border-color: var(--color-border-
|
|
247
|
+
border-color: var(--color-field-border-hover);
|
|
248
248
|
}
|
|
249
249
|
.search-select-control.open {
|
|
250
250
|
// White fill + the active/focus border, matching a focused text input (which lifts off the
|
|
@@ -414,7 +414,7 @@
|
|
|
414
414
|
margin: 4px;
|
|
415
415
|
padding: 0 12px;
|
|
416
416
|
height: 40px;
|
|
417
|
-
border: 1px solid var(--color-border);
|
|
417
|
+
border: 1px solid var(--color-field-border);
|
|
418
418
|
border-radius: var(--radius);
|
|
419
419
|
// AppInput's field model: muted resting fill that lifts to a clean surface on focus.
|
|
420
420
|
background: var(--color-field-bg);
|
|
@@ -426,7 +426,7 @@
|
|
|
426
426
|
// Hover and focus follow AppInput, as the phone country search does: a stronger border on hover,
|
|
427
427
|
// then a clean surface fill + soft primary border on focus.
|
|
428
428
|
.search-select-search:hover:not(:focus-within) {
|
|
429
|
-
border-color: var(--color-border-
|
|
429
|
+
border-color: var(--color-field-border-hover);
|
|
430
430
|
}
|
|
431
431
|
.search-select-search:focus-within {
|
|
432
432
|
background: var(--color-surface);
|
|
@@ -581,7 +581,7 @@
|
|
|
581
581
|
wui-datepicker:not([aria-invalid="true"]) .datepicker:not(.open) .datepicker-trigger:focus:not(:focus-visible),
|
|
582
582
|
wui-date-range:not([aria-invalid="true"]) .daterange:not(.open) .daterange-trigger:focus:not(:focus-visible) {
|
|
583
583
|
background-color: var(--color-field-bg);
|
|
584
|
-
border-color: var(--color-border);
|
|
584
|
+
border-color: var(--color-field-border);
|
|
585
585
|
}
|
|
586
586
|
// Portalled to <body> and fixed-positioned from JS so a modal's
|
|
587
587
|
// overflow:hidden can't clip it; top/left come from inline styles. z-index
|
|
@@ -1003,7 +1003,7 @@ button.datepicker-month:hover {
|
|
|
1003
1003
|
align-items: center;
|
|
1004
1004
|
width: 100%;
|
|
1005
1005
|
height: var(--wui-control-height);
|
|
1006
|
-
border: 1px solid var(--color-border);
|
|
1006
|
+
border: 1px solid var(--color-field-border);
|
|
1007
1007
|
// Match AppInput's field-radius ladder exactly (18px md), not the generic --radius (10px).
|
|
1008
1008
|
border-radius: var(--wui-field-radius);
|
|
1009
1009
|
// Match AppInput exactly: muted resting fill that lifts to a clean surface on focus.
|
|
@@ -1024,7 +1024,7 @@ button.datepicker-month:hover {
|
|
|
1024
1024
|
wui-phone:not([aria-invalid="true"])
|
|
1025
1025
|
.phone-input-wrap:hover:not(:focus-within):not(:has(> .input.error)):not(:has(> .input.is-invalid)):not(:has(> .input[aria-invalid="true"])) {
|
|
1026
1026
|
background: var(--color-field-bg);
|
|
1027
|
-
border-color: var(--color-border-
|
|
1027
|
+
border-color: var(--color-field-border-hover);
|
|
1028
1028
|
}
|
|
1029
1029
|
// Match AppInput's focus: clean surface fill + a soft primary border.
|
|
1030
1030
|
.app-phone-number-input .phone-input-wrap:focus-within {
|
|
@@ -1238,7 +1238,7 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
|
|
|
1238
1238
|
width: 100%;
|
|
1239
1239
|
height: 40px;
|
|
1240
1240
|
padding: 0 12px 0 36px;
|
|
1241
|
-
border: 1px solid var(--color-border);
|
|
1241
|
+
border: 1px solid var(--color-field-border);
|
|
1242
1242
|
border-radius: var(--radius);
|
|
1243
1243
|
font-size: 14px;
|
|
1244
1244
|
color: var(--color-text);
|
|
@@ -1248,7 +1248,7 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
|
|
|
1248
1248
|
}
|
|
1249
1249
|
.dropdown-search-input:hover:not(:focus) {
|
|
1250
1250
|
background: var(--color-field-bg);
|
|
1251
|
-
border-color: var(--color-border-
|
|
1251
|
+
border-color: var(--color-field-border-hover);
|
|
1252
1252
|
}
|
|
1253
1253
|
// Border is the focus cue everywhere else in the system — no glow ring here.
|
|
1254
1254
|
// AppInput's exact focus: clean surface fill + its soft primary border token.
|
package/scss/wui/_controls.scss
CHANGED
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
height: var(--wui-control-height);
|
|
302
302
|
padding: 12px;
|
|
303
303
|
border-radius: var(--wui-field-radius);
|
|
304
|
-
border: 1px solid var(--color-border);
|
|
304
|
+
border: 1px solid var(--color-field-border);
|
|
305
305
|
background: var(--color-field-bg);
|
|
306
306
|
font-size: 14px;
|
|
307
307
|
line-height: 1.5;
|
|
@@ -359,7 +359,7 @@ textarea.form-control.autosize {
|
|
|
359
359
|
.select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
|
|
360
360
|
.textarea:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error) {
|
|
361
361
|
background-color: var(--color-field-bg);
|
|
362
|
-
border-color: var(--color-border-
|
|
362
|
+
border-color: var(--color-field-border-hover);
|
|
363
363
|
}
|
|
364
364
|
.form-control:focus,
|
|
365
365
|
.form-select:focus,
|
|
@@ -462,7 +462,10 @@ textarea.form-control.autosize {
|
|
|
462
462
|
.input[readonly],
|
|
463
463
|
.select[readonly],
|
|
464
464
|
.textarea[readonly] {
|
|
465
|
-
|
|
465
|
+
// The light decorative border and the muted fill, never the field border, so a read-only
|
|
466
|
+
// value never looks typeable.
|
|
467
|
+
background: var(--color-bg-muted);
|
|
468
|
+
border-color: var(--color-border);
|
|
466
469
|
color: var(--color-text-muted);
|
|
467
470
|
cursor: default;
|
|
468
471
|
}
|
|
@@ -810,7 +813,7 @@ $wui-field-error-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/
|
|
|
810
813
|
display: flex;
|
|
811
814
|
align-items: stretch;
|
|
812
815
|
width: 100%;
|
|
813
|
-
border: 1px solid var(--color-border);
|
|
816
|
+
border: 1px solid var(--color-field-border);
|
|
814
817
|
border-radius: var(--wui-field-radius);
|
|
815
818
|
// Soft-filled at rest, white on focus — one shared fill for the whole control so the
|
|
816
819
|
// prefix/suffix and the input body are always the SAME colour combination as the field.
|
|
@@ -820,7 +823,7 @@ $wui-field-error-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/
|
|
|
820
823
|
background-color 0.12s ease;
|
|
821
824
|
}
|
|
822
825
|
.input-affixed:hover:not(:focus-within) {
|
|
823
|
-
border-color: var(--color-border-
|
|
826
|
+
border-color: var(--color-field-border-hover);
|
|
824
827
|
}
|
|
825
828
|
.input-affixed:focus-within {
|
|
826
829
|
background: var(--color-surface);
|
|
@@ -1098,7 +1101,7 @@ wui-select[compact] {
|
|
|
1098
1101
|
.input-with-unit {
|
|
1099
1102
|
display: flex;
|
|
1100
1103
|
align-items: stretch;
|
|
1101
|
-
border: 1px solid var(--color-border);
|
|
1104
|
+
border: 1px solid var(--color-field-border);
|
|
1102
1105
|
border-radius: var(--wui-field-radius);
|
|
1103
1106
|
// Soft-filled at rest, white on focus — the numeric input and its unit pill share the
|
|
1104
1107
|
// one wrapper fill, same colour combination as every other field.
|
|
@@ -1109,7 +1112,7 @@ wui-select[compact] {
|
|
|
1109
1112
|
overflow: hidden;
|
|
1110
1113
|
}
|
|
1111
1114
|
.input-with-unit:hover:not(:focus-within) {
|
|
1112
|
-
border-color: var(--color-border-
|
|
1115
|
+
border-color: var(--color-field-border-hover);
|
|
1113
1116
|
}
|
|
1114
1117
|
.input-with-unit:focus-within {
|
|
1115
1118
|
background: var(--color-surface);
|
|
@@ -1168,7 +1171,7 @@ wui-select[compact] {
|
|
|
1168
1171
|
.num-wrap {
|
|
1169
1172
|
display: flex;
|
|
1170
1173
|
align-items: stretch;
|
|
1171
|
-
border: 1px solid var(--color-border);
|
|
1174
|
+
border: 1px solid var(--color-field-border);
|
|
1172
1175
|
// Field radius ladder (matches AppInput): md 18px; sm/lg step below.
|
|
1173
1176
|
border-radius: var(--wui-field-radius);
|
|
1174
1177
|
// Match AppInput exactly: muted resting fill that lifts to a clean surface on focus.
|
|
@@ -1182,7 +1185,7 @@ wui-select[compact] {
|
|
|
1182
1185
|
// reverting to the grey hover one (matches AppInput, whose hover rule excludes the error state).
|
|
1183
1186
|
.num-wrap:hover:not(:focus-within):not(:has(.num-input.error)):not(:has(.num-input.is-invalid)):not(:has(.num-input[aria-invalid="true"])) {
|
|
1184
1187
|
background: var(--color-field-bg);
|
|
1185
|
-
border-color: var(--color-border-
|
|
1188
|
+
border-color: var(--color-field-border-hover);
|
|
1186
1189
|
}
|
|
1187
1190
|
.num-wrap:focus-within {
|
|
1188
1191
|
background: var(--color-surface);
|
|
@@ -1547,7 +1550,7 @@ wui-otp {
|
|
|
1547
1550
|
height: var(--wui-control-height);
|
|
1548
1551
|
// Colour model matches AppInput exactly: muted resting fill + soft border, same
|
|
1549
1552
|
// field radius. State rules below mirror AppInput's hover/focus/invalid/disabled.
|
|
1550
|
-
border: 1px solid var(--color-border);
|
|
1553
|
+
border: 1px solid var(--color-field-border);
|
|
1551
1554
|
border-radius: var(--wui-field-radius);
|
|
1552
1555
|
background: var(--color-field-bg);
|
|
1553
1556
|
font-size: 18px;
|
|
@@ -1561,7 +1564,7 @@ wui-otp {
|
|
|
1561
1564
|
// Hover — the whole field lifts its border to strong (AppInput hover), but not while a
|
|
1562
1565
|
// slot is active (focus wins) or the field is disabled.
|
|
1563
1566
|
.otp:hover:not(:focus-within):not(:has(.otp-field:disabled)) .otp-slot {
|
|
1564
|
-
border-color: var(--color-border-
|
|
1567
|
+
border-color: var(--color-field-border-hover);
|
|
1565
1568
|
}
|
|
1566
1569
|
// The caret cannot be seen through a transparent input, so the ACTIVE box carries the
|
|
1567
1570
|
// affordance instead — derived from selectionStart. Matches AppInput's focus: clean
|
package/scss/wui/_data.scss
CHANGED
|
@@ -701,6 +701,45 @@
|
|
|
701
701
|
border-radius: 999px;
|
|
702
702
|
}
|
|
703
703
|
|
|
704
|
+
// A table wider than its scroller fades out at each edge it continues past, so a cut-off column
|
|
705
|
+
// reads as "more this way". scrollEdges.js (ui-elements) keeps the two data-wui-overflow-*
|
|
706
|
+
// attributes current on scroll and resize. The fade is a mask on the scroller, because a shadow
|
|
707
|
+
// paints under the opaque cells. A mask also hides what a descendant floats outside the box, so
|
|
708
|
+
// it stands aside while a menu or picker inside the table is open (an expanded row, which has no
|
|
709
|
+
// popup, keeps it). A pinned first column never
|
|
710
|
+
// fades at the start: it is the part that stays put.
|
|
711
|
+
:is(.table-wrap, .table-responsive, [class*="table-responsive-"]) {
|
|
712
|
+
--wui-overflow-fade-start: 0px;
|
|
713
|
+
--wui-overflow-fade-end: 0px;
|
|
714
|
+
}
|
|
715
|
+
:is(.table-wrap, .table-responsive, [class*="table-responsive-"])[data-wui-overflow-start] {
|
|
716
|
+
--wui-overflow-fade-start: 32px;
|
|
717
|
+
}
|
|
718
|
+
:is(.table-wrap, .table-responsive, [class*="table-responsive-"])[data-wui-overflow-end] {
|
|
719
|
+
--wui-overflow-fade-end: 32px;
|
|
720
|
+
}
|
|
721
|
+
.table-wrap[data-wui-overflow-start]:has(> .wui-table-sticky-first) {
|
|
722
|
+
--wui-overflow-fade-start: 0px;
|
|
723
|
+
}
|
|
724
|
+
:is(.table-wrap, .table-responsive, [class*="table-responsive-"]):is([data-wui-overflow-start], [data-wui-overflow-end]):not(:has([aria-haspopup][aria-expanded="true"], .dropdown-menu.show)) {
|
|
725
|
+
mask-image: linear-gradient(
|
|
726
|
+
90deg,
|
|
727
|
+
transparent,
|
|
728
|
+
#000 var(--wui-overflow-fade-start),
|
|
729
|
+
#000 calc(100% - var(--wui-overflow-fade-end)),
|
|
730
|
+
transparent
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
:is(.table-wrap, .table-responsive, [class*="table-responsive-"]):dir(rtl):is([data-wui-overflow-start], [data-wui-overflow-end]):not(:has([aria-haspopup][aria-expanded="true"], .dropdown-menu.show)) {
|
|
734
|
+
mask-image: linear-gradient(
|
|
735
|
+
270deg,
|
|
736
|
+
transparent,
|
|
737
|
+
#000 var(--wui-overflow-fade-start),
|
|
738
|
+
#000 calc(100% - var(--wui-overflow-fade-end)),
|
|
739
|
+
transparent
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
|
|
704
743
|
// The identity/name column — a STABLE hook, because position is not one.
|
|
705
744
|
//
|
|
706
745
|
// The library owns .wui-select-cell, so a ledger's first cell is the 44px checkbox when
|
package/scss/wui/_flow.scss
CHANGED
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
// eyebrow, filled rail). Unset, completed steps follow the accent.
|
|
26
26
|
// --wui-step-size compact/vertical badge diameter (default 28px)
|
|
27
27
|
// --wui-step-badge-size icons-variant badge diameter (default 56px)
|
|
28
|
+
// --wui-step-journey-size journey badge diameter (default 40px)
|
|
29
|
+
// --wui-step-number-font the step number in a badge (default 12px; journey 13px, icons 22px)
|
|
30
|
+
// --wui-step-label-font the step label (default 13px; journey 16px, icons 15px)
|
|
31
|
+
// The `.wui-step-size-sm` / `.wui-step-size-lg` classes (end of this block) set these together.
|
|
28
32
|
// Every variant defaults to the brand primary — active, done and rail share one accent
|
|
29
33
|
// (no multi-colour). Colour variety is opt-in: a `.wui-step-tone-*` class or a var override.
|
|
30
34
|
// ============================================================================
|
|
@@ -76,6 +80,15 @@
|
|
|
76
80
|
.step.done + .step::before {
|
|
77
81
|
background: var(--wui-step-done-accent, var(--wui-step-accent, var(--color-primary)));
|
|
78
82
|
}
|
|
83
|
+
// The active circle's 4px ring would swallow the 4px gap, so both connectors touching the
|
|
84
|
+
// active step start 4px further out and keep the same gap from the ring's edge.
|
|
85
|
+
.step.active + .step::before {
|
|
86
|
+
left: calc(-50% + var(--wui-step-size, 28px) / 2 + 8px);
|
|
87
|
+
}
|
|
88
|
+
.step.active + .step::before,
|
|
89
|
+
.step.active::before {
|
|
90
|
+
right: calc(50% + var(--wui-step-size, 28px) / 2 + 8px);
|
|
91
|
+
}
|
|
79
92
|
.step-circle {
|
|
80
93
|
position: relative;
|
|
81
94
|
z-index: 1;
|
|
@@ -87,7 +100,7 @@
|
|
|
87
100
|
border: 1.5px solid var(--color-border);
|
|
88
101
|
border-radius: 999px;
|
|
89
102
|
background: var(--color-surface);
|
|
90
|
-
font-size: 12px;
|
|
103
|
+
font-size: var(--wui-step-number-font, 12px);
|
|
91
104
|
font-weight: 600;
|
|
92
105
|
color: var(--color-text-subtle);
|
|
93
106
|
}
|
|
@@ -106,7 +119,7 @@
|
|
|
106
119
|
}
|
|
107
120
|
.step-label {
|
|
108
121
|
max-width: 130px;
|
|
109
|
-
font-size: 13px;
|
|
122
|
+
font-size: var(--wui-step-label-font, 13px);
|
|
110
123
|
font-weight: 500;
|
|
111
124
|
line-height: 1.25;
|
|
112
125
|
color: var(--color-text-subtle);
|
|
@@ -210,11 +223,11 @@ button.step.done:focus-visible .step-circle {
|
|
|
210
223
|
content: none;
|
|
211
224
|
}
|
|
212
225
|
.stepper-journey .step-circle {
|
|
213
|
-
width: 40px;
|
|
214
|
-
height: 40px;
|
|
226
|
+
width: var(--wui-step-journey-size, 40px);
|
|
227
|
+
height: var(--wui-step-journey-size, 40px);
|
|
215
228
|
border: none;
|
|
216
229
|
background: var(--color-bg-muted);
|
|
217
|
-
font-size: 13px;
|
|
230
|
+
font-size: var(--wui-step-number-font, 13px);
|
|
218
231
|
font-weight: 700;
|
|
219
232
|
transition:
|
|
220
233
|
background 0.2s ease,
|
|
@@ -265,7 +278,7 @@ button.step.done:focus-visible .step-circle {
|
|
|
265
278
|
.stepper-journey .step-label {
|
|
266
279
|
max-width: none;
|
|
267
280
|
margin-top: 8px;
|
|
268
|
-
font-size: 16px;
|
|
281
|
+
font-size: var(--wui-step-label-font, 16px);
|
|
269
282
|
line-height: 1.3;
|
|
270
283
|
white-space: nowrap;
|
|
271
284
|
overflow: hidden;
|
|
@@ -406,7 +419,7 @@ button.step.done:focus-visible .step-circle {
|
|
|
406
419
|
border: none;
|
|
407
420
|
background: var(--color-bg-muted);
|
|
408
421
|
color: var(--color-text-subtle);
|
|
409
|
-
font-size: 22px;
|
|
422
|
+
font-size: var(--wui-step-number-font, 22px);
|
|
410
423
|
transition:
|
|
411
424
|
background 0.2s ease,
|
|
412
425
|
color 0.2s ease,
|
|
@@ -457,7 +470,7 @@ button.step.done:focus-visible .step-circle {
|
|
|
457
470
|
}
|
|
458
471
|
.stepper-icons .step-label {
|
|
459
472
|
max-width: 150px;
|
|
460
|
-
font-size: 15px;
|
|
473
|
+
font-size: var(--wui-step-label-font, 15px);
|
|
461
474
|
font-weight: 600;
|
|
462
475
|
color: var(--color-text-subtle);
|
|
463
476
|
}
|
|
@@ -534,28 +547,29 @@ button.step.done:focus-visible .step-circle {
|
|
|
534
547
|
--wui-step-soft: var(--color-primary-soft);
|
|
535
548
|
--wui-step-soft-fg: var(--color-primary);
|
|
536
549
|
}
|
|
537
|
-
//
|
|
550
|
+
// Like primary, each tone fills with its deep shade (the -text token) under white ink in light mode,
|
|
551
|
+
// and with the bright fill under near-black ink in dark mode; both pairs clear AA.
|
|
538
552
|
.wui-step-tone-success {
|
|
539
|
-
--wui-step-accent: var(--color-success);
|
|
540
|
-
--wui-step-accent-fg: var(--color-on-status-
|
|
553
|
+
--wui-step-accent: var(--color-success-text);
|
|
554
|
+
--wui-step-accent-fg: var(--color-on-status-strong);
|
|
541
555
|
--wui-step-soft: var(--color-success-soft);
|
|
542
556
|
--wui-step-soft-fg: var(--color-success-text);
|
|
543
557
|
}
|
|
544
558
|
.wui-step-tone-warning {
|
|
545
|
-
--wui-step-accent: var(--color-warning);
|
|
546
|
-
--wui-step-accent-fg: var(--color-on-status-
|
|
559
|
+
--wui-step-accent: var(--color-warning-text);
|
|
560
|
+
--wui-step-accent-fg: var(--color-on-status-strong);
|
|
547
561
|
--wui-step-soft: var(--color-warning-soft);
|
|
548
562
|
--wui-step-soft-fg: var(--color-warning-text);
|
|
549
563
|
}
|
|
550
564
|
.wui-step-tone-danger {
|
|
551
|
-
--wui-step-accent: var(--color-danger);
|
|
552
|
-
--wui-step-accent-fg: var(--color-on-status-
|
|
565
|
+
--wui-step-accent: var(--color-danger-text);
|
|
566
|
+
--wui-step-accent-fg: var(--color-on-status-strong);
|
|
553
567
|
--wui-step-soft: var(--color-danger-soft);
|
|
554
568
|
--wui-step-soft-fg: var(--color-danger-text);
|
|
555
569
|
}
|
|
556
570
|
.wui-step-tone-info {
|
|
557
|
-
--wui-step-accent: var(--color-info);
|
|
558
|
-
--wui-step-accent-fg: var(--color-on-status-
|
|
571
|
+
--wui-step-accent: var(--color-info-text);
|
|
572
|
+
--wui-step-accent-fg: var(--color-on-status-strong);
|
|
559
573
|
--wui-step-soft: var(--color-info-soft);
|
|
560
574
|
--wui-step-soft-fg: var(--color-info-text);
|
|
561
575
|
}
|
|
@@ -572,30 +586,70 @@ button.step.done:focus-visible .step-circle {
|
|
|
572
586
|
--wui-step-done-soft-fg: var(--color-primary);
|
|
573
587
|
}
|
|
574
588
|
.wui-step-done-tone-success {
|
|
575
|
-
--wui-step-done-accent: var(--color-success);
|
|
576
|
-
--wui-step-done-accent-fg: var(--color-on-status-
|
|
589
|
+
--wui-step-done-accent: var(--color-success-text);
|
|
590
|
+
--wui-step-done-accent-fg: var(--color-on-status-strong);
|
|
577
591
|
--wui-step-done-soft: var(--color-success-soft);
|
|
578
592
|
--wui-step-done-soft-fg: var(--color-success-text);
|
|
579
593
|
}
|
|
580
594
|
.wui-step-done-tone-warning {
|
|
581
|
-
--wui-step-done-accent: var(--color-warning);
|
|
582
|
-
--wui-step-done-accent-fg: var(--color-on-status-
|
|
595
|
+
--wui-step-done-accent: var(--color-warning-text);
|
|
596
|
+
--wui-step-done-accent-fg: var(--color-on-status-strong);
|
|
583
597
|
--wui-step-done-soft: var(--color-warning-soft);
|
|
584
598
|
--wui-step-done-soft-fg: var(--color-warning-text);
|
|
585
599
|
}
|
|
586
600
|
.wui-step-done-tone-danger {
|
|
587
|
-
--wui-step-done-accent: var(--color-danger);
|
|
588
|
-
--wui-step-done-accent-fg: var(--color-on-status-
|
|
601
|
+
--wui-step-done-accent: var(--color-danger-text);
|
|
602
|
+
--wui-step-done-accent-fg: var(--color-on-status-strong);
|
|
589
603
|
--wui-step-done-soft: var(--color-danger-soft);
|
|
590
604
|
--wui-step-done-soft-fg: var(--color-danger-text);
|
|
591
605
|
}
|
|
592
606
|
.wui-step-done-tone-info {
|
|
593
|
-
--wui-step-done-accent: var(--color-info);
|
|
594
|
-
--wui-step-done-accent-fg: var(--color-on-status-
|
|
607
|
+
--wui-step-done-accent: var(--color-info-text);
|
|
608
|
+
--wui-step-done-accent-fg: var(--color-on-status-strong);
|
|
595
609
|
--wui-step-done-soft: var(--color-info-soft);
|
|
596
610
|
--wui-step-done-soft-fg: var(--color-info-text);
|
|
597
611
|
}
|
|
598
612
|
|
|
613
|
+
// Size presets: scale the badge, its number and the label together, on every variant. Same
|
|
614
|
+
// placement rules as the tone presets: on the stepper or any ancestor (the wizard host). Medium is
|
|
615
|
+
// the unset default above. The number and label fonts are per-variant here, so these rules name
|
|
616
|
+
// each variant; one class sets them all.
|
|
617
|
+
// ----------------------------------------------------------------------------
|
|
618
|
+
.wui-step-size-sm {
|
|
619
|
+
--wui-step-size: 22px;
|
|
620
|
+
--wui-step-badge-size: 44px;
|
|
621
|
+
--wui-step-journey-size: 32px;
|
|
622
|
+
--wui-step-number-font: 11px;
|
|
623
|
+
--wui-step-label-font: 12px;
|
|
624
|
+
}
|
|
625
|
+
.wui-step-size-sm .stepper-journey,
|
|
626
|
+
.wui-step-size-sm.stepper-journey {
|
|
627
|
+
--wui-step-number-font: 12px;
|
|
628
|
+
--wui-step-label-font: 14px;
|
|
629
|
+
}
|
|
630
|
+
.wui-step-size-sm .stepper-icons,
|
|
631
|
+
.wui-step-size-sm.stepper-icons {
|
|
632
|
+
--wui-step-number-font: 18px;
|
|
633
|
+
--wui-step-label-font: 13px;
|
|
634
|
+
}
|
|
635
|
+
.wui-step-size-lg {
|
|
636
|
+
--wui-step-size: 36px;
|
|
637
|
+
--wui-step-badge-size: 68px;
|
|
638
|
+
--wui-step-journey-size: 48px;
|
|
639
|
+
--wui-step-number-font: 14px;
|
|
640
|
+
--wui-step-label-font: 15px;
|
|
641
|
+
}
|
|
642
|
+
.wui-step-size-lg .stepper-journey,
|
|
643
|
+
.wui-step-size-lg.stepper-journey {
|
|
644
|
+
--wui-step-number-font: 15px;
|
|
645
|
+
--wui-step-label-font: 18px;
|
|
646
|
+
}
|
|
647
|
+
.wui-step-size-lg .stepper-icons,
|
|
648
|
+
.wui-step-size-lg.stepper-icons {
|
|
649
|
+
--wui-step-number-font: 26px;
|
|
650
|
+
--wui-step-label-font: 17px;
|
|
651
|
+
}
|
|
652
|
+
|
|
599
653
|
// ============================================================================
|
|
600
654
|
// Pricing card. A tier's name, price, pitch, feature list and CTA.
|
|
601
655
|
//
|