@webority/theme 0.7.8 → 0.7.9
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/webority-theme.css +1 -1
- package/package.json +1 -1
- package/scss/_wui-components.scss +5 -1
- package/scss/wui/_controls.scss +28 -24
- package/scss/wui/_flow.scss +250 -34
- package/scss/wui/_tone-pill.scss +23 -0
- package/scss/wui/_typography.scss +45 -15
- package/scss/wui/_utilities.scss +29 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.9",
|
|
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": {
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
// This file is now an INDEX. The rules live in ./wui/*.scss, split by domain
|
|
19
19
|
// because one 5,000-line stylesheet made finding a component a grep.
|
|
20
20
|
//
|
|
21
|
+
// Shared tone-pill mixin — used by .badge, .status-label, and .chip.
|
|
22
|
+
// Must be imported before components that use it.
|
|
23
|
+
@import "wui/tone-pill";
|
|
24
|
+
|
|
21
25
|
// The order below is LOAD-BEARING. A later partial may deliberately override an
|
|
22
26
|
// earlier one, so reordering these imports silently changes the cascade — and
|
|
23
27
|
// nothing in the build will complain. `pnpm check:theme` measures the rules that
|
|
@@ -47,7 +51,7 @@
|
|
|
47
51
|
// and nothing failing anywhere to point at the cause. The component shipped; its styling did
|
|
48
52
|
// not. That is the same escape as th.sortable and .u-name, and the fix is the same principle:
|
|
49
53
|
// a component and the CSS it requires travel together.
|
|
50
|
-
|
|
54
|
+
|
|
51
55
|
// It is not free — roughly 183KB raw, 45KB gzipped, mostly inlined SVG. A product that never
|
|
52
56
|
// renders a phone field can skip it by importing the `wui/*` partials above individually
|
|
53
57
|
// instead of this aggregate; that is the deliberate opt-out, and it is a choice rather than
|
package/scss/wui/_controls.scss
CHANGED
|
@@ -176,6 +176,24 @@
|
|
|
176
176
|
// Re-assert the knob — the checkbox :checked tick has equal specificity.
|
|
177
177
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='7' fill='white'/%3E%3C/svg%3E");
|
|
178
178
|
}
|
|
179
|
+
|
|
180
|
+
// Circular variant (shape="circle") — a compact round on/off button instead of a sliding
|
|
181
|
+
// pill. The track is a square-sized circle; the knob dot stays CENTRED in both states (no
|
|
182
|
+
// left/right slide) and the fill flips to primary when on. Placed after the base switch
|
|
183
|
+
// block so the equal-specificity :checked position override wins on source order.
|
|
184
|
+
.form-switch-circle .form-check-input {
|
|
185
|
+
width: 24px;
|
|
186
|
+
height: 24px;
|
|
187
|
+
// The switch is a type="checkbox", which carries `corner-shape: squircle` — on a square
|
|
188
|
+
// that renders a rounded square, not a circle. Reset to a true round corner.
|
|
189
|
+
corner-shape: round;
|
|
190
|
+
border-radius: 999px;
|
|
191
|
+
background-position: center;
|
|
192
|
+
background-size: 10px 10px;
|
|
193
|
+
}
|
|
194
|
+
.form-switch-circle .form-check-input:checked {
|
|
195
|
+
background-position: center;
|
|
196
|
+
}
|
|
179
197
|
@media (prefers-reduced-motion: reduce) {
|
|
180
198
|
.form-check-input,
|
|
181
199
|
.wui-check,
|
|
@@ -1050,30 +1068,21 @@ wui-select[compact] {
|
|
|
1050
1068
|
border: 1px solid var(--color-border);
|
|
1051
1069
|
}
|
|
1052
1070
|
.badge-primary {
|
|
1053
|
-
|
|
1054
|
-
color: var(--color-primary);
|
|
1071
|
+
@include wui-tone-pill-colors(primary, var(--color-primary));
|
|
1055
1072
|
border-color: color-mix(in srgb, var(--color-primary) 25%, transparent);
|
|
1056
1073
|
}
|
|
1057
1074
|
.badge-success {
|
|
1058
|
-
|
|
1059
|
-
color: var(--color-success-text);
|
|
1060
|
-
border-color: transparent;
|
|
1075
|
+
@include wui-tone-pill-colors(success);
|
|
1061
1076
|
}
|
|
1062
1077
|
.badge-warning,
|
|
1063
1078
|
.badge-warn {
|
|
1064
|
-
|
|
1065
|
-
color: var(--color-warning-text);
|
|
1066
|
-
border-color: transparent;
|
|
1079
|
+
@include wui-tone-pill-colors(warning);
|
|
1067
1080
|
}
|
|
1068
1081
|
.badge-danger {
|
|
1069
|
-
|
|
1070
|
-
color: var(--color-danger-text);
|
|
1071
|
-
border-color: transparent;
|
|
1082
|
+
@include wui-tone-pill-colors(danger);
|
|
1072
1083
|
}
|
|
1073
1084
|
.badge-info {
|
|
1074
|
-
|
|
1075
|
-
color: var(--color-info-text);
|
|
1076
|
-
border-color: transparent;
|
|
1085
|
+
@include wui-tone-pill-colors(info);
|
|
1077
1086
|
}
|
|
1078
1087
|
.badge-dot::before {
|
|
1079
1088
|
content: "";
|
|
@@ -1109,29 +1118,24 @@ wui-select[compact] {
|
|
|
1109
1118
|
.status-label.success,
|
|
1110
1119
|
.status-label.tone-ok,
|
|
1111
1120
|
.status-label.tone-green {
|
|
1112
|
-
|
|
1113
|
-
color: var(--color-success-text);
|
|
1121
|
+
@include wui-tone-pill-colors(success);
|
|
1114
1122
|
}
|
|
1115
1123
|
.status-label.warning,
|
|
1116
1124
|
.status-label.tone-warn,
|
|
1117
1125
|
.status-label.tone-amber {
|
|
1118
|
-
|
|
1119
|
-
color: var(--color-warning-text);
|
|
1126
|
+
@include wui-tone-pill-colors(warning);
|
|
1120
1127
|
}
|
|
1121
1128
|
.status-label.danger,
|
|
1122
1129
|
.status-label.tone-bad,
|
|
1123
1130
|
.status-label.tone-red {
|
|
1124
|
-
|
|
1125
|
-
color: var(--color-danger-text);
|
|
1131
|
+
@include wui-tone-pill-colors(danger);
|
|
1126
1132
|
}
|
|
1127
1133
|
.status-label.info,
|
|
1128
1134
|
.status-label.tone-blue {
|
|
1129
|
-
|
|
1130
|
-
color: var(--color-info-text);
|
|
1135
|
+
@include wui-tone-pill-colors(info);
|
|
1131
1136
|
}
|
|
1132
1137
|
.status-label.primary {
|
|
1133
|
-
|
|
1134
|
-
color: var(--color-primary);
|
|
1138
|
+
@include wui-tone-pill-colors(primary, var(--color-primary));
|
|
1135
1139
|
}
|
|
1136
1140
|
// Default/neutral — also the bare `.status-label` look, so an unknown or omitted
|
|
1137
1141
|
// tone still renders as a proper pill instead of transparent text.
|
package/scss/wui/_flow.scss
CHANGED
|
@@ -5,9 +5,24 @@
|
|
|
5
5
|
// partials are a split of one stylesheet, not independent modules, so a rule
|
|
6
6
|
// here may be overridden by a later partial. Never reorder the imports.
|
|
7
7
|
|
|
8
|
-
// Wizard stepper.
|
|
8
|
+
// Wizard stepper. Three variants of one component:
|
|
9
9
|
// .stepper — compact: numbered circle above a label, line behind.
|
|
10
10
|
// .stepper-journey — wide: 40px dot beside a label + title, for a page masthead.
|
|
11
|
+
// .stepper-icons — large connected icon badges with a "STEP n" eyebrow.
|
|
12
|
+
//
|
|
13
|
+
// Fully themable through a small set of `--wui-step-*` custom properties — set them on
|
|
14
|
+
// the stepper (or the wizard host, or any ancestor: they inherit), or flip the whole
|
|
15
|
+
// accent with a `.wui-step-tone-*` class. Every colour/size below reads a var with the
|
|
16
|
+
// historical value as the fallback, so an UNSET wizard looks exactly as before while a
|
|
17
|
+
// product can recolour or resize it without overriding a single selector:
|
|
18
|
+
// --wui-step-accent solid state colour (active fill, done fill/rail, active eyebrow)
|
|
19
|
+
// --wui-step-accent-fg text/icon on the accent fill
|
|
20
|
+
// --wui-step-soft soft tint (active ring; the journey/icons "done" badge bg)
|
|
21
|
+
// --wui-step-soft-fg text/icon on the soft tint (the "done" badge check)
|
|
22
|
+
// --wui-step-connector the incomplete-rail colour
|
|
23
|
+
// --wui-step-size compact/vertical badge diameter (default 28px)
|
|
24
|
+
// --wui-step-badge-size icons-variant badge diameter (default 56px)
|
|
25
|
+
// The icons variant defaults its accent to success (green); the others to primary.
|
|
11
26
|
// ============================================================================
|
|
12
27
|
.stepper {
|
|
13
28
|
// Full width so the flex:1 steps spread evenly across the container. Without it,
|
|
@@ -34,23 +49,23 @@
|
|
|
34
49
|
.step + .step::before {
|
|
35
50
|
content: "";
|
|
36
51
|
position: absolute;
|
|
37
|
-
//
|
|
38
|
-
top:
|
|
39
|
-
left: calc(-50% +
|
|
40
|
-
right: calc(50% +
|
|
52
|
+
// Centred on the badge: half the diameter, minus 1 for the 2px line's own height.
|
|
53
|
+
top: calc(var(--wui-step-size, 28px) / 2 - 1px);
|
|
54
|
+
left: calc(-50% + var(--wui-step-size, 28px) / 2 + 4px);
|
|
55
|
+
right: calc(50% + var(--wui-step-size, 28px) / 2 + 4px);
|
|
41
56
|
height: 2px;
|
|
42
|
-
background: var(--color-border);
|
|
57
|
+
background: var(--wui-step-connector, var(--color-border));
|
|
43
58
|
z-index: 0;
|
|
44
59
|
}
|
|
45
60
|
.step.done + .step::before {
|
|
46
|
-
background: var(--color-primary);
|
|
61
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
47
62
|
}
|
|
48
63
|
.step-circle {
|
|
49
64
|
position: relative;
|
|
50
65
|
z-index: 1;
|
|
51
66
|
flex: none;
|
|
52
|
-
width: 28px;
|
|
53
|
-
height: 28px;
|
|
67
|
+
width: var(--wui-step-size, 28px);
|
|
68
|
+
height: var(--wui-step-size, 28px);
|
|
54
69
|
display: inline-grid;
|
|
55
70
|
place-items: center;
|
|
56
71
|
border: 1.5px solid var(--color-border);
|
|
@@ -61,15 +76,15 @@
|
|
|
61
76
|
color: var(--color-text-subtle);
|
|
62
77
|
}
|
|
63
78
|
.step.active .step-circle {
|
|
64
|
-
border-color: var(--color-primary);
|
|
65
|
-
background: var(--color-primary);
|
|
66
|
-
color: var(--color-on-scrim);
|
|
67
|
-
box-shadow: 0 0 0 4px var(--color-primary-soft);
|
|
79
|
+
border-color: var(--wui-step-accent, var(--color-primary));
|
|
80
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
81
|
+
color: var(--wui-step-accent-fg, var(--color-on-scrim));
|
|
82
|
+
box-shadow: 0 0 0 4px var(--wui-step-soft, var(--color-primary-soft));
|
|
68
83
|
}
|
|
69
84
|
.step.done .step-circle {
|
|
70
|
-
border-color: var(--color-primary);
|
|
71
|
-
background: var(--color-primary);
|
|
72
|
-
color: var(--color-on-scrim);
|
|
85
|
+
border-color: var(--wui-step-accent, var(--color-primary));
|
|
86
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
87
|
+
color: var(--wui-step-accent-fg, var(--color-on-scrim));
|
|
73
88
|
}
|
|
74
89
|
.step-label {
|
|
75
90
|
max-width: 130px;
|
|
@@ -101,12 +116,12 @@ button.step {
|
|
|
101
116
|
}
|
|
102
117
|
a.step:hover .step-circle,
|
|
103
118
|
button.step:hover .step-circle {
|
|
104
|
-
box-shadow: 0 0 0 4px var(--color-primary-soft);
|
|
119
|
+
box-shadow: 0 0 0 4px var(--wui-step-soft, var(--color-primary-soft));
|
|
105
120
|
transform: scale(1.04);
|
|
106
121
|
}
|
|
107
122
|
a.step:hover .step-label,
|
|
108
123
|
button.step:hover .step-label {
|
|
109
|
-
color: var(--color-primary);
|
|
124
|
+
color: var(--wui-step-accent, var(--color-primary));
|
|
110
125
|
}
|
|
111
126
|
a.step:focus-visible,
|
|
112
127
|
button.step:focus-visible {
|
|
@@ -116,8 +131,8 @@ button.step:focus-visible {
|
|
|
116
131
|
a.step:focus-visible .step-circle,
|
|
117
132
|
button.step:focus-visible .step-circle {
|
|
118
133
|
box-shadow:
|
|
119
|
-
0 0 0 4px var(--color-primary-soft),
|
|
120
|
-
0 0 0 6px var(--color-primary);
|
|
134
|
+
0 0 0 4px var(--wui-step-soft, var(--color-primary-soft)),
|
|
135
|
+
0 0 0 6px var(--wui-step-accent, var(--color-primary));
|
|
121
136
|
}
|
|
122
137
|
// A step that failed its stage — a red circle with an alert, so an invalid step
|
|
123
138
|
// reads as wrong at a glance rather than merely "not done".
|
|
@@ -173,12 +188,12 @@ button.step:focus-visible .step-circle {
|
|
|
173
188
|
transform 0.2s ease;
|
|
174
189
|
}
|
|
175
190
|
.stepper-journey .step.done .step-circle {
|
|
176
|
-
background: var(--color-success-soft);
|
|
177
|
-
color: var(--color-success-text);
|
|
191
|
+
background: var(--wui-step-soft, var(--color-success-soft));
|
|
192
|
+
color: var(--wui-step-soft-fg, var(--color-success-text));
|
|
178
193
|
}
|
|
179
194
|
.stepper-journey .step.active .step-circle {
|
|
180
|
-
background: var(--color-primary);
|
|
181
|
-
color: var(--color-on-scrim);
|
|
195
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
196
|
+
color: var(--wui-step-accent-fg, var(--color-on-scrim));
|
|
182
197
|
box-shadow: none;
|
|
183
198
|
transform: scale(1.06);
|
|
184
199
|
}
|
|
@@ -199,10 +214,10 @@ button.step:focus-visible .step-circle {
|
|
|
199
214
|
color: var(--color-text-subtle);
|
|
200
215
|
}
|
|
201
216
|
.stepper-journey .step.done .step-index {
|
|
202
|
-
color: var(--color-success-text);
|
|
217
|
+
color: var(--wui-step-soft-fg, var(--color-success-text));
|
|
203
218
|
}
|
|
204
219
|
.stepper-journey .step.active .step-index {
|
|
205
|
-
color: var(--color-primary);
|
|
220
|
+
color: var(--wui-step-accent, var(--color-primary));
|
|
206
221
|
}
|
|
207
222
|
.stepper-journey .step.error .step-circle {
|
|
208
223
|
background: var(--color-danger-soft);
|
|
@@ -240,7 +255,7 @@ button.step:focus-visible .step-circle {
|
|
|
240
255
|
background: var(--color-border-strong);
|
|
241
256
|
}
|
|
242
257
|
.stepper-journey .step-line.done {
|
|
243
|
-
background: var(--color-success);
|
|
258
|
+
background: var(--wui-step-accent, var(--color-success));
|
|
244
259
|
}
|
|
245
260
|
// Below xl the four label+title pairs no longer fit side by side, so the bar
|
|
246
261
|
// becomes a vertical list and the connectors go away.
|
|
@@ -270,7 +285,7 @@ button.step:focus-visible .step-circle {
|
|
|
270
285
|
// left, the label and its description stacked on the right.
|
|
271
286
|
.stepper-vertical .step {
|
|
272
287
|
display: grid;
|
|
273
|
-
grid-template-columns: 28px 1fr;
|
|
288
|
+
grid-template-columns: var(--wui-step-size, 28px) 1fr;
|
|
274
289
|
column-gap: 12px;
|
|
275
290
|
// No gap between the label and its description — they read as one block; the
|
|
276
291
|
// base .step gap of 10px is for the horizontal circle→label spacing.
|
|
@@ -307,18 +322,18 @@ button.step:focus-visible .step-circle {
|
|
|
307
322
|
.stepper-vertical .step:not(:last-child)::after {
|
|
308
323
|
content: "";
|
|
309
324
|
position: absolute;
|
|
310
|
-
//
|
|
311
|
-
left:
|
|
312
|
-
top: 28px;
|
|
325
|
+
// Half the badge minus 1 for the 2px line's own width; runs from below the circle.
|
|
326
|
+
left: calc(var(--wui-step-size, 28px) / 2 - 1px);
|
|
327
|
+
top: var(--wui-step-size, 28px);
|
|
313
328
|
// Reaches through the 18px inter-step gap to meet the next circle's top; keep
|
|
314
329
|
// this in sync with the .stepper-vertical `gap`.
|
|
315
330
|
bottom: -18px;
|
|
316
331
|
width: 2px;
|
|
317
|
-
background: var(--color-border);
|
|
332
|
+
background: var(--wui-step-connector, var(--color-border));
|
|
318
333
|
z-index: 0;
|
|
319
334
|
}
|
|
320
335
|
.stepper-vertical .step.done:not(:last-child)::after {
|
|
321
|
-
background: var(--color-primary);
|
|
336
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
322
337
|
}
|
|
323
338
|
// The journey bar stacked vertically reuses its own narrow-width treatment: a plain
|
|
324
339
|
// column with the horizontal connectors dropped (a real vertical rail here would
|
|
@@ -332,15 +347,169 @@ button.step:focus-visible .step-circle {
|
|
|
332
347
|
display: none;
|
|
333
348
|
}
|
|
334
349
|
|
|
350
|
+
// .stepper-icons — large icon badges joined by a rail, with a "STEP n" eyebrow above
|
|
351
|
+
// each title. Done tints green with a filled connector; active is a solid primary
|
|
352
|
+
// badge; pending is a muted badge. Built for icon-per-step flows — each step sets `icon`
|
|
353
|
+
// (a step with no icon falls back to its number).
|
|
354
|
+
// ----------------------------------------------------------------------------
|
|
355
|
+
.stepper-icons {
|
|
356
|
+
align-items: flex-start;
|
|
357
|
+
padding: 8px 8px 0;
|
|
358
|
+
}
|
|
359
|
+
.stepper-icons .step {
|
|
360
|
+
gap: 6px;
|
|
361
|
+
}
|
|
362
|
+
.stepper-icons .step-circle {
|
|
363
|
+
width: var(--wui-step-badge-size, 56px);
|
|
364
|
+
height: var(--wui-step-badge-size, 56px);
|
|
365
|
+
border: none;
|
|
366
|
+
background: var(--color-bg-muted);
|
|
367
|
+
color: var(--color-text-subtle);
|
|
368
|
+
font-size: 22px;
|
|
369
|
+
transition:
|
|
370
|
+
background 0.2s ease,
|
|
371
|
+
color 0.2s ease,
|
|
372
|
+
transform 0.2s ease;
|
|
373
|
+
}
|
|
374
|
+
// The icons variant defaults its accent to success (green), so an untoned icons wizard
|
|
375
|
+
// reads green — solid-green active badge, soft-green done badge, green rail. Every colour
|
|
376
|
+
// still routes through the shared --wui-step-* vars, so a tone class or an override recolours it.
|
|
377
|
+
.stepper-icons .step.active .step-circle {
|
|
378
|
+
background: var(--wui-step-accent, var(--color-success));
|
|
379
|
+
color: var(--wui-step-accent-fg, var(--color-on-scrim));
|
|
380
|
+
// The compact variant rings the active circle; here the solid fill carries it, so
|
|
381
|
+
// drop the ring to match the flat badge look.
|
|
382
|
+
box-shadow: none;
|
|
383
|
+
}
|
|
384
|
+
.stepper-icons .step.done .step-circle {
|
|
385
|
+
border: none;
|
|
386
|
+
background: var(--wui-step-soft, var(--color-success-soft));
|
|
387
|
+
color: var(--wui-step-soft-fg, var(--color-success-text));
|
|
388
|
+
}
|
|
389
|
+
.stepper-icons .step.error .step-circle {
|
|
390
|
+
background: var(--color-danger-soft);
|
|
391
|
+
color: var(--color-danger-text);
|
|
392
|
+
}
|
|
393
|
+
.stepper-icons .step.skipped .step-circle {
|
|
394
|
+
background: var(--color-bg-muted);
|
|
395
|
+
border: 1px dashed var(--color-border-strong);
|
|
396
|
+
color: var(--color-text-muted);
|
|
397
|
+
}
|
|
398
|
+
// The "STEP n" eyebrow sits between the badge and the title, colour-matched to the state.
|
|
399
|
+
.stepper-icons .step-index {
|
|
400
|
+
margin-top: 4px;
|
|
401
|
+
font-size: 12px;
|
|
402
|
+
font-weight: 600;
|
|
403
|
+
line-height: 1.2;
|
|
404
|
+
text-transform: uppercase;
|
|
405
|
+
letter-spacing: 0.06em;
|
|
406
|
+
color: var(--color-text-subtle);
|
|
407
|
+
}
|
|
408
|
+
.stepper-icons .step.active .step-index {
|
|
409
|
+
color: var(--wui-step-accent, var(--color-success));
|
|
410
|
+
}
|
|
411
|
+
.stepper-icons .step.done .step-index {
|
|
412
|
+
color: var(--wui-step-soft-fg, var(--color-success-text));
|
|
413
|
+
}
|
|
414
|
+
.stepper-icons .step.error .step-index {
|
|
415
|
+
color: var(--color-danger-text);
|
|
416
|
+
}
|
|
417
|
+
.stepper-icons .step-label {
|
|
418
|
+
max-width: 150px;
|
|
419
|
+
font-size: 15px;
|
|
420
|
+
font-weight: 600;
|
|
421
|
+
color: var(--color-text-subtle);
|
|
422
|
+
}
|
|
423
|
+
.stepper-icons .step.active .step-label,
|
|
424
|
+
.stepper-icons .step.done .step-label {
|
|
425
|
+
color: var(--color-text);
|
|
426
|
+
}
|
|
427
|
+
// The rail: thicker and rounded, recentred on the badge (half the diameter − 2 for the
|
|
428
|
+
// 4px line's own height), and filled with the accent once the step to its left is done.
|
|
429
|
+
.stepper-icons .step + .step::before {
|
|
430
|
+
top: calc(var(--wui-step-badge-size, 56px) / 2 - 2px);
|
|
431
|
+
left: calc(-50% + var(--wui-step-badge-size, 56px) / 2 + 8px);
|
|
432
|
+
right: calc(50% + var(--wui-step-badge-size, 56px) / 2 + 8px);
|
|
433
|
+
height: 4px;
|
|
434
|
+
border-radius: 999px;
|
|
435
|
+
background: var(--wui-step-connector, var(--color-border));
|
|
436
|
+
}
|
|
437
|
+
.stepper-icons .step.done + .step::before {
|
|
438
|
+
background: var(--wui-step-accent, var(--color-success));
|
|
439
|
+
}
|
|
440
|
+
// The compact hover ring is calibrated to the 28px badge; the 56px icon badge just
|
|
441
|
+
// lifts on hover instead.
|
|
442
|
+
.stepper-icons a.step:hover .step-circle,
|
|
443
|
+
.stepper-icons button.step:hover .step-circle {
|
|
444
|
+
box-shadow: none;
|
|
445
|
+
transform: scale(1.04);
|
|
446
|
+
}
|
|
447
|
+
// Below md the six badges no longer fit across, so the icons stepper stacks into a
|
|
448
|
+
// vertical list — the shared .stepper-vertical rules take over from here.
|
|
449
|
+
@include media-breakpoint-down(md) {
|
|
450
|
+
.stepper-icons.stepper-icons {
|
|
451
|
+
flex-direction: column;
|
|
452
|
+
align-items: stretch;
|
|
453
|
+
gap: 20px;
|
|
454
|
+
}
|
|
455
|
+
.stepper-icons.stepper-icons .step {
|
|
456
|
+
flex-direction: row;
|
|
457
|
+
align-items: center;
|
|
458
|
+
gap: 14px;
|
|
459
|
+
text-align: left;
|
|
460
|
+
}
|
|
461
|
+
.stepper-icons.stepper-icons .step + .step::before {
|
|
462
|
+
content: none;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
335
466
|
@media (prefers-reduced-motion: reduce) {
|
|
336
467
|
a.step:hover .step-circle,
|
|
337
468
|
button.step:hover .step-circle,
|
|
338
|
-
.stepper-journey .step-circle
|
|
469
|
+
.stepper-journey .step-circle,
|
|
470
|
+
.stepper-icons .step-circle {
|
|
339
471
|
transition: none;
|
|
340
472
|
transform: none;
|
|
341
473
|
}
|
|
342
474
|
}
|
|
343
475
|
|
|
476
|
+
// Tone presets — flip the whole accent (active fill, done rail, ring, journey/icons
|
|
477
|
+
// done tint) to a semantic ramp in one class. Because custom properties inherit, the
|
|
478
|
+
// class can sit on the stepper itself OR on an ancestor (the wizard host), and an inline
|
|
479
|
+
// `style="--wui-step-accent: …"` on a closer element still wins over it. Placing the
|
|
480
|
+
// class recolours every variant consistently; error steps stay red regardless (semantic).
|
|
481
|
+
// ----------------------------------------------------------------------------
|
|
482
|
+
.wui-step-tone-primary {
|
|
483
|
+
--wui-step-accent: var(--color-primary);
|
|
484
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
485
|
+
--wui-step-soft: var(--color-primary-soft);
|
|
486
|
+
--wui-step-soft-fg: var(--color-primary);
|
|
487
|
+
}
|
|
488
|
+
.wui-step-tone-success {
|
|
489
|
+
--wui-step-accent: var(--color-success);
|
|
490
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
491
|
+
--wui-step-soft: var(--color-success-soft);
|
|
492
|
+
--wui-step-soft-fg: var(--color-success-text);
|
|
493
|
+
}
|
|
494
|
+
.wui-step-tone-warning {
|
|
495
|
+
--wui-step-accent: var(--color-warning);
|
|
496
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
497
|
+
--wui-step-soft: var(--color-warning-soft);
|
|
498
|
+
--wui-step-soft-fg: var(--color-warning-text);
|
|
499
|
+
}
|
|
500
|
+
.wui-step-tone-danger {
|
|
501
|
+
--wui-step-accent: var(--color-danger);
|
|
502
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
503
|
+
--wui-step-soft: var(--color-danger-soft);
|
|
504
|
+
--wui-step-soft-fg: var(--color-danger-text);
|
|
505
|
+
}
|
|
506
|
+
.wui-step-tone-info {
|
|
507
|
+
--wui-step-accent: var(--color-info);
|
|
508
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
509
|
+
--wui-step-soft: var(--color-info-soft);
|
|
510
|
+
--wui-step-soft-fg: var(--color-info-text);
|
|
511
|
+
}
|
|
512
|
+
|
|
344
513
|
// ============================================================================
|
|
345
514
|
// Pricing card. A tier's name, price, pitch, feature list and CTA.
|
|
346
515
|
//
|
|
@@ -616,4 +785,51 @@ button.step:focus-visible .step-circle {
|
|
|
616
785
|
.form-actions-sticky {
|
|
617
786
|
transition: none;
|
|
618
787
|
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// ============================================================================
|
|
791
|
+
// AppWizard (<wui-wizard>) — stepper header + one visible step panel + a sticky
|
|
792
|
+
// Back/Skip/Next/Finish footer. Composes .stepper and .form-actions above.
|
|
793
|
+
// ============================================================================
|
|
794
|
+
wui-wizard {
|
|
795
|
+
display: block;
|
|
796
|
+
}
|
|
797
|
+
// Custom elements don't inherit the UA `[hidden] { display: none }` once we give the
|
|
798
|
+
// tag its own `display`, so the inactive panels need it stated explicitly.
|
|
799
|
+
wui-wizard-step {
|
|
800
|
+
display: block;
|
|
801
|
+
}
|
|
802
|
+
wui-wizard-step[hidden] {
|
|
803
|
+
display: none;
|
|
804
|
+
}
|
|
805
|
+
.wizard-stepper {
|
|
806
|
+
margin-bottom: 24px;
|
|
807
|
+
}
|
|
808
|
+
// A skipped step reads as "passed over", not "achieved": a dashed, muted circle so it
|
|
809
|
+
// is visibly distinct from a ticked (done) step.
|
|
810
|
+
.step.skipped .step-circle {
|
|
811
|
+
background: var(--color-bg-muted);
|
|
812
|
+
border: 1px dashed var(--color-border-strong);
|
|
813
|
+
color: var(--color-text-muted);
|
|
814
|
+
}
|
|
815
|
+
.wizard-panel {
|
|
816
|
+
// A resting min-height so the footer doesn't jump as steps of different length
|
|
817
|
+
// swap in; content taller than this simply grows the panel.
|
|
818
|
+
min-height: 96px;
|
|
819
|
+
}
|
|
820
|
+
.wizard-footer {
|
|
821
|
+
// The sticky Back/Skip/Next/Finish bar — pinned to the bottom of a scrolling flow
|
|
822
|
+
// so the actions (and the Skip on an optional step) are always in reach.
|
|
823
|
+
position: sticky;
|
|
824
|
+
bottom: 0;
|
|
825
|
+
margin-top: 24px;
|
|
826
|
+
padding: 16px 0;
|
|
827
|
+
border-top: 1px solid var(--color-border);
|
|
828
|
+
background: var(--color-surface);
|
|
829
|
+
z-index: 1;
|
|
830
|
+
}
|
|
831
|
+
.wizard-footer-actions {
|
|
832
|
+
display: flex;
|
|
833
|
+
align-items: center;
|
|
834
|
+
gap: 12px;
|
|
619
835
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// ── Shared tone-pill color mixin ──
|
|
2
|
+
// Consolidates the tone→color mapping used by .badge, .status-label, and .chip:
|
|
3
|
+
// background: var(--color-{tone}-soft)
|
|
4
|
+
// color: var(--color-{tone}-text) (override via $text — see below)
|
|
5
|
+
// border-color: transparent
|
|
6
|
+
//
|
|
7
|
+
// $text exists because the status tones and `primary` name their on-tint color
|
|
8
|
+
// differently: --color-{status}-text IS the on-tint hue, but --color-primary-text
|
|
9
|
+
// is the text-on-SOLID-primary color (near-black in dark mode) and fails AA on the
|
|
10
|
+
// soft tint — primary pills pass var(--color-primary) instead.
|
|
11
|
+
//
|
|
12
|
+
// Component-specific overrides (e.g. .badge-primary's colored border) are applied
|
|
13
|
+
// after the mixin call.
|
|
14
|
+
|
|
15
|
+
@mixin wui-tone-pill-colors($tone, $text: null) {
|
|
16
|
+
background: var(--color-#{$tone}-soft);
|
|
17
|
+
@if $text {
|
|
18
|
+
color: $text;
|
|
19
|
+
} @else {
|
|
20
|
+
color: var(--color-#{$tone}-text);
|
|
21
|
+
}
|
|
22
|
+
border-color: transparent;
|
|
23
|
+
}
|
|
@@ -121,29 +121,19 @@
|
|
|
121
121
|
|
|
122
122
|
/* Tones — tinted surface + on-tint text; icon/remove inherit the tone colour. */
|
|
123
123
|
.chip.primary {
|
|
124
|
-
|
|
125
|
-
background: var(--color-primary-soft);
|
|
126
|
-
color: var(--color-primary);
|
|
124
|
+
@include wui-tone-pill-colors(primary, var(--color-primary));
|
|
127
125
|
}
|
|
128
126
|
.chip.success {
|
|
129
|
-
|
|
130
|
-
background: var(--color-success-soft);
|
|
131
|
-
color: var(--color-success-text);
|
|
127
|
+
@include wui-tone-pill-colors(success);
|
|
132
128
|
}
|
|
133
129
|
.chip.warning {
|
|
134
|
-
|
|
135
|
-
background: var(--color-warning-soft);
|
|
136
|
-
color: var(--color-warning-text);
|
|
130
|
+
@include wui-tone-pill-colors(warning);
|
|
137
131
|
}
|
|
138
132
|
.chip.danger {
|
|
139
|
-
|
|
140
|
-
background: var(--color-danger-soft);
|
|
141
|
-
color: var(--color-danger-text);
|
|
133
|
+
@include wui-tone-pill-colors(danger);
|
|
142
134
|
}
|
|
143
135
|
.chip.info {
|
|
144
|
-
|
|
145
|
-
background: var(--color-info-soft);
|
|
146
|
-
color: var(--color-info-text);
|
|
136
|
+
@include wui-tone-pill-colors(info);
|
|
147
137
|
}
|
|
148
138
|
.chip.primary .chip-ic,
|
|
149
139
|
.chip.success .chip-ic,
|
|
@@ -238,6 +228,25 @@
|
|
|
238
228
|
min-width: 0;
|
|
239
229
|
align-items: center;
|
|
240
230
|
}
|
|
231
|
+
// Chips scale with the control size — the taller the field, the larger its tokens
|
|
232
|
+
// (the element always emits `.chip.chip-sm`; these override it per size tier). The
|
|
233
|
+
// two-class `.ms-chips .chip` outranks the single `.chip-sm`, so md is the base and
|
|
234
|
+
// the sm/lg tiers layer over it.
|
|
235
|
+
.ms-chips .chip {
|
|
236
|
+
gap: 5px;
|
|
237
|
+
padding: 3px 9px;
|
|
238
|
+
font-size: 0.8125rem;
|
|
239
|
+
}
|
|
240
|
+
.search-select-sm .ms-chips .chip {
|
|
241
|
+
gap: 4px;
|
|
242
|
+
padding: 2px 8px;
|
|
243
|
+
font-size: 0.75rem;
|
|
244
|
+
}
|
|
245
|
+
.search-select-lg .ms-chips .chip {
|
|
246
|
+
gap: 6px;
|
|
247
|
+
padding: 5px 12px;
|
|
248
|
+
font-size: 0.875rem;
|
|
249
|
+
}
|
|
241
250
|
// Collapse mode (collapse-chips): chips stay on one row; the JS folds the overflow into
|
|
242
251
|
// a "+N" counter (see WuiMultiSelect._collapseChips).
|
|
243
252
|
wui-multiselect[collapse-chips] .ms-chips {
|
|
@@ -295,6 +304,27 @@ wui-multiselect[collapse-chips] .ms-chips {
|
|
|
295
304
|
.ms-input:focus {
|
|
296
305
|
outline: none;
|
|
297
306
|
}
|
|
307
|
+
// AppTagInput lays the input on the LEFT with the chips filling and wrapping to its
|
|
308
|
+
// right (its template renders the input before the chips). Multiselect keeps its
|
|
309
|
+
// chips-first layout, so these overrides are scoped to `wui-taginput`.
|
|
310
|
+
wui-taginput .ms-input {
|
|
311
|
+
// Don't grow to fill — hold a modest resting width on the left; the chips take
|
|
312
|
+
// everything to the right. (align-items:center on the control centres the input
|
|
313
|
+
// against the chip row, so it needs no min-height of its own.)
|
|
314
|
+
flex: 0 1 auto;
|
|
315
|
+
flex-basis: 120px;
|
|
316
|
+
min-width: 96px;
|
|
317
|
+
}
|
|
318
|
+
wui-taginput .ms-chips {
|
|
319
|
+
flex: 1 1 auto;
|
|
320
|
+
}
|
|
321
|
+
// Match AppInput's per-size heights: the shared `.search-select-multi` floors md at
|
|
322
|
+
// 40px, but AppInput's md is the 44px control-height token — raise the floor so the
|
|
323
|
+
// sm/md/lg progression lines up with a text field beside it. (sm 36 / lg 52 already
|
|
324
|
+
// come from the size-specific `.search-select-{sm,lg} .search-select-control` rules.)
|
|
325
|
+
wui-taginput .search-select-multi {
|
|
326
|
+
min-height: var(--wui-control-height);
|
|
327
|
+
}
|
|
298
328
|
|
|
299
329
|
/* ── Choice card: image / custom-template variant ── */
|
|
300
330
|
.struct-card-img-card {
|
package/scss/wui/_utilities.scss
CHANGED
|
@@ -73,7 +73,6 @@
|
|
|
73
73
|
background: transparent;
|
|
74
74
|
color: var(--color-text-subtle);
|
|
75
75
|
cursor: help;
|
|
76
|
-
transform: scaleY(-1);
|
|
77
76
|
transition: color 0.15s;
|
|
78
77
|
}
|
|
79
78
|
.infotip-btn:hover {
|
|
@@ -598,6 +597,35 @@
|
|
|
598
597
|
color: var(--color-primary);
|
|
599
598
|
}
|
|
600
599
|
|
|
600
|
+
// AppAlert extras — a leading icon and/or a bold heading line. Bootstrap already
|
|
601
|
+
// styles `.alert`/`.alert-{variant}`; these rules only lay out the icon column and
|
|
602
|
+
// give the plain `.alert-heading` div its type treatment (Bootstrap's own rule is
|
|
603
|
+
// just `color: inherit`, meant for an <h4>).
|
|
604
|
+
.alert-has-icon {
|
|
605
|
+
display: flex;
|
|
606
|
+
align-items: flex-start;
|
|
607
|
+
gap: 12px;
|
|
608
|
+
}
|
|
609
|
+
.alert-icon {
|
|
610
|
+
flex: none;
|
|
611
|
+
display: inline-flex;
|
|
612
|
+
// Nudge onto the first line's optical centre.
|
|
613
|
+
margin-top: 1px;
|
|
614
|
+
}
|
|
615
|
+
.alert-content {
|
|
616
|
+
flex: 1;
|
|
617
|
+
min-width: 0;
|
|
618
|
+
}
|
|
619
|
+
.alert .alert-heading {
|
|
620
|
+
margin-bottom: 2px;
|
|
621
|
+
font-size: 1rem;
|
|
622
|
+
font-weight: 700;
|
|
623
|
+
}
|
|
624
|
+
// The body's trailing paragraph shouldn't add space below the alert.
|
|
625
|
+
.alert .alert-content > :last-child {
|
|
626
|
+
margin-bottom: 0;
|
|
627
|
+
}
|
|
628
|
+
|
|
601
629
|
// ============================================================================
|
|
602
630
|
// Inline help glyph — a hint attached to a word rather than to a field label.
|
|
603
631
|
// (For a field label use `.infotip`, which is a real popover button.)
|