@ashley-shrok/viewmodel-shell 5.1.2 → 6.0.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/agent-skill.md +69 -0
- package/dist/browser.d.ts +42 -0
- package/dist/browser.js +1532 -3
- package/dist/index.d.ts +285 -5
- package/dist/server.js +6 -0
- package/dist/tui.js +41 -0
- package/package.json +3 -1
- package/styles/default.css +334 -1
package/styles/default.css
CHANGED
|
@@ -29,6 +29,21 @@
|
|
|
29
29
|
--vms-error: #c2453d;
|
|
30
30
|
--vms-error-glow: rgba(194, 69, 61, 0.10);
|
|
31
31
|
--vms-warning: #8a630d;
|
|
32
|
+
/* Warning is the ONE tone with a polarity split. --vms-warning is deliberately
|
|
33
|
+
DARK on light themes because it doubles as a TEXT/border color (.vms-text--warning,
|
|
34
|
+
button/badge outline) and warning-colored TEXT on a light surface must be dark to
|
|
35
|
+
clear WCAG-AA — a bright yellow text on white is unreadable. But a warning FILL has
|
|
36
|
+
no such constraint: the standard design-system pattern (Bootstrap/Material) is a
|
|
37
|
+
BRIGHT yellow fill with a DARK foreground. --vms-warning-fill + --vms-on-warning-fill
|
|
38
|
+
are that pair — used on every SOLID warning fill (toast, primary badge/button, the
|
|
39
|
+
toned steps marker) so warning actually reads as a yellow that grabs attention on
|
|
40
|
+
light themes, while staying AA (dark #2a2205 on #e0a823 = 7.37:1). Theme-independent
|
|
41
|
+
(a solid amber fill reads the same on any page surface); dark themes need no override
|
|
42
|
+
— their --vms-warning is already #e0a823, so this ALSO fixes the white-on-bright-amber
|
|
43
|
+
fill that failed AA on dark themes (2.14:1). Tints (section/table/chip) keep the base
|
|
44
|
+
--vms-warning as their own consistent family. */
|
|
45
|
+
--vms-warning-fill: #e0a823;
|
|
46
|
+
--vms-on-warning-fill: #2a2205;
|
|
32
47
|
--vms-priority-high: #d76410;
|
|
33
48
|
--vms-success: #2da359;
|
|
34
49
|
--vms-info: #2277dd;
|
|
@@ -473,6 +488,32 @@ body:has(.vms-page--fill) { margin: 0; }
|
|
|
473
488
|
text-transform: uppercase;
|
|
474
489
|
letter-spacing: 0.05em;
|
|
475
490
|
}
|
|
491
|
+
/* Per-tile tone (StatItem.tone) — a toned stat becomes a subtly tinted chip
|
|
492
|
+
(surface tint + colored border, the SAME color-mix formula as Section tone, so
|
|
493
|
+
it inherits that surface's already-AA-cleared text contrast) so an unhealthy
|
|
494
|
+
stat reads at a glance. Only toned items get the chip surface; neutral items
|
|
495
|
+
stay byte-identical to today's inline stat. --_tone resolves per tone below. */
|
|
496
|
+
.vms-stat-bar__item--tone-danger { --_tone: var(--vms-error); }
|
|
497
|
+
.vms-stat-bar__item--tone-warning { --_tone: var(--vms-warning); }
|
|
498
|
+
.vms-stat-bar__item--tone-success { --_tone: var(--vms-success); }
|
|
499
|
+
.vms-stat-bar__item--tone-info { --_tone: var(--vms-info); }
|
|
500
|
+
.vms-stat-bar__item--toned {
|
|
501
|
+
align-items: center;
|
|
502
|
+
gap: var(--vms-space-2xs);
|
|
503
|
+
padding: var(--vms-space-2xs) var(--vms-space-sm);
|
|
504
|
+
border: 1px solid var(--_tone);
|
|
505
|
+
border-radius: var(--vms-radius-md);
|
|
506
|
+
background: color-mix(in srgb, var(--_tone) 14%, var(--vms-surface));
|
|
507
|
+
}
|
|
508
|
+
/* The tint + border carry the status (the Section-tone model); the value + label
|
|
509
|
+
stay NEUTRAL and readable rather than tone-colored — tone text on its own 14%
|
|
510
|
+
tint fails WCAG-AA (success bottomed at 2.79:1 across the light themes), while
|
|
511
|
+
neutral text on the tint clears it exactly as Section tone's neutral text does. */
|
|
512
|
+
.vms-stat-bar__item--toned .vms-stat-bar__value { color: var(--vms-text); }
|
|
513
|
+
/* Label strengthens from muted to full text on a toned chip: muted on the 14%
|
|
514
|
+
tint bottoms at 4.21:1 (just under the 4.5 AA-text bar), and an emphasized chip
|
|
515
|
+
reads better with a solid label anyway. Full text on the tint is 11.14:1. */
|
|
516
|
+
.vms-stat-bar__item--toned .vms-stat-bar__label { color: var(--vms-text); }
|
|
476
517
|
|
|
477
518
|
/* ── Form ── */
|
|
478
519
|
.vms-form { display: flex; flex-direction: column; gap: var(--vms-space-sm); align-items: stretch; }
|
|
@@ -574,6 +615,231 @@ select.vms-field__input { cursor: pointer; padding-right: var(--vms-space-xl);
|
|
|
574
615
|
overflow: auto;
|
|
575
616
|
}
|
|
576
617
|
|
|
618
|
+
/* Lookup / reference picker (FieldNode inputType="lookup" / "lookup-multiple",
|
|
619
|
+
Phase 21) — an editable combobox whose listbox popup floats over the page.
|
|
620
|
+
Built entirely from the existing .vms-field__* tokens: no new colors, no new
|
|
621
|
+
custom properties, so every theme recolors it automatically. */
|
|
622
|
+
.vms-field--lookup { position: relative; }
|
|
623
|
+
.vms-field__popup {
|
|
624
|
+
/* Anchored to .vms-field--lookup's positioning context, floating over what
|
|
625
|
+
follows so the popup never reflows the form when it opens. */
|
|
626
|
+
position: absolute;
|
|
627
|
+
top: 100%;
|
|
628
|
+
left: 0;
|
|
629
|
+
right: 0;
|
|
630
|
+
z-index: 20;
|
|
631
|
+
margin-top: var(--vms-space-2xs);
|
|
632
|
+
max-height: 16rem;
|
|
633
|
+
overflow-y: auto;
|
|
634
|
+
background: var(--vms-surface);
|
|
635
|
+
border: 1px solid var(--vms-border);
|
|
636
|
+
border-radius: var(--vms-radius);
|
|
637
|
+
/* A literal rgba, matching the toast overlay's shadow (the house precedent
|
|
638
|
+
for a floating surface) — there is no --vms-shadow token, and inventing
|
|
639
|
+
one would mean touching all 12 themes for a drop shadow. */
|
|
640
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.24);
|
|
641
|
+
color-scheme: var(--vms-color-scheme);
|
|
642
|
+
}
|
|
643
|
+
/* The popup is rendered ALWAYS and hidden when closed (aria-controls must stay
|
|
644
|
+
valid while hidden). This rule is LOAD-BEARING: the UA's [hidden] default is
|
|
645
|
+
display:none, but the block above would otherwise win on specificity and the
|
|
646
|
+
popup would be permanently visible. */
|
|
647
|
+
.vms-field__popup[hidden] { display: none; }
|
|
648
|
+
/* The lookup's aria-live status regions and its assistive hint: available to
|
|
649
|
+
assistive tech, invisible on screen. Deliberately NOT display:none and NOT
|
|
650
|
+
visibility:hidden — both REMOVE the element from the accessibility tree, so a
|
|
651
|
+
live region styled that way is never announced and the hint is never read.
|
|
652
|
+
This is the standard visually-hidden clip; it must stay clipped-but-rendered. */
|
|
653
|
+
.vms-field__live {
|
|
654
|
+
position: absolute;
|
|
655
|
+
width: 1px;
|
|
656
|
+
height: 1px;
|
|
657
|
+
margin: -1px;
|
|
658
|
+
padding: 0;
|
|
659
|
+
border: 0;
|
|
660
|
+
overflow: hidden;
|
|
661
|
+
clip: rect(0 0 0 0);
|
|
662
|
+
clip-path: inset(50%);
|
|
663
|
+
white-space: nowrap;
|
|
664
|
+
}
|
|
665
|
+
.vms-field__option {
|
|
666
|
+
padding: var(--vms-space-xs) var(--vms-space-md);
|
|
667
|
+
font-size: var(--vms-text-md);
|
|
668
|
+
line-height: var(--vms-control-line);
|
|
669
|
+
color: var(--vms-text);
|
|
670
|
+
cursor: pointer;
|
|
671
|
+
/* §7 item 33 (reflow) — option text WRAPS rather than truncating: a
|
|
672
|
+
candidate is a person's or record's name, not a status word, and at high
|
|
673
|
+
magnification a truncated option is unreadable. The border delimits a
|
|
674
|
+
wrapped option so it never reads as two separate suggestions (GOV.UK's 12x
|
|
675
|
+
tester: "the words just looked like separate suggestions that didn't make
|
|
676
|
+
much sense"). */
|
|
677
|
+
overflow-wrap: anywhere;
|
|
678
|
+
border-bottom: 1px solid var(--vms-border);
|
|
679
|
+
}
|
|
680
|
+
.vms-field__option:last-child { border-bottom: none; }
|
|
681
|
+
.vms-field__option:hover { background: var(--vms-surface-2); }
|
|
682
|
+
/* The active (aria-activedescendant) option. DOM focus stays in the input, so
|
|
683
|
+
:focus cannot express this — the highlight must be driven off aria-selected,
|
|
684
|
+
which is the same fact the live region announces. */
|
|
685
|
+
.vms-field__option[aria-selected="true"] {
|
|
686
|
+
background: var(--vms-accent-glow);
|
|
687
|
+
color: var(--vms-text);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/* ── lookup chips (Phase 21, LOOK-03; BOTH modes since 21-14 / D2a) ──
|
|
691
|
+
The selection, rendered OUTSIDE the combobox as chip(s) — for `lookup` AND
|
|
692
|
+
`lookup-multiple`, from ONE implementation. The only difference between the
|
|
693
|
+
two is arity (single replaces on pick, multi appends), which lives in
|
|
694
|
+
browser.ts and has no expression here at all: a chip is a chip.
|
|
695
|
+
|
|
696
|
+
🚨 We diverge from SLDS deliberately and it is worth knowing why, because the
|
|
697
|
+
survey says the opposite: Salesforce renders single-select's selection INSIDE
|
|
698
|
+
the input and ships no pill element for single at all. 21-13 followed them,
|
|
699
|
+
and the operator found that model has NOWHERE TO CLICK TO TYPE — the pill was
|
|
700
|
+
the input, so clicking in just appended to the name. Their model is coherent
|
|
701
|
+
given clear-then-search; ours is coherent given always-typeable. (There is no
|
|
702
|
+
`.vms-field--lookup-selected` any more; do not resurrect it.)
|
|
703
|
+
|
|
704
|
+
Structure is role=list/listitem + a real <button> (design §7 item 24) — see
|
|
705
|
+
browser.ts. This is presentation only; nothing here is on the wire.
|
|
706
|
+
|
|
707
|
+
⚠️ CONTRAST: the chip's fg/bg pair is NOT covered by the fixed 13-pair
|
|
708
|
+
check:aa-contrast gate, so it is hand-measured across the shipped default +
|
|
709
|
+
all 12 themes: 10.63:1 worst (dark-*), 13.60:1 (light-*), vs a 4.5:1 text bar.
|
|
710
|
+
Single-select reuses this exact pair rather than inventing a token, so it adds
|
|
711
|
+
no new pair to measure. Re-measure if --_chip-tone ever stops being
|
|
712
|
+
--vms-text. */
|
|
713
|
+
.vms-field__chips {
|
|
714
|
+
display: flex;
|
|
715
|
+
flex-wrap: wrap;
|
|
716
|
+
gap: var(--vms-space-2xs);
|
|
717
|
+
/* Reset the <ul>. NOTE this is exactly why browser.ts sets role="list"
|
|
718
|
+
EXPLICITLY: `list-style: none` strips the implicit list/listitem roles in
|
|
719
|
+
Safari/VoiceOver, so a styled <ul> silently stops being a list — the
|
|
720
|
+
accessibility regression is caused BY this line and repaired in the
|
|
721
|
+
renderer. Do not "clean up" that seemingly-redundant role. */
|
|
722
|
+
list-style: none;
|
|
723
|
+
margin: 0;
|
|
724
|
+
padding: 0;
|
|
725
|
+
}
|
|
726
|
+
.vms-field__chip {
|
|
727
|
+
/* The .vms-badge private-tone technique (default.css, .vms-badge): ONE private
|
|
728
|
+
custom property holds the working color and the fill, text and border all
|
|
729
|
+
derive from it, so EVERY THEME RECOLORS AUTOMATICALLY — --vms-text and
|
|
730
|
+
--vms-surface are theme-owned. Retoning a chip would be one line. */
|
|
731
|
+
--_chip-tone: var(--vms-text);
|
|
732
|
+
display: inline-flex;
|
|
733
|
+
align-items: center;
|
|
734
|
+
/* Hug content in ANY parent layout. Carried over from .vms-badge's comment
|
|
735
|
+
(written in 5.1.2 for exactly this failure mode) because the chip hits it
|
|
736
|
+
IDENTICALLY: a chip is semantically inline, but as a flex item it is
|
|
737
|
+
BLOCKIFIED (inline-flex → flex) and the chip row's align-items would then
|
|
738
|
+
stretch it. A definite cross-size opts out of that stretch —
|
|
739
|
+
align-items:stretch only stretches items whose cross size is `auto`.
|
|
740
|
+
Deliberately NOT align-self:start, which would top-anchor the chip since a
|
|
741
|
+
child's align-self beats the parent's align-items. */
|
|
742
|
+
width: fit-content;
|
|
743
|
+
max-width: 100%;
|
|
744
|
+
gap: var(--vms-space-2xs);
|
|
745
|
+
font-size: var(--vms-text-xs);
|
|
746
|
+
font-weight: 600;
|
|
747
|
+
/* Not the badge's `1`: a chip's text WRAPS (below), and line-height:1 makes
|
|
748
|
+
wrapped lines collide. */
|
|
749
|
+
line-height: 1.35;
|
|
750
|
+
/* Tighter on the right — the remove button carries its own hit area. */
|
|
751
|
+
padding: 0.2em 0.3em 0.2em 0.6em;
|
|
752
|
+
border-radius: 999px;
|
|
753
|
+
/* 🚨 DELIBERATELY NOT `white-space: nowrap` — the ONE thing not copied from
|
|
754
|
+
.vms-badge, and the easiest to reintroduce by "consistency". Design §7 item
|
|
755
|
+
33: chip text must WRAP WITHOUT TRUNCATION. A badge is a short status word;
|
|
756
|
+
a chip holds a PERSON'S NAME. GOV.UK's 12x-magnification tester on the
|
|
757
|
+
truncation failure: "Some larger country names may take over two lines. It
|
|
758
|
+
wasn't always clear to him that this had happened — the words just looked
|
|
759
|
+
like separate suggestions that didn't make much sense." The pill border-
|
|
760
|
+
radius + the surface knockout are what delimit a wrapped chip so it never
|
|
761
|
+
reads as two. (The popup's options carry the same rule and their own
|
|
762
|
+
delimiting border — see .vms-field__option.) */
|
|
763
|
+
overflow-wrap: anywhere;
|
|
764
|
+
/* The polarity-adaptive knockout — the house technique, used 18x in this file.
|
|
765
|
+
Mixing TOWARD --vms-surface (never toward white/black) auto-adapts to light
|
|
766
|
+
AND dark themes with ZERO per-theme deepening.
|
|
767
|
+
⚠️ PROVISIONAL MIX RATIO — 12%, not the badge's 16%, and Plan 21-09's
|
|
768
|
+
hand-check owns the final number. Two reasons it must not simply inherit
|
|
769
|
+
16%: (1) the fg/bg pair here is a NEW one the fixed 13-pair check:aa-contrast
|
|
770
|
+
gate does NOT auto-cover; (2) the badge's 16% was tuned for a small badge on
|
|
771
|
+
a PAGE surface. This is deliberately conservative — the tone is --vms-text
|
|
772
|
+
(near-maximal contrast against a 12% tint of ITSELF in the surface), not the
|
|
773
|
+
badge's --vms-text-muted, because a chip carries CONTENT (a name) rather
|
|
774
|
+
than muted status. The chip's background is opaque, so the field's input
|
|
775
|
+
backdrop does not enter the contrast pair. */
|
|
776
|
+
background: color-mix(in srgb, var(--_chip-tone) 12%, var(--vms-surface));
|
|
777
|
+
color: var(--_chip-tone);
|
|
778
|
+
border: 1px solid transparent;
|
|
779
|
+
}
|
|
780
|
+
/* §7 item 31 — the two-step Backspace's ARMED chip: the first press highlights
|
|
781
|
+
the last chip rather than deleting it. This is the VISUAL half only; the
|
|
782
|
+
announcement is the half that matters (browser.ts), because an arm that were
|
|
783
|
+
only a CSS class would leave an AT user pressing Backspace, hearing nothing,
|
|
784
|
+
pressing again, and deleting something they were never told about. Border, not
|
|
785
|
+
a fill swap, so it cannot disturb the contrast pair above. */
|
|
786
|
+
.vms-field__chip--armed { border-color: var(--_chip-tone); }
|
|
787
|
+
.vms-field__chip-remove {
|
|
788
|
+
display: inline-flex;
|
|
789
|
+
align-items: center;
|
|
790
|
+
justify-content: center;
|
|
791
|
+
/* Never let the button shrink or wrap away from its label — the chip's text
|
|
792
|
+
wraps; its remove affordance must not. */
|
|
793
|
+
flex: none;
|
|
794
|
+
align-self: flex-start;
|
|
795
|
+
width: 1.4em;
|
|
796
|
+
height: 1.4em;
|
|
797
|
+
padding: 0;
|
|
798
|
+
border: 0;
|
|
799
|
+
border-radius: 999px;
|
|
800
|
+
background: transparent;
|
|
801
|
+
/* Inherit the chip's tone rather than re-deriving it, so a retoned chip keeps
|
|
802
|
+
a consistent remove button for free. */
|
|
803
|
+
color: inherit;
|
|
804
|
+
font-family: inherit;
|
|
805
|
+
font-size: 1.1em;
|
|
806
|
+
line-height: 1;
|
|
807
|
+
cursor: pointer;
|
|
808
|
+
}
|
|
809
|
+
.vms-field__chip-remove:hover {
|
|
810
|
+
background: color-mix(in srgb, var(--_chip-tone) 22%, transparent);
|
|
811
|
+
}
|
|
812
|
+
/* The chip is INTERACTIVE where the badge is inert, so its remove button needs a
|
|
813
|
+
visible focus ring: it is a REAL focusable button (§7 item 26 gives the chips a
|
|
814
|
+
roving tabindex precisely so DOM focus lands here), and it is reachable by
|
|
815
|
+
keyboard alone. :focus-visible, so a mouse click doesn't ring it.
|
|
816
|
+
|
|
817
|
+
🚨 DELIBERATELY --_chip-tone, NOT --vms-accent (which is what
|
|
818
|
+
.vms-field__input:focus uses, and what this rule used before Plan 21-09's
|
|
819
|
+
hand-check). Measured, not assumed: --vms-accent clears the 3:1 non-text bar
|
|
820
|
+
(SC 1.4.11) against --vms-surface on all 13 targets, but only BARELY on
|
|
821
|
+
light-amber/light-green/light-teal (3.34 / 3.23 / 3.28). The chip's fill is a
|
|
822
|
+
TINTED surface, and that tint eats the entire remaining margin — the accent
|
|
823
|
+
ring measures 2.63 / 2.54 / 2.58 against the chip fill on those three themes:
|
|
824
|
+
a FAILING focus indicator on a keyboard-only affordance.
|
|
825
|
+
|
|
826
|
+
The mix ratio is NOT the lever, which is the non-obvious part: the ring still
|
|
827
|
+
fails at a 4% tint and only reaches 3.10:1 at 2% — a chip with no visible fill
|
|
828
|
+
at all. No chip worth rendering can rescue the accent here.
|
|
829
|
+
|
|
830
|
+
--_chip-tone is the structural fix and needs no per-theme rule: it is the same
|
|
831
|
+
polarity-adaptive knockout pair as the chip's TEXT (mixing toward
|
|
832
|
+
--vms-surface), so it inherits that pair's measured headroom — 10.63:1 worst
|
|
833
|
+
(dark-*), 13.60:1 (light-*), vs a 3:1 bar. It is also what the chip's own
|
|
834
|
+
private-tone technique already does everywhere else: .vms-field__chip--armed
|
|
835
|
+
borders with it and this button's `color` inherits it. The accent ring was the
|
|
836
|
+
outlier, not the convention. Re-measure if --_chip-tone ever stops being
|
|
837
|
+
--vms-text. */
|
|
838
|
+
.vms-field__chip-remove:focus-visible {
|
|
839
|
+
outline: 2px solid var(--_chip-tone);
|
|
840
|
+
outline-offset: 1px;
|
|
841
|
+
}
|
|
842
|
+
|
|
577
843
|
/* Form-collected checkbox (FieldNode inputType="checkbox") — inline label. */
|
|
578
844
|
.vms-field--checkbox { flex-direction: row; align-items: center; gap: var(--vms-space-xs); }
|
|
579
845
|
.vms-field--checkbox .vms-field__input {
|
|
@@ -650,6 +916,16 @@ select.vms-field__input { cursor: pointer; padding-right: var(--vms-space-xl);
|
|
|
650
916
|
border-color: var(--_btn-tone);
|
|
651
917
|
color: #fff;
|
|
652
918
|
}
|
|
919
|
+
/* Warning is the polarity exception: a filled warning button uses the bright fill +
|
|
920
|
+
dark label (white on warning fails AA — 3.2/2.14:1 light/dark; see --vms-warning-fill).
|
|
921
|
+
Border matches the fill (no rim) — same as every other primary tone, which is the
|
|
922
|
+
conventional filled-warning look (cf. Bootstrap .btn-warning). The dark label + filled
|
|
923
|
+
shape identify the control; a dark rim read as out-of-place next to danger/success/info. */
|
|
924
|
+
.vms-button--warning.vms-button--primary {
|
|
925
|
+
background: var(--vms-warning-fill);
|
|
926
|
+
border-color: var(--vms-warning-fill);
|
|
927
|
+
color: var(--vms-on-warning-fill);
|
|
928
|
+
}
|
|
653
929
|
.vms-button--primary:hover { filter: brightness(1.1); }
|
|
654
930
|
.vms-button--secondary {
|
|
655
931
|
background: transparent;
|
|
@@ -1103,7 +1379,10 @@ select.vms-field__input { cursor: pointer; padding-right: var(--vms-space-xl);
|
|
|
1103
1379
|
success/info are deepened (color-mix w/ black) so white at 14px also clears
|
|
1104
1380
|
4.5:1 (their pure tokens sit at 3.2 / 4.4:1). */
|
|
1105
1381
|
.vms-toast--danger { background: var(--vms-error); color: #fff; }
|
|
1106
|
-
|
|
1382
|
+
/* Warning uses the bright fill + dark foreground (see --vms-warning-fill): white on
|
|
1383
|
+
the dark #8a630d was muddy on light and white on the bright #e0a823 fails AA on dark
|
|
1384
|
+
(2.14:1). Dark text on the bright fill is 7.37:1 and reads as an attention-grabbing yellow. */
|
|
1385
|
+
.vms-toast--warning { background: var(--vms-warning-fill); color: var(--vms-on-warning-fill); }
|
|
1107
1386
|
.vms-toast--success { background: color-mix(in srgb, var(--vms-success) 80%, #000); color: #fff; }
|
|
1108
1387
|
.vms-toast--info { background: color-mix(in srgb, var(--vms-info) 88%, #000); color: #fff; }
|
|
1109
1388
|
/* fade-out applied just before removal. */
|
|
@@ -1178,6 +1457,14 @@ select.vms-field__input { cursor: pointer; padding-right: var(--vms-space-xl);
|
|
|
1178
1457
|
border-color: var(--_badge-tone);
|
|
1179
1458
|
color: #fff;
|
|
1180
1459
|
}
|
|
1460
|
+
/* Warning polarity exception: a filled warning badge uses the bright fill + dark text
|
|
1461
|
+
(white on warning fails AA; see --vms-warning-fill). Border matches the fill (no rim),
|
|
1462
|
+
like every other primary tone. */
|
|
1463
|
+
.vms-badge--warning.vms-badge--primary {
|
|
1464
|
+
background: var(--vms-warning-fill);
|
|
1465
|
+
border-color: var(--vms-warning-fill);
|
|
1466
|
+
color: var(--vms-on-warning-fill);
|
|
1467
|
+
}
|
|
1181
1468
|
.vms-badge--secondary {
|
|
1182
1469
|
background: transparent;
|
|
1183
1470
|
border-color: var(--_badge-tone);
|
|
@@ -1305,6 +1592,52 @@ button.vms-breadcrumb__link {
|
|
|
1305
1592
|
}
|
|
1306
1593
|
.vms-steps__label { color: var(--vms-text); font-weight: 600; }
|
|
1307
1594
|
.vms-steps__description { color: var(--vms-text-muted); font-size: var(--vms-text-xs); }
|
|
1595
|
+
/* Per-step tone (StepItem.tone) — overlays the universal status color onto the
|
|
1596
|
+
marker, ORTHOGONAL to the derived done/current/upcoming treatment: the tone
|
|
1597
|
+
recolors whatever the state already does (filled states fill in the tone;
|
|
1598
|
+
upcoming stays outlined but in the tone), so a failed/blocked stage reads red
|
|
1599
|
+
without losing the reached/not-reached distinction. Two-class selectors
|
|
1600
|
+
outspecify the base state rules. The knockout glyph stays --vms-surface
|
|
1601
|
+
(polarity-adaptive, >=3:1 on the filled tone tokens across all themes — a
|
|
1602
|
+
graphical indicator whose state also rides aria-label + glyph + label text). */
|
|
1603
|
+
.vms-steps__step--tone-danger { --_tone: var(--vms-error); }
|
|
1604
|
+
.vms-steps__step--tone-warning { --_tone: var(--vms-warning); }
|
|
1605
|
+
.vms-steps__step--tone-success { --_tone: var(--vms-success); }
|
|
1606
|
+
.vms-steps__step--tone-info { --_tone: var(--vms-info); }
|
|
1607
|
+
/* Tone recolors the DERIVED treatment: filled states (done/current) fill in the tone;
|
|
1608
|
+
upcoming stays outlined but in the tone — preserving the reached/not-reached read while
|
|
1609
|
+
overlaying status color. Two-class selectors outspecify the base state rules. */
|
|
1610
|
+
.vms-steps__step--toned.vms-steps__step--done .vms-steps__marker,
|
|
1611
|
+
.vms-steps__step--toned.vms-steps__step--current .vms-steps__marker {
|
|
1612
|
+
background: var(--_tone);
|
|
1613
|
+
border-color: var(--_tone);
|
|
1614
|
+
color: var(--vms-surface);
|
|
1615
|
+
}
|
|
1616
|
+
.vms-steps__step--toned.vms-steps__step--upcoming .vms-steps__marker {
|
|
1617
|
+
border-color: var(--_tone);
|
|
1618
|
+
color: var(--_tone);
|
|
1619
|
+
}
|
|
1620
|
+
.vms-steps__step--toned.vms-steps__step--current .vms-steps__marker {
|
|
1621
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, var(--_tone) 30%, transparent);
|
|
1622
|
+
}
|
|
1623
|
+
/* Warning FILLED (done/current): bright fill + dark glyph, no rim (see --vms-warning-fill). */
|
|
1624
|
+
.vms-steps__step--tone-warning.vms-steps__step--done .vms-steps__marker,
|
|
1625
|
+
.vms-steps__step--tone-warning.vms-steps__step--current .vms-steps__marker {
|
|
1626
|
+
background: var(--vms-warning-fill);
|
|
1627
|
+
border-color: var(--vms-warning-fill);
|
|
1628
|
+
color: var(--vms-on-warning-fill);
|
|
1629
|
+
}
|
|
1630
|
+
/* Warning UPCOMING (outline): try the BRIGHT amber for the ring + number rather than the
|
|
1631
|
+
dark --vms-warning. Bright amber as a line/digit on white is ~2.14:1 (below the strict
|
|
1632
|
+
bar), so this is a judgment call on visual legibility — the step's state is multi-channel
|
|
1633
|
+
(aria-label + number + position), so color is not its sole carrier. */
|
|
1634
|
+
.vms-steps__step--tone-warning.vms-steps__step--upcoming .vms-steps__marker {
|
|
1635
|
+
border-color: var(--vms-warning-fill);
|
|
1636
|
+
color: var(--vms-warning-fill);
|
|
1637
|
+
}
|
|
1638
|
+
.vms-steps__step--tone-warning.vms-steps__step--current .vms-steps__marker {
|
|
1639
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, var(--vms-warning-fill) 35%, transparent);
|
|
1640
|
+
}
|
|
1308
1641
|
|
|
1309
1642
|
/* Connector — the OUTGOING segment from this marker toward the next (hidden on
|
|
1310
1643
|
the last step). Colored by the step's own state: accent once the step is done,
|