@webority/theme 0.7.8 → 0.8.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/webority-theme.css +1 -1
- package/package.json +1 -1
- package/scss/_wui-components.scss +9 -1
- package/scss/wui/_card.scss +20 -1
- package/scss/wui/_controls.scss +61 -27
- package/scss/wui/_data.scss +4 -1
- package/scss/wui/_dock.scss +102 -0
- package/scss/wui/_flow.scss +263 -34
- package/scss/wui/_menu-motion.scss +153 -0
- package/scss/wui/_overlays.scss +221 -25
- package/scss/wui/_tone-pill.scss +23 -0
- package/scss/wui/_toolbar.scss +138 -0
- package/scss/wui/_typography.scss +45 -15
- package/scss/wui/_utilities.scss +29 -1
package/scss/wui/_flow.scss
CHANGED
|
@@ -5,9 +5,25 @@
|
|
|
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
|
+
// Every variant defaults to the brand primary — active, done and rail share one accent
|
|
26
|
+
// (no multi-colour). Colour variety is opt-in: a `.wui-step-tone-*` class or a var override.
|
|
11
27
|
// ============================================================================
|
|
12
28
|
.stepper {
|
|
13
29
|
// Full width so the flex:1 steps spread evenly across the container. Without it,
|
|
@@ -19,6 +35,18 @@
|
|
|
19
35
|
gap: 0;
|
|
20
36
|
padding: 0 8px;
|
|
21
37
|
}
|
|
38
|
+
// A STANDALONE AppStepper gets the brand (primary) accent as a DECLARED default, so a tone
|
|
39
|
+
// class placed on the stepper element itself overrides it. The wizard is excluded because
|
|
40
|
+
// its tone class rides on the wizard HOST (an ancestor of the generated header): declaring
|
|
41
|
+
// the vars on the header would block that inherited override, so the wizard leans on the
|
|
42
|
+
// var fallbacks instead — which now also default to primary. :where() keeps this at ZERO
|
|
43
|
+
// specificity, so a .wui-step-tone-* class or an inline --wui-step-* override still wins.
|
|
44
|
+
:where(.stepper:not(.wizard-stepper)) {
|
|
45
|
+
--wui-step-accent: var(--color-primary);
|
|
46
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
47
|
+
--wui-step-soft: var(--color-primary-soft);
|
|
48
|
+
--wui-step-soft-fg: var(--color-primary);
|
|
49
|
+
}
|
|
22
50
|
.step {
|
|
23
51
|
position: relative;
|
|
24
52
|
flex: 1;
|
|
@@ -34,23 +62,23 @@
|
|
|
34
62
|
.step + .step::before {
|
|
35
63
|
content: "";
|
|
36
64
|
position: absolute;
|
|
37
|
-
//
|
|
38
|
-
top:
|
|
39
|
-
left: calc(-50% +
|
|
40
|
-
right: calc(50% +
|
|
65
|
+
// Centred on the badge: half the diameter, minus 1 for the 2px line's own height.
|
|
66
|
+
top: calc(var(--wui-step-size, 28px) / 2 - 1px);
|
|
67
|
+
left: calc(-50% + var(--wui-step-size, 28px) / 2 + 4px);
|
|
68
|
+
right: calc(50% + var(--wui-step-size, 28px) / 2 + 4px);
|
|
41
69
|
height: 2px;
|
|
42
|
-
background: var(--color-border);
|
|
70
|
+
background: var(--wui-step-connector, var(--color-border));
|
|
43
71
|
z-index: 0;
|
|
44
72
|
}
|
|
45
73
|
.step.done + .step::before {
|
|
46
|
-
background: var(--color-primary);
|
|
74
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
47
75
|
}
|
|
48
76
|
.step-circle {
|
|
49
77
|
position: relative;
|
|
50
78
|
z-index: 1;
|
|
51
79
|
flex: none;
|
|
52
|
-
width: 28px;
|
|
53
|
-
height: 28px;
|
|
80
|
+
width: var(--wui-step-size, 28px);
|
|
81
|
+
height: var(--wui-step-size, 28px);
|
|
54
82
|
display: inline-grid;
|
|
55
83
|
place-items: center;
|
|
56
84
|
border: 1.5px solid var(--color-border);
|
|
@@ -61,15 +89,15 @@
|
|
|
61
89
|
color: var(--color-text-subtle);
|
|
62
90
|
}
|
|
63
91
|
.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);
|
|
92
|
+
border-color: var(--wui-step-accent, var(--color-primary));
|
|
93
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
94
|
+
color: var(--wui-step-accent-fg, var(--color-on-scrim));
|
|
95
|
+
box-shadow: 0 0 0 4px var(--wui-step-soft, var(--color-primary-soft));
|
|
68
96
|
}
|
|
69
97
|
.step.done .step-circle {
|
|
70
|
-
border-color: var(--color-primary);
|
|
71
|
-
background: var(--color-primary);
|
|
72
|
-
color: var(--color-on-scrim);
|
|
98
|
+
border-color: var(--wui-step-accent, var(--color-primary));
|
|
99
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
100
|
+
color: var(--wui-step-accent-fg, var(--color-on-scrim));
|
|
73
101
|
}
|
|
74
102
|
.step-label {
|
|
75
103
|
max-width: 130px;
|
|
@@ -101,12 +129,12 @@ button.step {
|
|
|
101
129
|
}
|
|
102
130
|
a.step:hover .step-circle,
|
|
103
131
|
button.step:hover .step-circle {
|
|
104
|
-
box-shadow: 0 0 0 4px var(--color-primary-soft);
|
|
132
|
+
box-shadow: 0 0 0 4px var(--wui-step-soft, var(--color-primary-soft));
|
|
105
133
|
transform: scale(1.04);
|
|
106
134
|
}
|
|
107
135
|
a.step:hover .step-label,
|
|
108
136
|
button.step:hover .step-label {
|
|
109
|
-
color: var(--color-primary);
|
|
137
|
+
color: var(--wui-step-accent, var(--color-primary));
|
|
110
138
|
}
|
|
111
139
|
a.step:focus-visible,
|
|
112
140
|
button.step:focus-visible {
|
|
@@ -116,8 +144,8 @@ button.step:focus-visible {
|
|
|
116
144
|
a.step:focus-visible .step-circle,
|
|
117
145
|
button.step:focus-visible .step-circle {
|
|
118
146
|
box-shadow:
|
|
119
|
-
0 0 0 4px var(--color-primary-soft),
|
|
120
|
-
0 0 0 6px var(--color-primary);
|
|
147
|
+
0 0 0 4px var(--wui-step-soft, var(--color-primary-soft)),
|
|
148
|
+
0 0 0 6px var(--wui-step-accent, var(--color-primary));
|
|
121
149
|
}
|
|
122
150
|
// A step that failed its stage — a red circle with an alert, so an invalid step
|
|
123
151
|
// reads as wrong at a glance rather than merely "not done".
|
|
@@ -173,12 +201,12 @@ button.step:focus-visible .step-circle {
|
|
|
173
201
|
transform 0.2s ease;
|
|
174
202
|
}
|
|
175
203
|
.stepper-journey .step.done .step-circle {
|
|
176
|
-
background: var(--color-
|
|
177
|
-
color: var(--color-
|
|
204
|
+
background: var(--wui-step-soft, var(--color-primary-soft));
|
|
205
|
+
color: var(--wui-step-soft-fg, var(--color-primary));
|
|
178
206
|
}
|
|
179
207
|
.stepper-journey .step.active .step-circle {
|
|
180
|
-
background: var(--color-primary);
|
|
181
|
-
color: var(--color-on-scrim);
|
|
208
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
209
|
+
color: var(--wui-step-accent-fg, var(--color-on-scrim));
|
|
182
210
|
box-shadow: none;
|
|
183
211
|
transform: scale(1.06);
|
|
184
212
|
}
|
|
@@ -199,10 +227,10 @@ button.step:focus-visible .step-circle {
|
|
|
199
227
|
color: var(--color-text-subtle);
|
|
200
228
|
}
|
|
201
229
|
.stepper-journey .step.done .step-index {
|
|
202
|
-
color: var(--color-
|
|
230
|
+
color: var(--wui-step-soft-fg, var(--color-primary));
|
|
203
231
|
}
|
|
204
232
|
.stepper-journey .step.active .step-index {
|
|
205
|
-
color: var(--color-primary);
|
|
233
|
+
color: var(--wui-step-accent, var(--color-primary));
|
|
206
234
|
}
|
|
207
235
|
.stepper-journey .step.error .step-circle {
|
|
208
236
|
background: var(--color-danger-soft);
|
|
@@ -240,7 +268,7 @@ button.step:focus-visible .step-circle {
|
|
|
240
268
|
background: var(--color-border-strong);
|
|
241
269
|
}
|
|
242
270
|
.stepper-journey .step-line.done {
|
|
243
|
-
background: var(--color-
|
|
271
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
244
272
|
}
|
|
245
273
|
// Below xl the four label+title pairs no longer fit side by side, so the bar
|
|
246
274
|
// becomes a vertical list and the connectors go away.
|
|
@@ -270,7 +298,7 @@ button.step:focus-visible .step-circle {
|
|
|
270
298
|
// left, the label and its description stacked on the right.
|
|
271
299
|
.stepper-vertical .step {
|
|
272
300
|
display: grid;
|
|
273
|
-
grid-template-columns: 28px 1fr;
|
|
301
|
+
grid-template-columns: var(--wui-step-size, 28px) 1fr;
|
|
274
302
|
column-gap: 12px;
|
|
275
303
|
// No gap between the label and its description — they read as one block; the
|
|
276
304
|
// base .step gap of 10px is for the horizontal circle→label spacing.
|
|
@@ -307,18 +335,18 @@ button.step:focus-visible .step-circle {
|
|
|
307
335
|
.stepper-vertical .step:not(:last-child)::after {
|
|
308
336
|
content: "";
|
|
309
337
|
position: absolute;
|
|
310
|
-
//
|
|
311
|
-
left:
|
|
312
|
-
top: 28px;
|
|
338
|
+
// Half the badge minus 1 for the 2px line's own width; runs from below the circle.
|
|
339
|
+
left: calc(var(--wui-step-size, 28px) / 2 - 1px);
|
|
340
|
+
top: var(--wui-step-size, 28px);
|
|
313
341
|
// Reaches through the 18px inter-step gap to meet the next circle's top; keep
|
|
314
342
|
// this in sync with the .stepper-vertical `gap`.
|
|
315
343
|
bottom: -18px;
|
|
316
344
|
width: 2px;
|
|
317
|
-
background: var(--color-border);
|
|
345
|
+
background: var(--wui-step-connector, var(--color-border));
|
|
318
346
|
z-index: 0;
|
|
319
347
|
}
|
|
320
348
|
.stepper-vertical .step.done:not(:last-child)::after {
|
|
321
|
-
background: var(--color-primary);
|
|
349
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
322
350
|
}
|
|
323
351
|
// The journey bar stacked vertically reuses its own narrow-width treatment: a plain
|
|
324
352
|
// column with the horizontal connectors dropped (a real vertical rail here would
|
|
@@ -332,15 +360,169 @@ button.step:focus-visible .step-circle {
|
|
|
332
360
|
display: none;
|
|
333
361
|
}
|
|
334
362
|
|
|
363
|
+
// .stepper-icons — large icon badges joined by a rail, with a "STEP n" eyebrow above
|
|
364
|
+
// each title. Done gets a soft-accent tint + filled connector; active is a solid-accent
|
|
365
|
+
// badge; pending is a muted badge — all one accent (brand primary by default). Built for
|
|
366
|
+
// icon-per-step flows — each step sets `icon` (a step with no icon falls back to its number).
|
|
367
|
+
// ----------------------------------------------------------------------------
|
|
368
|
+
.stepper-icons {
|
|
369
|
+
align-items: flex-start;
|
|
370
|
+
padding: 8px 8px 0;
|
|
371
|
+
}
|
|
372
|
+
.stepper-icons .step {
|
|
373
|
+
gap: 6px;
|
|
374
|
+
}
|
|
375
|
+
.stepper-icons .step-circle {
|
|
376
|
+
width: var(--wui-step-badge-size, 56px);
|
|
377
|
+
height: var(--wui-step-badge-size, 56px);
|
|
378
|
+
border: none;
|
|
379
|
+
background: var(--color-bg-muted);
|
|
380
|
+
color: var(--color-text-subtle);
|
|
381
|
+
font-size: 22px;
|
|
382
|
+
transition:
|
|
383
|
+
background 0.2s ease,
|
|
384
|
+
color 0.2s ease,
|
|
385
|
+
transform 0.2s ease;
|
|
386
|
+
}
|
|
387
|
+
// Like every variant, the icons stepper defaults to the brand primary — a solid-primary
|
|
388
|
+
// active badge, a soft-primary done badge, a primary rail. Every colour routes through the
|
|
389
|
+
// shared --wui-step-* vars, so a `.wui-step-tone-*` class or an override recolours it.
|
|
390
|
+
.stepper-icons .step.active .step-circle {
|
|
391
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
392
|
+
color: var(--wui-step-accent-fg, var(--color-on-scrim));
|
|
393
|
+
// The compact variant rings the active circle; here the solid fill carries it, so
|
|
394
|
+
// drop the ring to match the flat badge look.
|
|
395
|
+
box-shadow: none;
|
|
396
|
+
}
|
|
397
|
+
.stepper-icons .step.done .step-circle {
|
|
398
|
+
border: none;
|
|
399
|
+
background: var(--wui-step-soft, var(--color-primary-soft));
|
|
400
|
+
color: var(--wui-step-soft-fg, var(--color-primary));
|
|
401
|
+
}
|
|
402
|
+
.stepper-icons .step.error .step-circle {
|
|
403
|
+
background: var(--color-danger-soft);
|
|
404
|
+
color: var(--color-danger-text);
|
|
405
|
+
}
|
|
406
|
+
.stepper-icons .step.skipped .step-circle {
|
|
407
|
+
background: var(--color-bg-muted);
|
|
408
|
+
border: 1px dashed var(--color-border-strong);
|
|
409
|
+
color: var(--color-text-muted);
|
|
410
|
+
}
|
|
411
|
+
// The "STEP n" eyebrow sits between the badge and the title, colour-matched to the state.
|
|
412
|
+
.stepper-icons .step-index {
|
|
413
|
+
margin-top: 4px;
|
|
414
|
+
font-size: 12px;
|
|
415
|
+
font-weight: 600;
|
|
416
|
+
line-height: 1.2;
|
|
417
|
+
text-transform: uppercase;
|
|
418
|
+
letter-spacing: 0.06em;
|
|
419
|
+
color: var(--color-text-subtle);
|
|
420
|
+
}
|
|
421
|
+
.stepper-icons .step.active .step-index {
|
|
422
|
+
color: var(--wui-step-accent, var(--color-primary));
|
|
423
|
+
}
|
|
424
|
+
.stepper-icons .step.done .step-index {
|
|
425
|
+
color: var(--wui-step-soft-fg, var(--color-primary));
|
|
426
|
+
}
|
|
427
|
+
.stepper-icons .step.error .step-index {
|
|
428
|
+
color: var(--color-danger-text);
|
|
429
|
+
}
|
|
430
|
+
.stepper-icons .step-label {
|
|
431
|
+
max-width: 150px;
|
|
432
|
+
font-size: 15px;
|
|
433
|
+
font-weight: 600;
|
|
434
|
+
color: var(--color-text-subtle);
|
|
435
|
+
}
|
|
436
|
+
.stepper-icons .step.active .step-label,
|
|
437
|
+
.stepper-icons .step.done .step-label {
|
|
438
|
+
color: var(--color-text);
|
|
439
|
+
}
|
|
440
|
+
// The rail: thicker and rounded, recentred on the badge (half the diameter − 2 for the
|
|
441
|
+
// 4px line's own height), and filled with the accent once the step to its left is done.
|
|
442
|
+
.stepper-icons .step + .step::before {
|
|
443
|
+
top: calc(var(--wui-step-badge-size, 56px) / 2 - 2px);
|
|
444
|
+
left: calc(-50% + var(--wui-step-badge-size, 56px) / 2 + 8px);
|
|
445
|
+
right: calc(50% + var(--wui-step-badge-size, 56px) / 2 + 8px);
|
|
446
|
+
height: 4px;
|
|
447
|
+
border-radius: 999px;
|
|
448
|
+
background: var(--wui-step-connector, var(--color-border));
|
|
449
|
+
}
|
|
450
|
+
.stepper-icons .step.done + .step::before {
|
|
451
|
+
background: var(--wui-step-accent, var(--color-primary));
|
|
452
|
+
}
|
|
453
|
+
// The compact hover ring is calibrated to the 28px badge; the 56px icon badge just
|
|
454
|
+
// lifts on hover instead.
|
|
455
|
+
.stepper-icons a.step:hover .step-circle,
|
|
456
|
+
.stepper-icons button.step:hover .step-circle {
|
|
457
|
+
box-shadow: none;
|
|
458
|
+
transform: scale(1.04);
|
|
459
|
+
}
|
|
460
|
+
// Below md the six badges no longer fit across, so the icons stepper stacks into a
|
|
461
|
+
// vertical list — the shared .stepper-vertical rules take over from here.
|
|
462
|
+
@include media-breakpoint-down(md) {
|
|
463
|
+
.stepper-icons.stepper-icons {
|
|
464
|
+
flex-direction: column;
|
|
465
|
+
align-items: stretch;
|
|
466
|
+
gap: 20px;
|
|
467
|
+
}
|
|
468
|
+
.stepper-icons.stepper-icons .step {
|
|
469
|
+
flex-direction: row;
|
|
470
|
+
align-items: center;
|
|
471
|
+
gap: 14px;
|
|
472
|
+
text-align: left;
|
|
473
|
+
}
|
|
474
|
+
.stepper-icons.stepper-icons .step + .step::before {
|
|
475
|
+
content: none;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
335
479
|
@media (prefers-reduced-motion: reduce) {
|
|
336
480
|
a.step:hover .step-circle,
|
|
337
481
|
button.step:hover .step-circle,
|
|
338
|
-
.stepper-journey .step-circle
|
|
482
|
+
.stepper-journey .step-circle,
|
|
483
|
+
.stepper-icons .step-circle {
|
|
339
484
|
transition: none;
|
|
340
485
|
transform: none;
|
|
341
486
|
}
|
|
342
487
|
}
|
|
343
488
|
|
|
489
|
+
// Tone presets — flip the whole accent (active fill, done rail, ring, journey/icons
|
|
490
|
+
// done tint) to a semantic ramp in one class. Because custom properties inherit, the
|
|
491
|
+
// class can sit on the stepper itself OR on an ancestor (the wizard host), and an inline
|
|
492
|
+
// `style="--wui-step-accent: …"` on a closer element still wins over it. Placing the
|
|
493
|
+
// class recolours every variant consistently; error steps stay red regardless (semantic).
|
|
494
|
+
// ----------------------------------------------------------------------------
|
|
495
|
+
.wui-step-tone-primary {
|
|
496
|
+
--wui-step-accent: var(--color-primary);
|
|
497
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
498
|
+
--wui-step-soft: var(--color-primary-soft);
|
|
499
|
+
--wui-step-soft-fg: var(--color-primary);
|
|
500
|
+
}
|
|
501
|
+
.wui-step-tone-success {
|
|
502
|
+
--wui-step-accent: var(--color-success);
|
|
503
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
504
|
+
--wui-step-soft: var(--color-success-soft);
|
|
505
|
+
--wui-step-soft-fg: var(--color-success-text);
|
|
506
|
+
}
|
|
507
|
+
.wui-step-tone-warning {
|
|
508
|
+
--wui-step-accent: var(--color-warning);
|
|
509
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
510
|
+
--wui-step-soft: var(--color-warning-soft);
|
|
511
|
+
--wui-step-soft-fg: var(--color-warning-text);
|
|
512
|
+
}
|
|
513
|
+
.wui-step-tone-danger {
|
|
514
|
+
--wui-step-accent: var(--color-danger);
|
|
515
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
516
|
+
--wui-step-soft: var(--color-danger-soft);
|
|
517
|
+
--wui-step-soft-fg: var(--color-danger-text);
|
|
518
|
+
}
|
|
519
|
+
.wui-step-tone-info {
|
|
520
|
+
--wui-step-accent: var(--color-info);
|
|
521
|
+
--wui-step-accent-fg: var(--color-on-scrim);
|
|
522
|
+
--wui-step-soft: var(--color-info-soft);
|
|
523
|
+
--wui-step-soft-fg: var(--color-info-text);
|
|
524
|
+
}
|
|
525
|
+
|
|
344
526
|
// ============================================================================
|
|
345
527
|
// Pricing card. A tier's name, price, pitch, feature list and CTA.
|
|
346
528
|
//
|
|
@@ -616,4 +798,51 @@ button.step:focus-visible .step-circle {
|
|
|
616
798
|
.form-actions-sticky {
|
|
617
799
|
transition: none;
|
|
618
800
|
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// ============================================================================
|
|
804
|
+
// AppWizard (<wui-wizard>) — stepper header + one visible step panel + a sticky
|
|
805
|
+
// Back/Skip/Next/Finish footer. Composes .stepper and .form-actions above.
|
|
806
|
+
// ============================================================================
|
|
807
|
+
wui-wizard {
|
|
808
|
+
display: block;
|
|
809
|
+
width: 100%;
|
|
810
|
+
}
|
|
811
|
+
// Custom elements don't inherit the UA `[hidden] { display: none }` once we give the
|
|
812
|
+
// tag its own `display`, so the inactive panels need it stated explicitly.
|
|
813
|
+
wui-wizard-step {
|
|
814
|
+
display: block;
|
|
815
|
+
}
|
|
816
|
+
wui-wizard-step[hidden] {
|
|
817
|
+
display: none;
|
|
818
|
+
}
|
|
819
|
+
.wizard-stepper {
|
|
820
|
+
margin-bottom: 24px;
|
|
821
|
+
}
|
|
822
|
+
// A skipped step reads as "passed over", not "achieved": a dashed, muted circle so it
|
|
823
|
+
// is visibly distinct from a ticked (done) step.
|
|
824
|
+
.step.skipped .step-circle {
|
|
825
|
+
background: var(--color-bg-muted);
|
|
826
|
+
border: 1px dashed var(--color-border-strong);
|
|
827
|
+
color: var(--color-text-muted);
|
|
828
|
+
}
|
|
829
|
+
.wizard-panel {
|
|
830
|
+
// A resting min-height so the footer doesn't jump as steps of different length
|
|
831
|
+
// swap in; content taller than this simply grows the panel.
|
|
832
|
+
min-height: 96px;
|
|
833
|
+
}
|
|
834
|
+
.wizard-footer {
|
|
835
|
+
// The sticky Back/Skip/Next/Finish bar — pinned to the bottom of a scrolling flow
|
|
836
|
+
// so the actions (and the Skip on an optional step) are always in reach. Runs flush on
|
|
837
|
+
// the flow (no divider or fill) — the buttons alone read as the footer.
|
|
838
|
+
position: sticky;
|
|
839
|
+
bottom: 0;
|
|
840
|
+
margin-top: 24px;
|
|
841
|
+
padding: 16px 0;
|
|
842
|
+
z-index: 1;
|
|
843
|
+
}
|
|
844
|
+
.wizard-footer-actions {
|
|
845
|
+
display: flex;
|
|
846
|
+
align-items: center;
|
|
847
|
+
gap: 12px;
|
|
619
848
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// ── Menu open motion ──
|
|
2
|
+
// One entrance for every menu-like overlay: Bootstrap dropdown menus (AppDropdown,
|
|
3
|
+
// AppWorkspaceSwitcher), popovers (AppPopover), and every portalled wui-* panel
|
|
4
|
+
// (select / autocomplete / multiselect / phone / date / date-range / time).
|
|
5
|
+
//
|
|
6
|
+
// The motion is a PRODUCT-LEVEL choice, not a per-component prop — menus are opened by
|
|
7
|
+
// Bootstrap/react-bootstrap internals, and mixing motions inside one product reads as a
|
|
8
|
+
// bug. A product picks once, on the root element:
|
|
9
|
+
//
|
|
10
|
+
// <html data-wui-menu-motion="drop"> zoom + fade + a 6px drop out of the trigger (default)
|
|
11
|
+
// <html data-wui-menu-motion="zoom"> zoom + fade only (the quietest)
|
|
12
|
+
// <html data-wui-menu-motion="spring"> elastic overshoot (playful; marketing surfaces)
|
|
13
|
+
// <html data-wui-menu-motion="unfold"> scales open vertically, like a sheet
|
|
14
|
+
// <html data-wui-menu-motion="none"> no entrance
|
|
15
|
+
//
|
|
16
|
+
// Two load-bearing choices:
|
|
17
|
+
// - The keyframes animate the STANDALONE `scale` / `translate` properties, never
|
|
18
|
+
// `transform` — Popper and anchorOverlay position these panels via transform/fixed
|
|
19
|
+
// coordinates, and the standalone properties compose with that instead of clobbering.
|
|
20
|
+
// - Panels shown by removing `hidden` (the wui-* set) replay the animation on every
|
|
21
|
+
// reveal for free; Bootstrap surfaces key off `.show`. Close stays instant: the wui
|
|
22
|
+
// elements hide with `hidden` in the same tick, and delaying that for an exit
|
|
23
|
+
// animation would change observable close timing everywhere.
|
|
24
|
+
//
|
|
25
|
+
// Part of the wui-components layer — see _wui-components.scss for load order.
|
|
26
|
+
|
|
27
|
+
:root {
|
|
28
|
+
--wui-menu-anim: wui-menu-drop;
|
|
29
|
+
--wui-menu-anim-duration: 200ms;
|
|
30
|
+
--wui-menu-anim-ease: var(--wui-ease-out-quart);
|
|
31
|
+
}
|
|
32
|
+
:root[data-wui-menu-motion="zoom"] {
|
|
33
|
+
--wui-menu-anim: wui-menu-zoom;
|
|
34
|
+
--wui-menu-anim-duration: 160ms;
|
|
35
|
+
}
|
|
36
|
+
:root[data-wui-menu-motion="spring"] {
|
|
37
|
+
--wui-menu-anim: wui-menu-spring;
|
|
38
|
+
--wui-menu-anim-duration: 320ms;
|
|
39
|
+
--wui-menu-anim-ease: var(--wui-ease-elastic);
|
|
40
|
+
}
|
|
41
|
+
:root[data-wui-menu-motion="unfold"] {
|
|
42
|
+
--wui-menu-anim: wui-menu-unfold;
|
|
43
|
+
--wui-menu-anim-duration: 220ms;
|
|
44
|
+
}
|
|
45
|
+
:root[data-wui-menu-motion="none"] {
|
|
46
|
+
--wui-menu-anim: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@keyframes wui-menu-drop {
|
|
50
|
+
from {
|
|
51
|
+
opacity: 0;
|
|
52
|
+
scale: 0.95;
|
|
53
|
+
translate: 0 var(--wui-menu-drop, -6px);
|
|
54
|
+
}
|
|
55
|
+
to {
|
|
56
|
+
opacity: 1;
|
|
57
|
+
scale: 1;
|
|
58
|
+
translate: 0 0;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
@keyframes wui-menu-zoom {
|
|
62
|
+
from {
|
|
63
|
+
opacity: 0;
|
|
64
|
+
scale: 0.95;
|
|
65
|
+
}
|
|
66
|
+
to {
|
|
67
|
+
opacity: 1;
|
|
68
|
+
scale: 1;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
@keyframes wui-menu-spring {
|
|
72
|
+
from {
|
|
73
|
+
opacity: 0;
|
|
74
|
+
scale: 0.9;
|
|
75
|
+
translate: 0 var(--wui-menu-drop, -4px);
|
|
76
|
+
}
|
|
77
|
+
to {
|
|
78
|
+
opacity: 1;
|
|
79
|
+
scale: 1;
|
|
80
|
+
translate: 0 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
@keyframes wui-menu-unfold {
|
|
84
|
+
from {
|
|
85
|
+
opacity: 0;
|
|
86
|
+
scale: 0.97 0.82;
|
|
87
|
+
}
|
|
88
|
+
to {
|
|
89
|
+
opacity: 1;
|
|
90
|
+
scale: 1 1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.dropdown-menu.show,
|
|
95
|
+
.popover.show,
|
|
96
|
+
.search-select-menu:not([hidden]),
|
|
97
|
+
.country-dropdown-menu:not([hidden]),
|
|
98
|
+
.datepicker-pop:not([hidden]),
|
|
99
|
+
.daterange-pop:not([hidden]),
|
|
100
|
+
.timepicker-pop:not([hidden]) {
|
|
101
|
+
animation: var(--wui-menu-anim) var(--wui-menu-anim-duration) var(--wui-menu-anim-ease);
|
|
102
|
+
transform-origin: top;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// End-aligned dropdowns zoom from the corner they attach to.
|
|
106
|
+
.dropdown-menu-end.show {
|
|
107
|
+
transform-origin: top right;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Opening upward: origin flips to the bottom edge and the drop comes from below.
|
|
111
|
+
.search-select-menu.drop-up,
|
|
112
|
+
.country-dropdown-menu.drop-up,
|
|
113
|
+
.datepicker-pop.drop-up,
|
|
114
|
+
.daterange-pop.drop-up,
|
|
115
|
+
.timepicker-pop.drop-up,
|
|
116
|
+
.dropdown-menu.show[data-popper-placement^="top"],
|
|
117
|
+
.dropup .dropdown-menu.show {
|
|
118
|
+
--wui-menu-drop: 6px;
|
|
119
|
+
|
|
120
|
+
transform-origin: bottom;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Popover follows its Popper side; the drop always comes from the trigger's direction.
|
|
124
|
+
.popover.show[data-popper-placement^="top"] {
|
|
125
|
+
--wui-menu-drop: 6px;
|
|
126
|
+
|
|
127
|
+
transform-origin: bottom center;
|
|
128
|
+
}
|
|
129
|
+
.popover.show[data-popper-placement^="right"] {
|
|
130
|
+
--wui-menu-drop: 0px;
|
|
131
|
+
|
|
132
|
+
transform-origin: left center;
|
|
133
|
+
}
|
|
134
|
+
.popover.show[data-popper-placement^="left"] {
|
|
135
|
+
--wui-menu-drop: 0px;
|
|
136
|
+
|
|
137
|
+
transform-origin: right center;
|
|
138
|
+
}
|
|
139
|
+
.popover.show[data-popper-placement^="bottom"] {
|
|
140
|
+
transform-origin: top center;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@media (prefers-reduced-motion: reduce) {
|
|
144
|
+
.dropdown-menu.show,
|
|
145
|
+
.popover.show,
|
|
146
|
+
.search-select-menu:not([hidden]),
|
|
147
|
+
.country-dropdown-menu:not([hidden]),
|
|
148
|
+
.datepicker-pop:not([hidden]),
|
|
149
|
+
.daterange-pop:not([hidden]),
|
|
150
|
+
.timepicker-pop:not([hidden]) {
|
|
151
|
+
animation: none;
|
|
152
|
+
}
|
|
153
|
+
}
|