@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/_overlays.scss
CHANGED
|
@@ -430,10 +430,16 @@
|
|
|
430
430
|
z-index: var(--wui-z-toast);
|
|
431
431
|
display: flex;
|
|
432
432
|
flex-direction: column;
|
|
433
|
-
gap:
|
|
433
|
+
gap: 8px;
|
|
434
434
|
max-width: min(92vw, 400px);
|
|
435
435
|
}
|
|
436
436
|
|
|
437
|
+
// Bootstrap's .toast-container stacks children with margin-bottom: $toast-spacing (1.5rem),
|
|
438
|
+
// which ADDED to the flex gap above — the stack spacing is the gap alone.
|
|
439
|
+
.wui-toast-container > :not(:last-child) {
|
|
440
|
+
margin-bottom: 0;
|
|
441
|
+
}
|
|
442
|
+
|
|
437
443
|
.wui-toast {
|
|
438
444
|
--wui-toast-accent: var(--color-primary);
|
|
439
445
|
position: relative;
|
|
@@ -441,10 +447,12 @@
|
|
|
441
447
|
align-items: flex-start;
|
|
442
448
|
gap: 12px;
|
|
443
449
|
width: 100%;
|
|
444
|
-
padding: 14px
|
|
450
|
+
padding: 14px 16px;
|
|
445
451
|
background: var(--color-surface);
|
|
446
452
|
color: var(--color-text);
|
|
447
|
-
border:
|
|
453
|
+
// The full-strength border, not border-light: on a white page the surface-on-white
|
|
454
|
+
// card otherwise merges into the background (the overlay shadow alone is too soft).
|
|
455
|
+
border: 1px solid var(--color-border);
|
|
448
456
|
border-radius: var(--radius-lg, 12px);
|
|
449
457
|
box-shadow: var(--wui-shadow-overlay);
|
|
450
458
|
overflow: hidden;
|
|
@@ -456,15 +464,6 @@
|
|
|
456
464
|
animation: wui-toast-in 0.24s ease;
|
|
457
465
|
}
|
|
458
466
|
|
|
459
|
-
// The left accent bar reads the variant tint.
|
|
460
|
-
.wui-toast::before {
|
|
461
|
-
content: "";
|
|
462
|
-
position: absolute;
|
|
463
|
-
inset: 0 auto 0 0;
|
|
464
|
-
width: 4px;
|
|
465
|
-
background: var(--wui-toast-accent);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
467
|
// While a swipe is in progress the toast follows the pointer with no transition.
|
|
469
468
|
.wui-toast--dragging {
|
|
470
469
|
transition: none;
|
|
@@ -513,21 +512,81 @@
|
|
|
513
512
|
overflow-wrap: anywhere;
|
|
514
513
|
}
|
|
515
514
|
|
|
515
|
+
// Hierarchy: with a title present the message reads as the SUBTITLE and drops to muted —
|
|
516
|
+
// title (ink, 600) > message (muted) > action (compact ink, hover reveals the variant tint).
|
|
517
|
+
// A title-less toast keeps full ink, or a bare "Saved" would look washed out.
|
|
518
|
+
.wui-toast-title + .wui-toast-message {
|
|
519
|
+
color: var(--color-text-muted);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Determinate task progress (toast `progress` 0–100) — work advancing, not time running out.
|
|
523
|
+
.wui-toast-task {
|
|
524
|
+
display: flex;
|
|
525
|
+
align-items: center;
|
|
526
|
+
gap: 8px;
|
|
527
|
+
margin-top: 7px;
|
|
528
|
+
}
|
|
529
|
+
.wui-toast-track {
|
|
530
|
+
flex: 1 1 auto;
|
|
531
|
+
height: 6px;
|
|
532
|
+
border-radius: 999px;
|
|
533
|
+
background: var(--color-bg-muted);
|
|
534
|
+
overflow: hidden;
|
|
535
|
+
}
|
|
536
|
+
.wui-toast-track-fill {
|
|
537
|
+
height: 100%;
|
|
538
|
+
border-radius: 999px;
|
|
539
|
+
background: var(--wui-toast-accent);
|
|
540
|
+
transition: width 200ms var(--wui-ease-ui);
|
|
541
|
+
}
|
|
542
|
+
.wui-toast-track-pct {
|
|
543
|
+
flex: none;
|
|
544
|
+
font-size: 0.75rem;
|
|
545
|
+
font-weight: 600;
|
|
546
|
+
color: var(--color-text-muted);
|
|
547
|
+
}
|
|
548
|
+
|
|
516
549
|
// Action button — tinted with the variant accent, scoped to the toast so it never
|
|
517
550
|
// restyles an arbitrary .btn-link a rich body might contain.
|
|
551
|
+
// Lives in the content column, below the message/progress (never beside them).
|
|
552
|
+
// Deliberately NOT a .btn — Bootstrap's button chrome (padding, hover lift, transitions)
|
|
553
|
+
// has no business on a text-line action, so the element carries only this class and the
|
|
554
|
+
// styling is self-contained. Neutral bold ink like the title; underline on hover, no motion.
|
|
555
|
+
// The 3px/8px padding exists for the hover pill; the negative margins give it back, so the
|
|
556
|
+
// resting text sits exactly where the padding-less version did and the approved rhythm holds.
|
|
518
557
|
.wui-toast-action {
|
|
519
558
|
flex: none;
|
|
520
|
-
align-self:
|
|
521
|
-
|
|
522
|
-
|
|
559
|
+
align-self: flex-start;
|
|
560
|
+
background: none;
|
|
561
|
+
border: 0;
|
|
562
|
+
padding: 3px 8px;
|
|
563
|
+
margin: -1px 0 -3px -8px;
|
|
564
|
+
border-radius: 6px;
|
|
565
|
+
cursor: pointer;
|
|
566
|
+
color: var(--color-text);
|
|
567
|
+
font-family: inherit;
|
|
523
568
|
font-size: 0.8125rem;
|
|
524
569
|
font-weight: 600;
|
|
525
|
-
|
|
570
|
+
line-height: 1.4;
|
|
571
|
+
text-decoration: none;
|
|
526
572
|
white-space: nowrap;
|
|
573
|
+
transition: background-color 120ms ease, color 120ms ease;
|
|
527
574
|
}
|
|
575
|
+
// Hover: a soft pill in the toast's variant tint — highlight, not underline, no motion.
|
|
528
576
|
.wui-toast-action:hover {
|
|
577
|
+
background: color-mix(in srgb, var(--wui-toast-accent) 14%, transparent);
|
|
529
578
|
color: var(--wui-toast-accent);
|
|
530
|
-
|
|
579
|
+
}
|
|
580
|
+
.wui-toast-action:focus-visible {
|
|
581
|
+
outline: 2px solid var(--wui-toast-accent);
|
|
582
|
+
outline-offset: 1px;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// Geometry: optical space above the action = message half-leading (3.5px) + column gap
|
|
586
|
+
// (2px) + 2px margin + action half-leading (2px) ≈ 9.5px; below = action half-leading
|
|
587
|
+
// (2px) + this padding (7px) ≈ 9px. Equal by construction — don't re-balance one side alone.
|
|
588
|
+
.wui-toast:has(.wui-toast-action) {
|
|
589
|
+
padding-bottom: 7px;
|
|
531
590
|
}
|
|
532
591
|
.wui-toast-action:focus-visible {
|
|
533
592
|
outline: 2px solid var(--wui-toast-accent);
|
|
@@ -540,18 +599,18 @@
|
|
|
540
599
|
font-size: 0.65rem;
|
|
541
600
|
}
|
|
542
601
|
|
|
543
|
-
//
|
|
544
|
-
//
|
|
545
|
-
//
|
|
602
|
+
// The auto-dismiss TIMER, deliberately invisible (height 0): the element still runs the
|
|
603
|
+
// countdown animation because its animationend is what dismisses the toast on both surfaces,
|
|
604
|
+
// and :hover/:focus-within pausing it is what keeps a toast open while being read. Do not
|
|
605
|
+
// remove the element or the animation — only its visibility is retired (a visible countdown
|
|
606
|
+
// reads as pressure).
|
|
546
607
|
.wui-toast-progress {
|
|
547
608
|
position: absolute;
|
|
548
609
|
left: 0;
|
|
549
610
|
bottom: 0;
|
|
550
|
-
height:
|
|
611
|
+
height: 0;
|
|
551
612
|
width: 100%;
|
|
552
613
|
transform-origin: left center;
|
|
553
|
-
background: var(--wui-toast-accent);
|
|
554
|
-
opacity: 0.5;
|
|
555
614
|
animation-name: wui-toast-countdown;
|
|
556
615
|
animation-timing-function: linear;
|
|
557
616
|
animation-fill-mode: forwards;
|
|
@@ -594,9 +653,146 @@
|
|
|
594
653
|
}
|
|
595
654
|
}
|
|
596
655
|
|
|
656
|
+
// ── Entrance variants (toast/WUI.toast `animation`; host default via AppToast/app-toast) ──
|
|
657
|
+
// The base .wui-toast entrance above is `rise`. The variants below animate the STANDALONE
|
|
658
|
+
// scale/translate properties so they never fight the swipe-to-dismiss inline transform.
|
|
659
|
+
|
|
660
|
+
// `organic` — studied frame-by-frame from Ivan Bjelajac's notification: the surface
|
|
661
|
+
// materializes softly while the status icon grows from a dot with a slight overshoot,
|
|
662
|
+
// and the message trails in last.
|
|
663
|
+
.wui-toast--anim-organic {
|
|
664
|
+
animation: wui-toast-materialize 360ms var(--wui-ease-out-quart);
|
|
665
|
+
}
|
|
666
|
+
.wui-toast--anim-organic .wui-toast-icon {
|
|
667
|
+
animation: wui-toast-icon-grow 420ms 60ms cubic-bezier(0.34, 1.45, 0.64, 1) backwards;
|
|
668
|
+
}
|
|
669
|
+
.wui-toast--anim-organic .wui-toast-content {
|
|
670
|
+
animation: wui-toast-content-in 300ms 190ms var(--wui-ease-out-quart) backwards;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// `jelly` — drops in with a squash-and-stretch landing.
|
|
674
|
+
.wui-toast--anim-jelly {
|
|
675
|
+
animation: wui-toast-jelly 500ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// `spring` — slides up from below with an elastic settle.
|
|
679
|
+
.wui-toast--anim-spring {
|
|
680
|
+
animation: wui-toast-spring 550ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
@keyframes wui-toast-materialize {
|
|
684
|
+
from {
|
|
685
|
+
opacity: 0;
|
|
686
|
+
scale: 0.97;
|
|
687
|
+
}
|
|
688
|
+
to {
|
|
689
|
+
opacity: 1;
|
|
690
|
+
scale: 1;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
@keyframes wui-toast-icon-grow {
|
|
694
|
+
0% {
|
|
695
|
+
scale: 0;
|
|
696
|
+
}
|
|
697
|
+
70% {
|
|
698
|
+
scale: 1.18;
|
|
699
|
+
}
|
|
700
|
+
100% {
|
|
701
|
+
scale: 1;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
@keyframes wui-toast-content-in {
|
|
705
|
+
from {
|
|
706
|
+
opacity: 0;
|
|
707
|
+
translate: 6px 0;
|
|
708
|
+
}
|
|
709
|
+
to {
|
|
710
|
+
opacity: 1;
|
|
711
|
+
translate: 0 0;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
@keyframes wui-toast-jelly {
|
|
715
|
+
0% {
|
|
716
|
+
opacity: 0;
|
|
717
|
+
translate: 0 -46px;
|
|
718
|
+
scale: 0.6 0.6;
|
|
719
|
+
}
|
|
720
|
+
55% {
|
|
721
|
+
opacity: 1;
|
|
722
|
+
translate: 0 6px;
|
|
723
|
+
scale: 1.05 0.85;
|
|
724
|
+
}
|
|
725
|
+
75% {
|
|
726
|
+
translate: 0 -2px;
|
|
727
|
+
scale: 0.97 1.05;
|
|
728
|
+
}
|
|
729
|
+
100% {
|
|
730
|
+
opacity: 1;
|
|
731
|
+
translate: 0 0;
|
|
732
|
+
scale: 1 1;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
@keyframes wui-toast-spring {
|
|
736
|
+
from {
|
|
737
|
+
opacity: 0;
|
|
738
|
+
translate: 0 64px;
|
|
739
|
+
scale: 0.92;
|
|
740
|
+
}
|
|
741
|
+
to {
|
|
742
|
+
opacity: 1;
|
|
743
|
+
translate: 0 0;
|
|
744
|
+
scale: 1;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// ── Inverse surface (toast/WUI.toast `surface: 'inverse'`) ──
|
|
749
|
+
// The toast renders on the OPPOSITE surface of the active mode — a dark card on a light
|
|
750
|
+
// page, a light card on a dark page — so the stack always contrasts with the content.
|
|
751
|
+
// Everything inside consumes --color-* vars, so re-pointing them here restyles the whole
|
|
752
|
+
// card (icon, text hierarchy, action pill, progress track) in one place.
|
|
753
|
+
.wui-toast--surface-inverse {
|
|
754
|
+
--color-surface: var(--wui-dark-bg-surface);
|
|
755
|
+
--color-border: var(--wui-dark-border);
|
|
756
|
+
--color-text: var(--wui-dark-text);
|
|
757
|
+
--color-text-muted: var(--wui-dark-text-muted);
|
|
758
|
+
--color-bg-muted: var(--wui-dark-bg-muted);
|
|
759
|
+
}
|
|
760
|
+
// Bootstrap's .btn-close glyph is ink-dark; on the dark card it needs the white filter.
|
|
761
|
+
.wui-toast--surface-inverse .wui-toast-close {
|
|
762
|
+
filter: invert(1) grayscale(100%) brightness(200%);
|
|
763
|
+
}
|
|
764
|
+
:root[data-theme="dark"] .wui-toast--surface-inverse,
|
|
765
|
+
:root[data-bs-theme="dark"] .wui-toast--surface-inverse {
|
|
766
|
+
--color-surface: var(--wui-bg-light);
|
|
767
|
+
--color-border: var(--wui-border-light);
|
|
768
|
+
--color-text: var(--wui-text-heading);
|
|
769
|
+
--color-text-muted: var(--wui-text-2);
|
|
770
|
+
--color-bg-muted: var(--wui-bg-muted);
|
|
771
|
+
}
|
|
772
|
+
:root[data-theme="dark"] .wui-toast--surface-inverse .wui-toast-close,
|
|
773
|
+
:root[data-bs-theme="dark"] .wui-toast--surface-inverse .wui-toast-close {
|
|
774
|
+
filter: none;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// ── Corner treatments (toast/WUI.toast `shape`) — `rounded` is the base radius above ──
|
|
778
|
+
.wui-toast--shape-pill {
|
|
779
|
+
border-radius: 999px;
|
|
780
|
+
align-items: center;
|
|
781
|
+
padding-block: 12px;
|
|
782
|
+
}
|
|
783
|
+
.wui-toast--shape-pill .wui-toast-icon,
|
|
784
|
+
.wui-toast--shape-pill .wui-toast-close {
|
|
785
|
+
margin-top: 0;
|
|
786
|
+
}
|
|
787
|
+
.wui-toast--shape-sharp {
|
|
788
|
+
border-radius: 4px;
|
|
789
|
+
}
|
|
790
|
+
|
|
597
791
|
@media (prefers-reduced-motion: reduce) {
|
|
598
|
-
// Drop the entrance
|
|
599
|
-
.wui-toast
|
|
792
|
+
// Drop the entrance motion; the countdown bar stays — it is the auto-dismiss timer, not decoration.
|
|
793
|
+
.wui-toast,
|
|
794
|
+
.wui-toast--anim-organic .wui-toast-icon,
|
|
795
|
+
.wui-toast--anim-organic .wui-toast-content {
|
|
600
796
|
animation: none;
|
|
601
797
|
transition: none;
|
|
602
798
|
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// ── Toolbar ──
|
|
2
|
+
// AppToolbar / <app-toolbar> — a Figma-style tool strip: a pill of icon tools where
|
|
3
|
+
// the active tool expands to reveal its label. Radio-backed (no JS needed on Razor);
|
|
4
|
+
// the expand/collapse is pure CSS off :checked.
|
|
5
|
+
//
|
|
6
|
+
// Part of the wui-components layer — see _wui-components.scss for load order.
|
|
7
|
+
|
|
8
|
+
.toolbar {
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
gap: 4px;
|
|
12
|
+
padding: 6px;
|
|
13
|
+
background: var(--color-surface);
|
|
14
|
+
border: 1px solid var(--color-border);
|
|
15
|
+
border-radius: var(--wui-radius-lg);
|
|
16
|
+
corner-shape: squircle;
|
|
17
|
+
box-shadow: var(--wui-shadow-overlay);
|
|
18
|
+
}
|
|
19
|
+
.toolbar.is-disabled {
|
|
20
|
+
opacity: 0.6;
|
|
21
|
+
pointer-events: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.toolbar-item {
|
|
25
|
+
display: inline-flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
height: 36px;
|
|
28
|
+
padding-inline: 9px;
|
|
29
|
+
border-radius: var(--wui-radius);
|
|
30
|
+
color: var(--color-text-muted);
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
margin-bottom: 0;
|
|
33
|
+
transition:
|
|
34
|
+
background-color 160ms var(--wui-ease-ui),
|
|
35
|
+
color 160ms var(--wui-ease-ui);
|
|
36
|
+
}
|
|
37
|
+
.toolbar-item:hover {
|
|
38
|
+
background: var(--color-bg-muted);
|
|
39
|
+
color: var(--color-text);
|
|
40
|
+
}
|
|
41
|
+
// The active tool: brand fill + the label slides open beside the icon.
|
|
42
|
+
.toolbar-item:has(.toolbar-input:checked) {
|
|
43
|
+
background: var(--color-primary);
|
|
44
|
+
color: var(--color-primary-text);
|
|
45
|
+
}
|
|
46
|
+
.toolbar-item:has(.toolbar-input:disabled) {
|
|
47
|
+
opacity: 0.5;
|
|
48
|
+
cursor: default;
|
|
49
|
+
}
|
|
50
|
+
.toolbar-item:has(.toolbar-input:focus-visible) {
|
|
51
|
+
outline: 2px solid var(--color-primary);
|
|
52
|
+
outline-offset: 2px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Visually hidden but focusable/announceable — same trick as .segmented-input.
|
|
56
|
+
.toolbar-input {
|
|
57
|
+
position: absolute;
|
|
58
|
+
width: 1px;
|
|
59
|
+
height: 1px;
|
|
60
|
+
margin: 0;
|
|
61
|
+
padding: 0;
|
|
62
|
+
border: 0;
|
|
63
|
+
clip-path: inset(50%);
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
white-space: nowrap;
|
|
66
|
+
appearance: none;
|
|
67
|
+
opacity: 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.toolbar-item-icon {
|
|
71
|
+
display: grid;
|
|
72
|
+
place-items: center;
|
|
73
|
+
line-height: 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.toolbar-item-label {
|
|
77
|
+
max-width: 0;
|
|
78
|
+
margin-left: 0;
|
|
79
|
+
opacity: 0;
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
white-space: nowrap;
|
|
82
|
+
font-size: 0.875rem;
|
|
83
|
+
font-weight: 500;
|
|
84
|
+
transition:
|
|
85
|
+
max-width 240ms var(--wui-ease-ui),
|
|
86
|
+
margin-left 240ms var(--wui-ease-ui),
|
|
87
|
+
opacity 180ms var(--wui-ease-ui);
|
|
88
|
+
}
|
|
89
|
+
.toolbar-item:has(.toolbar-input:checked) .toolbar-item-label {
|
|
90
|
+
max-width: 10rem;
|
|
91
|
+
margin-left: 7px;
|
|
92
|
+
opacity: 1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.toolbar-sep {
|
|
96
|
+
width: 1px;
|
|
97
|
+
align-self: stretch;
|
|
98
|
+
margin-block: 6px;
|
|
99
|
+
margin-inline: 3px;
|
|
100
|
+
background: var(--color-border);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.toolbar-action {
|
|
104
|
+
display: inline-flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
width: 36px;
|
|
108
|
+
height: 36px;
|
|
109
|
+
padding: 0;
|
|
110
|
+
border: none;
|
|
111
|
+
border-radius: var(--wui-radius);
|
|
112
|
+
background: transparent;
|
|
113
|
+
color: var(--color-text-muted);
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
transition:
|
|
116
|
+
background-color 160ms var(--wui-ease-ui),
|
|
117
|
+
color 160ms var(--wui-ease-ui);
|
|
118
|
+
}
|
|
119
|
+
.toolbar-action:hover:not(:disabled) {
|
|
120
|
+
background: var(--color-bg-muted);
|
|
121
|
+
color: var(--color-text);
|
|
122
|
+
}
|
|
123
|
+
.toolbar-action:focus-visible {
|
|
124
|
+
outline: 2px solid var(--color-primary);
|
|
125
|
+
outline-offset: 2px;
|
|
126
|
+
}
|
|
127
|
+
.toolbar-action:disabled {
|
|
128
|
+
opacity: 0.5;
|
|
129
|
+
cursor: default;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@media (prefers-reduced-motion: reduce) {
|
|
133
|
+
.toolbar-item,
|
|
134
|
+
.toolbar-item-label,
|
|
135
|
+
.toolbar-action {
|
|
136
|
+
transition: none;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -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.)
|