@glimstone/core 4.0.0 → 4.1.1
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/README.md +13 -0
- package/dist/button.d.ts +5 -0
- package/dist/button.js +4 -3
- package/dist/clipboard.d.ts +4 -0
- package/dist/clipboard.js +30 -0
- package/dist/colorNames.d.ts +10 -0
- package/dist/colorNames.js +61 -0
- package/dist/colorPicker.d.ts +59 -3
- package/dist/colorPicker.js +181 -73
- package/dist/dialog.d.ts +5 -0
- package/dist/dialog.js +27 -22
- package/dist/field.d.ts +21 -0
- package/dist/field.js +26 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/marks.d.ts +30 -0
- package/dist/marks.js +30 -0
- package/dist/media.d.ts +2 -0
- package/dist/media.js +4 -0
- package/dist/menu.d.ts +109 -0
- package/dist/menu.js +163 -0
- package/dist/meter.d.ts +32 -0
- package/dist/meter.js +44 -0
- package/dist/pill.d.ts +3 -0
- package/dist/pill.js +7 -0
- package/dist/selectModel.d.ts +17 -0
- package/dist/selectModel.js +23 -0
- package/dist/selector.d.ts +2 -2
- package/dist/sidebarRow.d.ts +4 -0
- package/dist/sidebarRow.js +6 -1
- package/dist/table.d.ts +12 -0
- package/dist/table.js +5 -0
- package/dist/toastEngine.d.ts +12 -0
- package/dist/toastEngine.js +8 -0
- package/dist/tree.d.ts +38 -0
- package/dist/tree.js +57 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/window.d.ts +29 -0
- package/dist/window.js +62 -0
- package/glyph-map.md +48 -0
- package/glyphs.json +247 -0
- package/glyphs.md +28 -2
- package/package.json +1 -1
- package/tokens.css +1093 -12
package/tokens.css
CHANGED
|
@@ -107,6 +107,9 @@
|
|
|
107
107
|
--carbon-surface3: #525252;
|
|
108
108
|
--carbon-hover: #353535;
|
|
109
109
|
--carbon-hover-raised: #6f6f6f;
|
|
110
|
+
/* A switch that is off. On the light ramp surface3 stands too close to a card
|
|
111
|
+
and to the knob to see, so the track goes down to 3:1 against both. */
|
|
112
|
+
--toggle-off: #525252;
|
|
110
113
|
--carbon-border: #393939;
|
|
111
114
|
|
|
112
115
|
/* The About card's brand marks at rest, adjusted from the published brand
|
|
@@ -213,6 +216,7 @@
|
|
|
213
216
|
--carbon-surface3: #d1d1d1;
|
|
214
217
|
--carbon-hover: #e0e0e0;
|
|
215
218
|
--carbon-hover-raised: #c6c6c6;
|
|
219
|
+
--toggle-off: #8d8d8d;
|
|
216
220
|
--carbon-border: #d1d1d1;
|
|
217
221
|
|
|
218
222
|
/* Warm brands deepened, dark ones left dark (see the dark block). */
|
|
@@ -278,6 +282,7 @@
|
|
|
278
282
|
--carbon-surface3: #d1d1d1;
|
|
279
283
|
--carbon-hover: #e0e0e0;
|
|
280
284
|
--carbon-hover-raised: #c6c6c6;
|
|
285
|
+
--toggle-off: #8d8d8d;
|
|
281
286
|
--carbon-border: #d1d1d1;
|
|
282
287
|
|
|
283
288
|
/* The same brand values as the media block, for an explicit light choice. */
|
|
@@ -389,14 +394,20 @@ body {
|
|
|
389
394
|
row is a bigger target, and in glyph mode the symbol is the whole row.
|
|
390
395
|
`flex: none` because a flex line squeezes the glyph beside a long label
|
|
391
396
|
first. */
|
|
392
|
-
.glim-nav-row > svg {
|
|
397
|
+
:is(.glim-nav-row, .glim-nav-row-main) > svg {
|
|
393
398
|
width: 1.25rem;
|
|
394
399
|
height: 1.25rem;
|
|
395
400
|
flex: none;
|
|
396
401
|
}
|
|
402
|
+
/* A tree's row keeps a deep name its room with a smaller glyph. */
|
|
403
|
+
:is(.glim-nav-row--tree, .glim-nav-row--tree > .glim-nav-row-main) > svg {
|
|
404
|
+
width: 1.05rem;
|
|
405
|
+
height: 1.05rem;
|
|
406
|
+
}
|
|
397
407
|
|
|
398
408
|
/* A closed reactive row must not reserve a gap beside a zero-width label. */
|
|
399
|
-
.glim-nav-row.glim-reactive
|
|
409
|
+
.glim-nav-row.glim-reactive:not(.glim-nav-row--slots),
|
|
410
|
+
.glim-nav-row--slots.glim-reactive > .glim-nav-row-main {
|
|
400
411
|
gap: 0;
|
|
401
412
|
}
|
|
402
413
|
|
|
@@ -594,6 +605,70 @@ body {
|
|
|
594
605
|
background-color: var(--carbon-hover);
|
|
595
606
|
}
|
|
596
607
|
|
|
608
|
+
/* A drag on the square or the bar is the picker's, never a scroll of the
|
|
609
|
+
page. The handle shows the colour it stands on. */
|
|
610
|
+
.glim-picker-sv,
|
|
611
|
+
.glim-picker-hue { touch-action: none; }
|
|
612
|
+
.glim-picker-dot { background-color: var(--glim-picker-colour, transparent); }
|
|
613
|
+
|
|
614
|
+
/* The ColorPicker components: the widget, the preview with the name it
|
|
615
|
+
proposes and the hex field, and Apply. Without an anchor the panel sits in
|
|
616
|
+
the page on whatever surface holds it; with one it floats on the body, above
|
|
617
|
+
windows and below toasts, like a menu. */
|
|
618
|
+
.glim-picker-panel {
|
|
619
|
+
--glim-picker-colour: transparent;
|
|
620
|
+
display: flex;
|
|
621
|
+
flex-direction: column;
|
|
622
|
+
gap: 0.75rem;
|
|
623
|
+
width: 18.5rem;
|
|
624
|
+
max-width: 100%;
|
|
625
|
+
}
|
|
626
|
+
.glim-picker-panel .glim-picker-sv { height: 10rem; }
|
|
627
|
+
.glim-picker-panel .glim-picker-dot {
|
|
628
|
+
width: 1.1rem;
|
|
629
|
+
height: 1.1rem;
|
|
630
|
+
margin: -0.55rem 0 0 -0.55rem;
|
|
631
|
+
}
|
|
632
|
+
.glim-picker-panel--float {
|
|
633
|
+
position: fixed;
|
|
634
|
+
z-index: 60;
|
|
635
|
+
padding: 0.8rem;
|
|
636
|
+
border-radius: var(--radius-card);
|
|
637
|
+
background-color: var(--carbon-surface);
|
|
638
|
+
box-shadow: var(--elevation), var(--hairline);
|
|
639
|
+
}
|
|
640
|
+
.glim-picker-foot {
|
|
641
|
+
display: flex;
|
|
642
|
+
align-items: center;
|
|
643
|
+
gap: 0.55rem;
|
|
644
|
+
}
|
|
645
|
+
.glim-picker-swatch {
|
|
646
|
+
width: 1.6rem;
|
|
647
|
+
height: 1.6rem;
|
|
648
|
+
flex: none;
|
|
649
|
+
border-radius: var(--radius-pill);
|
|
650
|
+
background-color: var(--glim-picker-colour);
|
|
651
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--glim-picker-colour) 30%, transparent), inset 0 0 0 1px var(--carbon-border);
|
|
652
|
+
}
|
|
653
|
+
.glim-picker-name {
|
|
654
|
+
flex: 1;
|
|
655
|
+
min-width: 0;
|
|
656
|
+
overflow: hidden;
|
|
657
|
+
font-weight: 600;
|
|
658
|
+
text-overflow: ellipsis;
|
|
659
|
+
white-space: nowrap;
|
|
660
|
+
}
|
|
661
|
+
.glim-picker-foot .glim-picker-hex {
|
|
662
|
+
width: 6.2rem;
|
|
663
|
+
height: var(--btn-h);
|
|
664
|
+
flex: none;
|
|
665
|
+
margin-inline-start: auto;
|
|
666
|
+
}
|
|
667
|
+
.glim-picker-actions {
|
|
668
|
+
display: flex;
|
|
669
|
+
justify-content: flex-end;
|
|
670
|
+
}
|
|
671
|
+
|
|
597
672
|
/* Rainbow, the accent in its plural form (docs/design-language.md; the JS side
|
|
598
673
|
is hueVars and applyRainbow in packages/core/src/appearance.ts). An element that owns
|
|
599
674
|
a palette position sets --item-hue and carries .glim-hue, and these rules
|
|
@@ -721,6 +796,9 @@ body {
|
|
|
721
796
|
0% { left: -35%; }
|
|
722
797
|
100% { left: 100%; }
|
|
723
798
|
}
|
|
799
|
+
@keyframes glim-progress-sheen {
|
|
800
|
+
to { translate: 100% 0; }
|
|
801
|
+
}
|
|
724
802
|
/* Translation only. This runs on the route wrapper while the cards inside it
|
|
725
803
|
animate their own transforms, and a scale or rotation on an ancestor makes
|
|
726
804
|
the engine resample the whole subtree, so the page trembles before it
|
|
@@ -906,6 +984,10 @@ body {
|
|
|
906
984
|
--motion-slosh-splash-tilt: 7deg;
|
|
907
985
|
--motion-slosh-splash-run: 3.4;
|
|
908
986
|
--motion-slosh-splash-ripple: 1.5;
|
|
987
|
+
/* A progress bar without a value: one sweep of its light across the
|
|
988
|
+
track. Its sheen: one pass over the filled part. */
|
|
989
|
+
--motion-indeterminate-dur: 1.4s;
|
|
990
|
+
--motion-progress-sheen-dur: 1.6s;
|
|
909
991
|
}
|
|
910
992
|
:root[data-motion='subtle'] {
|
|
911
993
|
--motion-control-dur: 80ms;
|
|
@@ -950,6 +1032,8 @@ body {
|
|
|
950
1032
|
--motion-slosh-splash-tilt: 4deg;
|
|
951
1033
|
--motion-slosh-splash-run: 2.2;
|
|
952
1034
|
--motion-slosh-splash-ripple: 1;
|
|
1035
|
+
--motion-indeterminate-dur: 2.2s;
|
|
1036
|
+
--motion-progress-sheen-dur: 2.6s;
|
|
953
1037
|
}
|
|
954
1038
|
:root[data-motion='off'] {
|
|
955
1039
|
--motion-control-dur: 0s;
|
|
@@ -998,7 +1082,27 @@ body {
|
|
|
998
1082
|
--motion-slosh-splash-tilt: 0deg;
|
|
999
1083
|
--motion-slosh-splash-run: 0;
|
|
1000
1084
|
--motion-slosh-splash-ripple: 0;
|
|
1085
|
+
/* Long rather than 0; both stop outright at this level, below. */
|
|
1086
|
+
--motion-indeterminate-dur: 60s;
|
|
1087
|
+
--motion-progress-sheen-dur: 60s;
|
|
1088
|
+
}
|
|
1089
|
+
/* A progress bar without a value sends a short light across its track, and
|
|
1090
|
+
a running one a sheen over its fill. A meter never moves: it shows a level
|
|
1091
|
+
that stands, and a light on it would say something is under way. Both
|
|
1092
|
+
stop at "off", where a bar without a value keeps its stripes, and under
|
|
1093
|
+
reduced motion even for storm: wanting more movement is not wanting
|
|
1094
|
+
something that never stops. */
|
|
1095
|
+
:root:not([data-motion='off']) .glim-progress--busy > .glim-progress-fill {
|
|
1096
|
+
width: 35%;
|
|
1097
|
+
background: var(--accent);
|
|
1098
|
+
opacity: 1;
|
|
1099
|
+
animation: glim-indeterminate var(--motion-indeterminate-dur) ease-in-out infinite;
|
|
1100
|
+
}
|
|
1101
|
+
:root:not([data-motion='off']) .glim-progress:not(.glim-progress--busy, .glim-progress--paused, .glim-progress--done, .glim-progress--failed) .glim-progress-fill::after {
|
|
1102
|
+
animation: glim-progress-sheen var(--motion-progress-sheen-dur) ease-in-out infinite;
|
|
1001
1103
|
}
|
|
1104
|
+
.glim-progress-fill { transition: width var(--motion-control-dur) linear; }
|
|
1105
|
+
|
|
1002
1106
|
:root[data-motion='off'] * { transition-duration: 0s !important; }
|
|
1003
1107
|
:root[data-motion='subtle'] .transition,
|
|
1004
1108
|
:root[data-motion='subtle'] .transition-colors,
|
|
@@ -1071,6 +1175,8 @@ body {
|
|
|
1071
1175
|
--motion-slosh-splash-tilt: 10deg;
|
|
1072
1176
|
--motion-slosh-splash-run: 4.8;
|
|
1073
1177
|
--motion-slosh-splash-ripple: 2;
|
|
1178
|
+
--motion-indeterminate-dur: 0.9s;
|
|
1179
|
+
--motion-progress-sheen-dur: 1.1s;
|
|
1074
1180
|
}
|
|
1075
1181
|
:root[data-motion='storm'][dir="rtl"] { --glim-toast-slide: -44px; }
|
|
1076
1182
|
|
|
@@ -1840,6 +1946,11 @@ body {
|
|
|
1840
1946
|
.glim-btn-sm { min-width: var(--btn-w-sm); }
|
|
1841
1947
|
.glim-btn-md { min-width: var(--btn-w-md); }
|
|
1842
1948
|
.glim-btn-lg { min-width: var(--btn-w-lg); }
|
|
1949
|
+
/* A foot holds several answers in one row, so they hug their words down to the
|
|
1950
|
+
smallest floor. An explicit stage is a width of its own and stays. */
|
|
1951
|
+
.glim-modal-foot > :is(.glim-btn-sm, .glim-btn-md, .glim-btn-lg),
|
|
1952
|
+
.glim-modal-foot > .glim-tip-wrap > :is(.glim-btn-sm, .glim-btn-md, .glim-btn-lg) { min-width: var(--btn-w-xs); }
|
|
1953
|
+
.glim-path > .glim-btn:not(.glim-btn-icon) { min-width: 0; }
|
|
1843
1954
|
|
|
1844
1955
|
/* Rule 40. A surface-filled button's hovered ground takes 22% of the tint and
|
|
1845
1956
|
its glyph all of it; its words keep the text colour, which the accent on a
|
|
@@ -1861,7 +1972,7 @@ body {
|
|
|
1861
1972
|
.glim-btn-bare:not(:disabled):is(:hover, :focus-visible) {
|
|
1862
1973
|
color: var(--btn-tint);
|
|
1863
1974
|
}
|
|
1864
|
-
.glim-btn-bare:is(:hover, :focus-visible) {
|
|
1975
|
+
.glim-btn-bare:not([aria-pressed="true"]):is(:hover, :focus-visible) {
|
|
1865
1976
|
background-color: transparent;
|
|
1866
1977
|
}
|
|
1867
1978
|
|
|
@@ -2196,14 +2307,17 @@ body {
|
|
|
2196
2307
|
height, sized by its glyph. In a mode that shows words it is an ordinary
|
|
2197
2308
|
button with its label (see `ButtonVariant` in packages/react/src/Button.tsx). */
|
|
2198
2309
|
.glim-btn-icon {
|
|
2199
|
-
width: var(--btn-h);
|
|
2200
|
-
min-width: 0;
|
|
2310
|
+
min-width: var(--btn-h);
|
|
2201
2311
|
padding-inline: 0;
|
|
2202
2312
|
}
|
|
2313
|
+
/* A square that holds more than its glyph, such as a count, grows to hold it. */
|
|
2314
|
+
.glim-btn-icon:has(> :not(.glim-btn-glyph, .glim-sr-only)) {
|
|
2315
|
+
padding-inline: var(--btn-pad-x);
|
|
2316
|
+
}
|
|
2203
2317
|
|
|
2204
2318
|
/* A row action promoted to a key control stays square at the other height. */
|
|
2205
2319
|
.glim-btn-icon.glim-btn-key {
|
|
2206
|
-
width: var(--btn-h-key);
|
|
2320
|
+
min-width: var(--btn-h-key);
|
|
2207
2321
|
}
|
|
2208
2322
|
|
|
2209
2323
|
/* A glyph alone in a square fills half its box, as on a 32px icon badge with a
|
|
@@ -2493,6 +2607,13 @@ body {
|
|
|
2493
2607
|
outline: 2px solid var(--focus-ring);
|
|
2494
2608
|
outline-offset: 1px;
|
|
2495
2609
|
}
|
|
2610
|
+
/* In a well or a sub-card the trigger stands among fields, so it takes their
|
|
2611
|
+
ground and hovers up the ramp (rule 21). */
|
|
2612
|
+
:is(.glim-well, .glim-subcard) :is(.glim-select-trigger:not(.glim-select-trigger--inset), .glim-combobox-control) {
|
|
2613
|
+
border-color: transparent;
|
|
2614
|
+
background: var(--carbon-surface3);
|
|
2615
|
+
}
|
|
2616
|
+
:is(.glim-well, .glim-subcard) .glim-select-trigger:not(.glim-select-trigger--inset):hover { background: var(--carbon-hover-raised); }
|
|
2496
2617
|
.glim-select-trigger[data-disabled] { opacity: 0.5; cursor: default; }
|
|
2497
2618
|
/* Busy: the trigger keeps its focus and takes no input until the answer is back. */
|
|
2498
2619
|
.glim-select-trigger[data-readonly] { opacity: 0.5; cursor: progress; }
|
|
@@ -2661,6 +2782,37 @@ body {
|
|
|
2661
2782
|
@media (pointer: coarse) {
|
|
2662
2783
|
.glim-select-item { min-height: 2.75rem; }
|
|
2663
2784
|
}
|
|
2785
|
+
/* The box a closed list hangs from stays on the body for the machine, out of
|
|
2786
|
+
the way. */
|
|
2787
|
+
.glim-select-positioner:has(> [hidden]) { display: none; }
|
|
2788
|
+
/* A list that draws a context menu's rows (Select with rows="menu"): the menu's
|
|
2789
|
+
panel, and the states the machine marks with attributes instead of the focus.
|
|
2790
|
+
The wash comes before the highlight, which covers it, as a hover does in the
|
|
2791
|
+
menu. */
|
|
2792
|
+
.glim-select-content--menu {
|
|
2793
|
+
min-width: max(var(--reference-width, 0px), 16rem);
|
|
2794
|
+
padding: 0.35rem;
|
|
2795
|
+
box-shadow: var(--elevation), var(--hairline);
|
|
2796
|
+
}
|
|
2797
|
+
.glim-select-content--menu .glim-menu-item[data-state="checked"] { background-color: var(--accent-soft); }
|
|
2798
|
+
.glim-select-content--menu .glim-menu-item[data-highlighted] { background-color: var(--carbon-hover); }
|
|
2799
|
+
.glim-select-content--menu .glim-menu-item[data-disabled] {
|
|
2800
|
+
opacity: 0.45;
|
|
2801
|
+
background-color: transparent;
|
|
2802
|
+
cursor: default;
|
|
2803
|
+
}
|
|
2804
|
+
.glim-select-content--menu .glim-menu-tick:not([data-state="checked"]) { visibility: hidden; }
|
|
2805
|
+
.glim-select-content--menu .glim-select-group + .glim-select-group {
|
|
2806
|
+
margin-top: 0.3rem;
|
|
2807
|
+
padding-top: 0.3rem;
|
|
2808
|
+
border-top-color: color-mix(in srgb, var(--carbon-text) 9%, transparent);
|
|
2809
|
+
}
|
|
2810
|
+
@media (pointer: coarse) {
|
|
2811
|
+
.glim-select-content--menu .glim-menu-item {
|
|
2812
|
+
height: auto;
|
|
2813
|
+
min-height: 2.75rem;
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2664
2816
|
.glim-select-empty {
|
|
2665
2817
|
padding: 0.5rem 0.75rem;
|
|
2666
2818
|
color: var(--carbon-text-muted);
|
|
@@ -2700,6 +2852,7 @@ body {
|
|
|
2700
2852
|
.glim-slider-thumb[data-dragging] { cursor: grabbing; }
|
|
2701
2853
|
.glim-slider-thumb[data-disabled] { opacity: 0.5; cursor: default; }
|
|
2702
2854
|
.glim-slider-value {
|
|
2855
|
+
margin-inline-start: auto;
|
|
2703
2856
|
color: var(--carbon-text);
|
|
2704
2857
|
font-size: var(--text-body);
|
|
2705
2858
|
font-variant-numeric: tabular-nums;
|
|
@@ -2718,7 +2871,7 @@ body {
|
|
|
2718
2871
|
:where([class*="glim-"]) :where(*, ::before, ::after) {
|
|
2719
2872
|
box-sizing: border-box;
|
|
2720
2873
|
}
|
|
2721
|
-
:where(.glim-btn, .glim-badge, .glim-readme-btn, .glim-toggle-track, .glim-toast-dismiss, .glim-window-button, .glim-give-network, .glim-give-coin, .glim-give-amount, .glim-sel-seg, .glim-num-field) {
|
|
2874
|
+
:where(.glim-btn, .glim-badge, .glim-readme-btn, .glim-toggle-track, .glim-toast-dismiss, .glim-window-button, .glim-give-network, .glim-give-coin, .glim-give-amount, .glim-sel-seg, .glim-num-field, .glim-menu-item, .glim-menu-head-edit, .glim-menubar-item, .glim-checkbox, .glim-input, .glim-secret-eye, .glim-icon-btn, .glim-glyph-field-input, .glim-nav-row-main, button.glim-nav-row) {
|
|
2722
2875
|
margin: 0;
|
|
2723
2876
|
padding: 0;
|
|
2724
2877
|
border: 0 solid;
|
|
@@ -2810,11 +2963,20 @@ body {
|
|
|
2810
2963
|
}
|
|
2811
2964
|
.glim-modal-foot {
|
|
2812
2965
|
display: flex;
|
|
2966
|
+
flex-wrap: wrap;
|
|
2813
2967
|
align-items: center;
|
|
2814
2968
|
justify-content: flex-end;
|
|
2815
2969
|
gap: 0.75rem;
|
|
2816
2970
|
padding: 1rem 1.25rem;
|
|
2817
2971
|
}
|
|
2972
|
+
/* A button keeps its words: in a flex row what stands beside it gives way, and
|
|
2973
|
+
in a foot it moves to the next line. In the layer, so an app's own flex
|
|
2974
|
+
rule for a button still wins. */
|
|
2975
|
+
.glim-btn {
|
|
2976
|
+
flex-shrink: 0;
|
|
2977
|
+
max-width: 100%;
|
|
2978
|
+
}
|
|
2979
|
+
.glim-modal-foot > .glim-tip-wrap { flex: none; }
|
|
2818
2980
|
|
|
2819
2981
|
/* The fills a button can take (ButtonTone). `ok`, `danger` and `warn` put the
|
|
2820
2982
|
solid status tokens under the ground's ink: in both themes the solid values
|
|
@@ -2862,7 +3024,7 @@ body {
|
|
|
2862
3024
|
width: 2.25rem;
|
|
2863
3025
|
height: 1.25rem;
|
|
2864
3026
|
border-radius: var(--radius-pill);
|
|
2865
|
-
background-color: var(--
|
|
3027
|
+
background-color: var(--toggle-off);
|
|
2866
3028
|
transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
2867
3029
|
}
|
|
2868
3030
|
.glim-toggle-track[aria-checked="true"] { background-color: var(--accent); }
|
|
@@ -3233,7 +3395,7 @@ body {
|
|
|
3233
3395
|
display: flex;
|
|
3234
3396
|
align-items: flex-start;
|
|
3235
3397
|
gap: 0.625rem;
|
|
3236
|
-
width:
|
|
3398
|
+
width: 24rem;
|
|
3237
3399
|
max-width: calc(100vw - 2rem);
|
|
3238
3400
|
padding: 0.75rem 0.875rem;
|
|
3239
3401
|
border-radius: var(--radius-card);
|
|
@@ -3250,14 +3412,32 @@ body {
|
|
|
3250
3412
|
.glim-toast-glyph--success { color: var(--status-ok-solid); }
|
|
3251
3413
|
.glim-toast-glyph--warn { color: var(--status-warn-solid); }
|
|
3252
3414
|
.glim-toast-glyph--fail { color: var(--status-fail-solid); }
|
|
3253
|
-
.glim-toast-
|
|
3415
|
+
.glim-toast-body {
|
|
3416
|
+
display: flex;
|
|
3254
3417
|
flex: 1 1 0%;
|
|
3418
|
+
flex-direction: column;
|
|
3419
|
+
gap: 0.5rem;
|
|
3255
3420
|
min-width: 0;
|
|
3421
|
+
}
|
|
3422
|
+
.glim-toast-message {
|
|
3256
3423
|
margin: 0;
|
|
3424
|
+
text-wrap: pretty;
|
|
3257
3425
|
font-size: 0.875rem;
|
|
3258
3426
|
line-height: 1.375;
|
|
3259
3427
|
overflow-wrap: break-word;
|
|
3260
3428
|
}
|
|
3429
|
+
/* A phone keeps the window in view: the newest two across its width. */
|
|
3430
|
+
@media (max-width: 600px) {
|
|
3431
|
+
.glim-toast-stack {
|
|
3432
|
+
inset-inline-start: 0;
|
|
3433
|
+
padding: 0.5rem;
|
|
3434
|
+
}
|
|
3435
|
+
.glim-toast-stack > :nth-last-child(n + 3) { display: none; }
|
|
3436
|
+
.glim-toast-card {
|
|
3437
|
+
width: 100%;
|
|
3438
|
+
max-width: none;
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3261
3441
|
.glim-toast-dismiss {
|
|
3262
3442
|
flex-shrink: 0;
|
|
3263
3443
|
margin: -0.25rem;
|
|
@@ -3432,7 +3612,12 @@ body {
|
|
|
3432
3612
|
so two always fit a row. */
|
|
3433
3613
|
.glim-sel--pairs { align-items: stretch; }
|
|
3434
3614
|
@media (max-width: 600px) {
|
|
3435
|
-
.glim-sel--pairs {
|
|
3615
|
+
.glim-sel--pairs {
|
|
3616
|
+
--seg-basis: calc(50% - 0.25rem);
|
|
3617
|
+
width: 100%;
|
|
3618
|
+
}
|
|
3619
|
+
/* A pill around several rows bulges at its ends. */
|
|
3620
|
+
.glim-sel--pairs.glim-sel--well { border-radius: var(--radius-card); }
|
|
3436
3621
|
}
|
|
3437
3622
|
|
|
3438
3623
|
.glim-sel-seg {
|
|
@@ -3540,6 +3725,7 @@ body {
|
|
|
3540
3725
|
.glim-sel-label--wrap {
|
|
3541
3726
|
white-space: normal;
|
|
3542
3727
|
text-wrap: balance;
|
|
3728
|
+
overflow-wrap: break-word;
|
|
3543
3729
|
}
|
|
3544
3730
|
|
|
3545
3731
|
/* Under a finger a 20px pill is too small to hit. A well is a row of
|
|
@@ -3555,7 +3741,8 @@ body {
|
|
|
3555
3741
|
its glyph reads the fill's ink. */
|
|
3556
3742
|
.glim-sel-seg.glim-hue-icon:not(.glim-active) > svg,
|
|
3557
3743
|
.glim-sel-tile.glim-hue-icon:not(.glim-active) > svg,
|
|
3558
|
-
.glim-nav-row:not(.glim-active) > svg
|
|
3744
|
+
.glim-nav-row:not(.glim-active) > svg,
|
|
3745
|
+
.glim-nav-row:not(.glim-active) > .glim-nav-row-main > svg {
|
|
3559
3746
|
color: var(--accent-glyph);
|
|
3560
3747
|
}
|
|
3561
3748
|
|
|
@@ -3685,6 +3872,46 @@ body {
|
|
|
3685
3872
|
.glim-nav-row:not(.glim-active):hover:dir(rtl) { translate: -2px 0; }
|
|
3686
3873
|
}
|
|
3687
3874
|
.glim-nav-row--centred { justify-content: center; }
|
|
3875
|
+
button.glim-nav-row {
|
|
3876
|
+
width: 100%;
|
|
3877
|
+
text-align: start;
|
|
3878
|
+
cursor: pointer;
|
|
3879
|
+
}
|
|
3880
|
+
/* A row with something beside its link. The link's press covers the row, and
|
|
3881
|
+
what stands in a slot lies above that press. The narrow rail has no room for
|
|
3882
|
+
a slot. */
|
|
3883
|
+
.glim-nav-row--slots { gap: 0.5rem; }
|
|
3884
|
+
/* A tree's row: each level steps in by the chevron's width, and the smaller
|
|
3885
|
+
glyph and gap leave a deep name its room. */
|
|
3886
|
+
.glim-nav-row--tree {
|
|
3887
|
+
gap: 0.5rem;
|
|
3888
|
+
padding-inline-start: calc(0.5rem + var(--nav-depth, 0) * 0.85rem);
|
|
3889
|
+
}
|
|
3890
|
+
.glim-nav-row--tree > .glim-nav-row-main { gap: 0.5rem; }
|
|
3891
|
+
.glim-nav-row-main {
|
|
3892
|
+
display: flex;
|
|
3893
|
+
flex: 1 1 auto;
|
|
3894
|
+
align-items: center;
|
|
3895
|
+
gap: 0.75rem;
|
|
3896
|
+
min-width: 0;
|
|
3897
|
+
text-align: start;
|
|
3898
|
+
text-decoration: none;
|
|
3899
|
+
cursor: pointer;
|
|
3900
|
+
}
|
|
3901
|
+
.glim-nav-row-main::after {
|
|
3902
|
+
content: "";
|
|
3903
|
+
position: absolute;
|
|
3904
|
+
inset: 0;
|
|
3905
|
+
border-radius: inherit;
|
|
3906
|
+
}
|
|
3907
|
+
.glim-nav-row-slot {
|
|
3908
|
+
position: relative;
|
|
3909
|
+
z-index: 1;
|
|
3910
|
+
display: inline-flex;
|
|
3911
|
+
flex: none;
|
|
3912
|
+
align-items: center;
|
|
3913
|
+
gap: 0.25rem;
|
|
3914
|
+
}
|
|
3688
3915
|
.glim-nav-label {
|
|
3689
3916
|
min-width: 0;
|
|
3690
3917
|
overflow: hidden;
|
|
@@ -3815,4 +4042,858 @@ body {
|
|
|
3815
4042
|
.glim-subcard .glim-sel--chip .glim-sel-seg:not(.glim-active):not(:disabled):hover {
|
|
3816
4043
|
background-color: var(--carbon-hover-raised);
|
|
3817
4044
|
}
|
|
4045
|
+
|
|
4046
|
+
/* The general window (Window): the confirm surface's frame, grown to hold a
|
|
4047
|
+
form, a list or a whole tool at three widths. Its notch sits in the card's
|
|
4048
|
+
padding, so the body starts far enough down to clear it, and the start of
|
|
4049
|
+
the foot holds one quiet line, such as where the work carries on. */
|
|
4050
|
+
.glim-window { max-width: 40rem; }
|
|
4051
|
+
.glim-window--wide { max-width: 58rem; }
|
|
4052
|
+
.glim-window--full {
|
|
4053
|
+
max-width: 80rem;
|
|
4054
|
+
height: calc(100vh - 2rem - var(--window-bar));
|
|
4055
|
+
max-height: none;
|
|
4056
|
+
}
|
|
4057
|
+
.glim-window-title { margin: 0; }
|
|
4058
|
+
.glim-window-body {
|
|
4059
|
+
display: flex;
|
|
4060
|
+
flex-direction: column;
|
|
4061
|
+
gap: 1rem;
|
|
4062
|
+
padding-top: 1.75rem;
|
|
4063
|
+
}
|
|
4064
|
+
/* The start text gives way first and wraps, so a button does not drop to the
|
|
4065
|
+
next line for a few pixels. */
|
|
4066
|
+
.glim-window-start {
|
|
4067
|
+
flex: 1 1 0;
|
|
4068
|
+
min-width: min(4rem, 100%);
|
|
4069
|
+
overflow-wrap: anywhere;
|
|
4070
|
+
font-size: var(--text-meta);
|
|
4071
|
+
color: var(--carbon-text-muted);
|
|
4072
|
+
}
|
|
4073
|
+
|
|
4074
|
+
/* The context menu and the menus of the bar (ContextMenu, MenuBar). Both sit
|
|
4075
|
+
on the body, so no card or scroll box clips them, and a submenu is a menu
|
|
4076
|
+
of its own beside its row: inside the first one, that menu's scrolling
|
|
4077
|
+
would cut it off. Above windows, below toasts and bubbles. */
|
|
4078
|
+
.glim-menu {
|
|
4079
|
+
position: fixed;
|
|
4080
|
+
z-index: 60;
|
|
4081
|
+
display: flex;
|
|
4082
|
+
flex-direction: column;
|
|
4083
|
+
min-width: 16rem;
|
|
4084
|
+
max-height: calc(100vh - 2rem);
|
|
4085
|
+
overflow: auto;
|
|
4086
|
+
padding: 0.35rem;
|
|
4087
|
+
border-radius: var(--radius-card);
|
|
4088
|
+
background-color: var(--carbon-surface);
|
|
4089
|
+
box-shadow: var(--elevation), var(--hairline);
|
|
4090
|
+
}
|
|
4091
|
+
.glim-menu-item {
|
|
4092
|
+
display: flex;
|
|
4093
|
+
flex: none;
|
|
4094
|
+
align-items: center;
|
|
4095
|
+
gap: 0.6rem;
|
|
4096
|
+
height: 2rem;
|
|
4097
|
+
padding-inline: 0.6rem;
|
|
4098
|
+
border-radius: var(--radius-control);
|
|
4099
|
+
font-size: var(--text-body);
|
|
4100
|
+
text-align: start;
|
|
4101
|
+
white-space: nowrap;
|
|
4102
|
+
cursor: pointer;
|
|
4103
|
+
}
|
|
4104
|
+
/* A menu the pointer opened carries data-pointer until a key is pressed in
|
|
4105
|
+
it, so the first row it focused stays unlit (focusFirstMenuRow). */
|
|
4106
|
+
.glim-menu-item:hover,
|
|
4107
|
+
.glim-menu:not([data-pointer]) .glim-menu-item:focus-visible,
|
|
4108
|
+
.glim-menu-item[aria-expanded="true"] { background-color: var(--carbon-hover); }
|
|
4109
|
+
.glim-menu-item:disabled {
|
|
4110
|
+
opacity: 0.45;
|
|
4111
|
+
cursor: default;
|
|
4112
|
+
}
|
|
4113
|
+
.glim-menu-item:disabled:hover { background-color: transparent; }
|
|
4114
|
+
/* The current choice of a radio group, washed rather than filled, since the
|
|
4115
|
+
tick at its end already says which. */
|
|
4116
|
+
.glim-menu-item--current { background-color: var(--accent-soft); }
|
|
4117
|
+
/* Also the empty room of a row without a glyph, so every label starts at one edge. */
|
|
4118
|
+
.glim-menu-glyph {
|
|
4119
|
+
display: inline-grid;
|
|
4120
|
+
flex: none;
|
|
4121
|
+
width: 0.95rem;
|
|
4122
|
+
height: 0.95rem;
|
|
4123
|
+
color: var(--accent-glyph);
|
|
4124
|
+
}
|
|
4125
|
+
.glim-menu-glyph > svg {
|
|
4126
|
+
width: 100%;
|
|
4127
|
+
height: 100%;
|
|
4128
|
+
}
|
|
4129
|
+
.glim-menu-dot {
|
|
4130
|
+
flex: none;
|
|
4131
|
+
width: 0.95rem;
|
|
4132
|
+
height: 0.95rem;
|
|
4133
|
+
border-radius: var(--radius-pill);
|
|
4134
|
+
}
|
|
4135
|
+
.glim-menu-label {
|
|
4136
|
+
flex: 1 1 auto;
|
|
4137
|
+
min-width: 0;
|
|
4138
|
+
overflow: hidden;
|
|
4139
|
+
text-overflow: ellipsis;
|
|
4140
|
+
}
|
|
4141
|
+
.glim-menu-end {
|
|
4142
|
+
display: inline-flex;
|
|
4143
|
+
flex: none;
|
|
4144
|
+
align-items: center;
|
|
4145
|
+
margin-inline-start: auto;
|
|
4146
|
+
}
|
|
4147
|
+
.glim-menu-tick { color: var(--accent-glyph); }
|
|
4148
|
+
.glim-menu-count {
|
|
4149
|
+
padding-inline-start: 1.2rem;
|
|
4150
|
+
font-size: var(--text-meta);
|
|
4151
|
+
color: var(--carbon-text-muted);
|
|
4152
|
+
}
|
|
4153
|
+
.glim-menu-caret { color: var(--carbon-text-muted); }
|
|
4154
|
+
.glim-menu-caret svg {
|
|
4155
|
+
width: 0.7rem;
|
|
4156
|
+
height: 0.7rem;
|
|
4157
|
+
rotate: -90deg;
|
|
4158
|
+
}
|
|
4159
|
+
.glim-menu-caret:dir(rtl) svg { rotate: 90deg; }
|
|
4160
|
+
.glim-menu-sep {
|
|
4161
|
+
flex: none;
|
|
4162
|
+
height: 1px;
|
|
4163
|
+
margin: 0.3rem 0.4rem;
|
|
4164
|
+
background-color: color-mix(in srgb, var(--carbon-text) 9%, transparent);
|
|
4165
|
+
}
|
|
4166
|
+
.glim-menu-head {
|
|
4167
|
+
display: flex;
|
|
4168
|
+
align-items: center;
|
|
4169
|
+
gap: 0.5rem;
|
|
4170
|
+
min-height: 1.6rem;
|
|
4171
|
+
padding-block: 0.35rem 0.2rem;
|
|
4172
|
+
padding-inline: 0.6rem 0.3rem;
|
|
4173
|
+
font-size: var(--text-meta);
|
|
4174
|
+
letter-spacing: 0.14em;
|
|
4175
|
+
text-transform: uppercase;
|
|
4176
|
+
color: var(--carbon-text-muted);
|
|
4177
|
+
}
|
|
4178
|
+
.glim-menu-head-edit {
|
|
4179
|
+
display: grid;
|
|
4180
|
+
flex: none;
|
|
4181
|
+
place-items: center;
|
|
4182
|
+
width: 1.6rem;
|
|
4183
|
+
height: 1.6rem;
|
|
4184
|
+
margin-inline-start: auto;
|
|
4185
|
+
border-radius: var(--radius-control);
|
|
4186
|
+
color: var(--accent-glyph);
|
|
4187
|
+
cursor: pointer;
|
|
4188
|
+
}
|
|
4189
|
+
.glim-menu-head-edit:hover,
|
|
4190
|
+
.glim-menu:not([data-pointer]) .glim-menu-head-edit:focus-visible { background-color: var(--carbon-hover); }
|
|
4191
|
+
.glim-menu-head-edit svg {
|
|
4192
|
+
width: 0.85rem;
|
|
4193
|
+
height: 0.85rem;
|
|
4194
|
+
}
|
|
4195
|
+
|
|
4196
|
+
/* The menu bar of a desktop-style app's head row: bare words that take the
|
|
4197
|
+
second surface under the pointer and while their menu is open. */
|
|
4198
|
+
.glim-menubar {
|
|
4199
|
+
display: flex;
|
|
4200
|
+
flex: none;
|
|
4201
|
+
align-items: center;
|
|
4202
|
+
gap: 2px;
|
|
4203
|
+
}
|
|
4204
|
+
.glim-menubar-item {
|
|
4205
|
+
height: 2.2rem;
|
|
4206
|
+
padding-inline: 0.7rem;
|
|
4207
|
+
border-radius: var(--radius-pill);
|
|
4208
|
+
font-weight: 500;
|
|
4209
|
+
color: var(--carbon-text-sub);
|
|
4210
|
+
cursor: pointer;
|
|
4211
|
+
}
|
|
4212
|
+
.glim-menubar-item:hover,
|
|
4213
|
+
.glim-menubar-item[aria-expanded="true"] {
|
|
4214
|
+
background-color: var(--carbon-surface2);
|
|
4215
|
+
color: var(--carbon-text);
|
|
4216
|
+
}
|
|
4217
|
+
|
|
4218
|
+
/* The checkbox (Checkbox, and the box of a menu's checkbox item): the one
|
|
4219
|
+
place a box stands instead of a switch (rule 39). Drawn rather than the
|
|
4220
|
+
system's, at the control radius held small enough to stay a box, and when
|
|
4221
|
+
ticked the accent with the tick in its contrast ink. */
|
|
4222
|
+
.glim-checkbox {
|
|
4223
|
+
display: inline-flex;
|
|
4224
|
+
align-items: center;
|
|
4225
|
+
gap: 0.6rem;
|
|
4226
|
+
min-height: 2rem;
|
|
4227
|
+
padding-inline: 0.4rem;
|
|
4228
|
+
border-radius: var(--radius-control);
|
|
4229
|
+
text-align: start;
|
|
4230
|
+
cursor: pointer;
|
|
4231
|
+
}
|
|
4232
|
+
.glim-checkbox:hover { background-color: var(--carbon-hover); }
|
|
4233
|
+
.glim-checkbox:disabled {
|
|
4234
|
+
opacity: 0.55;
|
|
4235
|
+
cursor: default;
|
|
4236
|
+
}
|
|
4237
|
+
.glim-checkbox:disabled:hover { background-color: transparent; }
|
|
4238
|
+
.glim-checkbox-box {
|
|
4239
|
+
display: grid;
|
|
4240
|
+
flex: none;
|
|
4241
|
+
place-items: center;
|
|
4242
|
+
width: 1.125rem;
|
|
4243
|
+
height: 1.125rem;
|
|
4244
|
+
border-radius: min(var(--radius-control), 5px);
|
|
4245
|
+
background-color: color-mix(in srgb, var(--carbon-surface3) 60%, transparent);
|
|
4246
|
+
color: transparent;
|
|
4247
|
+
}
|
|
4248
|
+
.glim-checkbox-box > svg {
|
|
4249
|
+
width: 0.75rem;
|
|
4250
|
+
height: 0.75rem;
|
|
4251
|
+
}
|
|
4252
|
+
[aria-checked="true"] > .glim-checkbox-box {
|
|
4253
|
+
background-color: var(--accent);
|
|
4254
|
+
color: var(--accent-contrast);
|
|
4255
|
+
}
|
|
4256
|
+
/* The slim checkbox: the box alone, for a row or a cell of a dense list,
|
|
4257
|
+
where the frame's padding and hover ground would crowd the row. The row
|
|
4258
|
+
around it gives the hover, and the box only firms up. */
|
|
4259
|
+
.glim-checkbox--slim {
|
|
4260
|
+
min-height: 0;
|
|
4261
|
+
padding: 0;
|
|
4262
|
+
border-radius: min(var(--radius-control), 5px);
|
|
4263
|
+
}
|
|
4264
|
+
.glim-checkbox--slim:hover { background-color: transparent; }
|
|
4265
|
+
.glim-checkbox--slim[aria-checked="false"]:not(:disabled):hover > .glim-checkbox-box {
|
|
4266
|
+
background-color: var(--carbon-surface3);
|
|
4267
|
+
}
|
|
4268
|
+
|
|
4269
|
+
/* A key cap (Kbd), in the app's own type rather than the browser's monospace. */
|
|
4270
|
+
.glim-kbd {
|
|
4271
|
+
display: inline-grid;
|
|
4272
|
+
place-items: center;
|
|
4273
|
+
height: 1.2rem;
|
|
4274
|
+
padding-inline: 0.4rem;
|
|
4275
|
+
border-radius: var(--radius-control);
|
|
4276
|
+
background-color: var(--carbon-surface3);
|
|
4277
|
+
font-family: inherit;
|
|
4278
|
+
font-size: var(--text-meta);
|
|
4279
|
+
color: var(--carbon-text-sub);
|
|
4280
|
+
white-space: nowrap;
|
|
4281
|
+
}
|
|
4282
|
+
|
|
4283
|
+
/* The data pill (Pill): one value of a row, quiet at rest. A state takes a
|
|
4284
|
+
wash of its solid colour over the second surface, so the text keeps the
|
|
4285
|
+
body ink and a column of pills still reads as one column. */
|
|
4286
|
+
.glim-well,
|
|
4287
|
+
.glim-subcard {
|
|
4288
|
+
--pill-ground: var(--carbon-surface3);
|
|
4289
|
+
--pill-state: var(--carbon-hover-raised);
|
|
4290
|
+
}
|
|
4291
|
+
.glim-pill {
|
|
4292
|
+
display: inline-flex;
|
|
4293
|
+
flex: none;
|
|
4294
|
+
align-items: center;
|
|
4295
|
+
height: 1.35rem;
|
|
4296
|
+
padding-inline: 0.55rem;
|
|
4297
|
+
border-radius: var(--radius-pill);
|
|
4298
|
+
background-color: var(--pill-ground, var(--carbon-surface2));
|
|
4299
|
+
font-size: var(--text-meta);
|
|
4300
|
+
color: var(--carbon-text-sub);
|
|
4301
|
+
white-space: nowrap;
|
|
4302
|
+
}
|
|
4303
|
+
.glim-pill--state { background-color: var(--pill-state, var(--carbon-surface3)); color: var(--carbon-text); }
|
|
4304
|
+
.glim-pill--ok { background-color: color-mix(in srgb, var(--pill-ground, var(--carbon-surface2)), var(--status-ok-solid) 30%); color: var(--carbon-text); }
|
|
4305
|
+
.glim-pill--warn { background-color: color-mix(in srgb, var(--pill-ground, var(--carbon-surface2)), var(--status-warn-solid) 35%); color: var(--carbon-text); }
|
|
4306
|
+
.glim-pill--fail { background-color: color-mix(in srgb, var(--pill-ground, var(--carbon-surface2)), var(--status-fail-solid) 35%); color: var(--carbon-text); }
|
|
4307
|
+
|
|
4308
|
+
/* A text field (PasswordField, CopyField): borderless and filled (rule 14),
|
|
4309
|
+
a step up the ramp on focus and inside a sub-card, like the number field.
|
|
4310
|
+
It fills its column; a width belongs to the wrapper around it. */
|
|
4311
|
+
.glim-input {
|
|
4312
|
+
width: 100%;
|
|
4313
|
+
min-width: 0;
|
|
4314
|
+
height: var(--btn-h);
|
|
4315
|
+
padding-inline: 0.75rem;
|
|
4316
|
+
border-radius: var(--radius-control);
|
|
4317
|
+
background-color: var(--carbon-surface2);
|
|
4318
|
+
color: var(--carbon-text);
|
|
4319
|
+
font-size: var(--text-body);
|
|
4320
|
+
line-height: 1.25rem;
|
|
4321
|
+
}
|
|
4322
|
+
.glim-input:focus,
|
|
4323
|
+
.glim-well .glim-input,
|
|
4324
|
+
.glim-subcard .glim-input { background-color: var(--carbon-surface3); }
|
|
4325
|
+
.glim-well .glim-num-field { background-color: var(--carbon-surface3); }
|
|
4326
|
+
.glim-well .glim-num-field:focus { background-color: var(--carbon-hover-raised); }
|
|
4327
|
+
.glim-well .glim-input:focus,
|
|
4328
|
+
.glim-subcard .glim-input:focus { background-color: var(--carbon-hover-raised); }
|
|
4329
|
+
.glim-input:disabled {
|
|
4330
|
+
opacity: 0.5;
|
|
4331
|
+
cursor: not-allowed;
|
|
4332
|
+
}
|
|
4333
|
+
.glim-input::placeholder { color: var(--carbon-text-muted); }
|
|
4334
|
+
.glim-input--mono {
|
|
4335
|
+
font-family: ui-monospace, "Cascadia Code", Menlo, Consolas, monospace;
|
|
4336
|
+
font-size: var(--text-subline);
|
|
4337
|
+
text-overflow: ellipsis;
|
|
4338
|
+
}
|
|
4339
|
+
|
|
4340
|
+
/* A few lines of text (TextArea): the field's look, grown by its corner. */
|
|
4341
|
+
.glim-input--area {
|
|
4342
|
+
display: block;
|
|
4343
|
+
height: auto;
|
|
4344
|
+
min-height: calc(var(--btn-h) * 2);
|
|
4345
|
+
padding-block: 0.4rem;
|
|
4346
|
+
resize: vertical;
|
|
4347
|
+
}
|
|
4348
|
+
|
|
4349
|
+
/* One labelled row (FieldRow, rule 35): the name at the start and its controls
|
|
4350
|
+
together at the end. The name's margin takes the free room, so a growing
|
|
4351
|
+
control gets all of it, and a control that drops under the name keeps the
|
|
4352
|
+
row's end through the justify. */
|
|
4353
|
+
.glim-field-row {
|
|
4354
|
+
display: flex;
|
|
4355
|
+
flex-wrap: wrap;
|
|
4356
|
+
align-items: center;
|
|
4357
|
+
justify-content: flex-end;
|
|
4358
|
+
gap: 0.35rem 0.75rem;
|
|
4359
|
+
min-height: var(--btn-h);
|
|
4360
|
+
}
|
|
4361
|
+
.glim-field-row-name {
|
|
4362
|
+
display: flex;
|
|
4363
|
+
flex: 0 1 auto;
|
|
4364
|
+
align-items: center;
|
|
4365
|
+
gap: 0.35rem;
|
|
4366
|
+
min-width: 0;
|
|
4367
|
+
margin-inline-end: auto;
|
|
4368
|
+
}
|
|
4369
|
+
.glim-field-row-label small {
|
|
4370
|
+
font-size: var(--text-meta);
|
|
4371
|
+
color: var(--carbon-text-muted);
|
|
4372
|
+
}
|
|
4373
|
+
.glim-field-row > :not(.glim-field-row-name) { max-width: 100%; }
|
|
4374
|
+
|
|
4375
|
+
.glim-field-row > .glim-slider {
|
|
4376
|
+
flex: 1 1 13rem;
|
|
4377
|
+
min-width: 0;
|
|
4378
|
+
}
|
|
4379
|
+
.glim-field-row > .glim-combobox {
|
|
4380
|
+
flex: 0 1 16rem;
|
|
4381
|
+
min-width: 0;
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
/* Rows that share a column for their names (FieldRowGroup): a grid as wide as
|
|
4385
|
+
the longest name, handed down to each row. Their controls sit in one cell,
|
|
4386
|
+
and on a phone the rows go back to wrapping on their own. */
|
|
4387
|
+
.glim-field-row-group {
|
|
4388
|
+
display: grid;
|
|
4389
|
+
grid-template-columns: repeat(var(--field-columns, 1), max-content minmax(0, 1fr));
|
|
4390
|
+
gap: 0.5rem 1.5rem;
|
|
4391
|
+
}
|
|
4392
|
+
.glim-field-row-group > .glim-field-row {
|
|
4393
|
+
display: grid;
|
|
4394
|
+
grid-column: span 2;
|
|
4395
|
+
grid-template-columns: subgrid;
|
|
4396
|
+
column-gap: 0.75rem;
|
|
4397
|
+
}
|
|
4398
|
+
.glim-field-row-group > .glim-field-row--wide { grid-column: 1 / -1; }
|
|
4399
|
+
.glim-field-row--wide > .glim-field-row-controls { grid-column: 2 / -1; }
|
|
4400
|
+
.glim-field-row-controls {
|
|
4401
|
+
display: flex;
|
|
4402
|
+
align-items: center;
|
|
4403
|
+
justify-content: flex-end;
|
|
4404
|
+
gap: 0.35rem 0.75rem;
|
|
4405
|
+
min-width: 0;
|
|
4406
|
+
}
|
|
4407
|
+
@media (max-width: 600px) {
|
|
4408
|
+
.glim-field-row-group {
|
|
4409
|
+
display: flex;
|
|
4410
|
+
flex-direction: column;
|
|
4411
|
+
}
|
|
4412
|
+
.glim-field-row-group > .glim-field-row { display: flex; }
|
|
4413
|
+
.glim-field-row-controls { flex: 1 1 13rem; }
|
|
4414
|
+
}
|
|
4415
|
+
|
|
4416
|
+
/* A field with a glyph inside (GlyphField). The box is the field, so it takes
|
|
4417
|
+
the input's focus step, and what stands after the input sits in its room. */
|
|
4418
|
+
.glim-glyph-field {
|
|
4419
|
+
display: flex;
|
|
4420
|
+
align-items: center;
|
|
4421
|
+
gap: 0.4rem;
|
|
4422
|
+
padding-inline: 0.65rem 0.15rem;
|
|
4423
|
+
cursor: text;
|
|
4424
|
+
}
|
|
4425
|
+
.glim-glyph-field:focus-within { background-color: var(--carbon-surface3); }
|
|
4426
|
+
:is(.glim-well, .glim-subcard) .glim-glyph-field:focus-within { background-color: var(--carbon-hover-raised); }
|
|
4427
|
+
.glim-glyph-field-glyph {
|
|
4428
|
+
display: inline-grid;
|
|
4429
|
+
flex: none;
|
|
4430
|
+
width: 0.95rem;
|
|
4431
|
+
height: 0.95rem;
|
|
4432
|
+
color: var(--carbon-text-sub);
|
|
4433
|
+
}
|
|
4434
|
+
.glim-glyph-field-glyph > svg {
|
|
4435
|
+
width: 100%;
|
|
4436
|
+
height: 100%;
|
|
4437
|
+
}
|
|
4438
|
+
.glim-glyph-field-input {
|
|
4439
|
+
flex: 1;
|
|
4440
|
+
min-width: 0;
|
|
4441
|
+
height: 100%;
|
|
4442
|
+
text-overflow: ellipsis;
|
|
4443
|
+
}
|
|
4444
|
+
.glim-glyph-field-input::placeholder { color: var(--carbon-text-muted); }
|
|
4445
|
+
.glim-glyph-field > .glim-icon-btn {
|
|
4446
|
+
width: 1.6rem;
|
|
4447
|
+
height: 1.6rem;
|
|
4448
|
+
}
|
|
4449
|
+
|
|
4450
|
+
/* A small holder for a glyph (GlyphTile). It fills with the accent while the
|
|
4451
|
+
row, button or link around it is reached ("Lists"). */
|
|
4452
|
+
.glim-tile {
|
|
4453
|
+
display: inline-grid;
|
|
4454
|
+
flex: none;
|
|
4455
|
+
place-items: center;
|
|
4456
|
+
width: 1.75rem;
|
|
4457
|
+
height: 1.75rem;
|
|
4458
|
+
border-radius: var(--radius-control);
|
|
4459
|
+
color: var(--accent-glyph);
|
|
4460
|
+
}
|
|
4461
|
+
.glim-tile > svg {
|
|
4462
|
+
width: 1rem;
|
|
4463
|
+
height: 1rem;
|
|
4464
|
+
}
|
|
4465
|
+
.glim-tile--quiet { color: var(--carbon-text-sub); }
|
|
4466
|
+
.glim-tile--ground { background-color: var(--carbon-surface3); }
|
|
4467
|
+
.glim-tile--active,
|
|
4468
|
+
:is(button, a, .glim-list-row, .glim-nav-row):is(:hover, :focus-visible, :focus-within) > .glim-tile {
|
|
4469
|
+
background-color: var(--accent);
|
|
4470
|
+
color: var(--accent-contrast);
|
|
4471
|
+
}
|
|
4472
|
+
|
|
4473
|
+
/* A short list of facts in columns (Table). Hairlines at low opacity part the
|
|
4474
|
+
rows, and there is no box around them (rule 5). */
|
|
4475
|
+
.glim-table {
|
|
4476
|
+
width: 100%;
|
|
4477
|
+
border-collapse: collapse;
|
|
4478
|
+
font-size: var(--text-subline);
|
|
4479
|
+
}
|
|
4480
|
+
.glim-table :is(th, td) {
|
|
4481
|
+
padding: 0.4rem 0.5rem;
|
|
4482
|
+
text-align: start;
|
|
4483
|
+
white-space: nowrap;
|
|
4484
|
+
}
|
|
4485
|
+
.glim-table th {
|
|
4486
|
+
font-size: var(--text-meta);
|
|
4487
|
+
font-weight: 500;
|
|
4488
|
+
color: var(--carbon-text-muted);
|
|
4489
|
+
}
|
|
4490
|
+
.glim-table tr + tr td,
|
|
4491
|
+
.glim-table thead + tbody tr:first-child td {
|
|
4492
|
+
box-shadow: inset 0 1px 0 color-mix(in srgb, var(--carbon-text) 7%, transparent);
|
|
4493
|
+
}
|
|
4494
|
+
.glim-table :is(th, td).glim-table-end { text-align: end; }
|
|
4495
|
+
.glim-table td.glim-table-muted { color: var(--carbon-text-muted); }
|
|
4496
|
+
.glim-table td.glim-table-accent { color: var(--accent-ink); }
|
|
4497
|
+
|
|
4498
|
+
/* A path and its picker's button (PathField). */
|
|
4499
|
+
.glim-path {
|
|
4500
|
+
display: flex;
|
|
4501
|
+
flex: 1 1 13rem;
|
|
4502
|
+
align-items: center;
|
|
4503
|
+
gap: 0.4rem;
|
|
4504
|
+
min-width: 0;
|
|
4505
|
+
max-width: 30rem;
|
|
4506
|
+
}
|
|
4507
|
+
.glim-path > .glim-input { flex: 1; }
|
|
4508
|
+
|
|
4509
|
+
/* A hierarchy to walk through (Tree). Each level steps in by the chevron's
|
|
4510
|
+
width, and the chosen row is filled as a selection is (rule 3). */
|
|
4511
|
+
.glim-tree {
|
|
4512
|
+
display: flex;
|
|
4513
|
+
flex-direction: column;
|
|
4514
|
+
gap: 2px;
|
|
4515
|
+
min-width: 0;
|
|
4516
|
+
overflow: auto;
|
|
4517
|
+
}
|
|
4518
|
+
.glim-tree-row {
|
|
4519
|
+
display: flex;
|
|
4520
|
+
flex: none;
|
|
4521
|
+
align-items: center;
|
|
4522
|
+
gap: 0.3rem;
|
|
4523
|
+
height: var(--btn-h);
|
|
4524
|
+
padding-inline: calc(0.3rem + var(--tree-level, 0) * 0.85rem) 0.55rem;
|
|
4525
|
+
border-radius: var(--radius-control);
|
|
4526
|
+
font-size: var(--text-body);
|
|
4527
|
+
cursor: pointer;
|
|
4528
|
+
user-select: none;
|
|
4529
|
+
}
|
|
4530
|
+
.glim-tree-row:not([aria-selected="true"]):hover { background-color: var(--carbon-hover); }
|
|
4531
|
+
.glim-well .glim-tree-row:not([aria-selected="true"]):hover { background-color: var(--carbon-surface3); }
|
|
4532
|
+
.glim-tree-row[aria-selected="true"] {
|
|
4533
|
+
background-color: var(--accent);
|
|
4534
|
+
color: var(--accent-contrast);
|
|
4535
|
+
}
|
|
4536
|
+
.glim-tree-toggle {
|
|
4537
|
+
display: grid;
|
|
4538
|
+
flex: none;
|
|
4539
|
+
place-items: center;
|
|
4540
|
+
width: 1.1rem;
|
|
4541
|
+
height: 1.1rem;
|
|
4542
|
+
border-radius: var(--radius-control);
|
|
4543
|
+
color: var(--carbon-text-muted);
|
|
4544
|
+
}
|
|
4545
|
+
.glim-tree-toggle:hover {
|
|
4546
|
+
background-color: color-mix(in srgb, currentColor 18%, transparent);
|
|
4547
|
+
color: var(--carbon-text);
|
|
4548
|
+
}
|
|
4549
|
+
.glim-tree-toggle > svg {
|
|
4550
|
+
width: 0.7rem;
|
|
4551
|
+
height: 0.7rem;
|
|
4552
|
+
rotate: -90deg;
|
|
4553
|
+
}
|
|
4554
|
+
.glim-tree-toggle:dir(rtl) > svg { rotate: 90deg; }
|
|
4555
|
+
[aria-expanded="true"] > .glim-tree-toggle > svg { rotate: none; }
|
|
4556
|
+
.glim-tree-glyph {
|
|
4557
|
+
display: inline-grid;
|
|
4558
|
+
flex: none;
|
|
4559
|
+
width: 1.05rem;
|
|
4560
|
+
height: 1.05rem;
|
|
4561
|
+
color: var(--accent-glyph);
|
|
4562
|
+
}
|
|
4563
|
+
.glim-tree-glyph > svg {
|
|
4564
|
+
width: 100%;
|
|
4565
|
+
height: 100%;
|
|
4566
|
+
}
|
|
4567
|
+
[aria-selected="true"] > :is(.glim-tree-toggle, .glim-tree-glyph) { color: var(--accent-contrast); }
|
|
4568
|
+
.glim-tree-label {
|
|
4569
|
+
min-width: 0;
|
|
4570
|
+
overflow: hidden;
|
|
4571
|
+
text-overflow: ellipsis;
|
|
4572
|
+
white-space: nowrap;
|
|
4573
|
+
}
|
|
4574
|
+
|
|
4575
|
+
/* The round mark on a row picked for an action on many (RowMark, rule 39).
|
|
4576
|
+
The fill reads --accent, so a row with a rainbow position hands it its hue. */
|
|
4577
|
+
.glim-rowmark {
|
|
4578
|
+
display: grid;
|
|
4579
|
+
flex: none;
|
|
4580
|
+
place-items: center;
|
|
4581
|
+
width: 1.125rem;
|
|
4582
|
+
height: 1.125rem;
|
|
4583
|
+
border-radius: var(--radius-pill);
|
|
4584
|
+
background-color: color-mix(in srgb, var(--carbon-surface3) 60%, transparent);
|
|
4585
|
+
color: transparent;
|
|
4586
|
+
}
|
|
4587
|
+
.glim-rowmark > svg {
|
|
4588
|
+
width: 0.75rem;
|
|
4589
|
+
height: 0.75rem;
|
|
4590
|
+
}
|
|
4591
|
+
.glim-rowmark--on {
|
|
4592
|
+
background-color: var(--accent);
|
|
4593
|
+
color: var(--accent-contrast);
|
|
4594
|
+
}
|
|
4595
|
+
|
|
4596
|
+
/* One row of a list (ListRow). The buttons stand at their place while out of
|
|
4597
|
+
sight, so a hover moves nothing, and a row without hover shows them (rule 6). */
|
|
4598
|
+
.glim-list-row {
|
|
4599
|
+
display: flex;
|
|
4600
|
+
align-items: center;
|
|
4601
|
+
gap: 0.6rem;
|
|
4602
|
+
min-width: 0;
|
|
4603
|
+
min-height: 2.6rem;
|
|
4604
|
+
padding-inline: 0.5rem;
|
|
4605
|
+
border-radius: var(--radius-control);
|
|
4606
|
+
}
|
|
4607
|
+
.glim-list-row:is(:hover, :focus-within) { background-color: var(--carbon-hover); }
|
|
4608
|
+
.glim-list-row--opens { cursor: pointer; }
|
|
4609
|
+
.glim-list-row-tile {
|
|
4610
|
+
display: grid;
|
|
4611
|
+
flex: none;
|
|
4612
|
+
place-items: center;
|
|
4613
|
+
width: 1.75rem;
|
|
4614
|
+
height: 1.75rem;
|
|
4615
|
+
border-radius: var(--radius-control);
|
|
4616
|
+
color: var(--accent-glyph);
|
|
4617
|
+
}
|
|
4618
|
+
.glim-list-row-tile > svg {
|
|
4619
|
+
width: 1.05rem;
|
|
4620
|
+
height: 1.05rem;
|
|
4621
|
+
}
|
|
4622
|
+
.glim-list-row:is(:hover, :focus-within) > .glim-list-row-tile {
|
|
4623
|
+
background-color: var(--accent);
|
|
4624
|
+
color: var(--accent-contrast);
|
|
4625
|
+
}
|
|
4626
|
+
.glim-list-row-name {
|
|
4627
|
+
display: flex;
|
|
4628
|
+
flex: 1 1 0;
|
|
4629
|
+
align-items: center;
|
|
4630
|
+
gap: 0.4rem;
|
|
4631
|
+
min-width: 0;
|
|
4632
|
+
white-space: nowrap;
|
|
4633
|
+
}
|
|
4634
|
+
.glim-list-row-name--mono {
|
|
4635
|
+
font-family: ui-monospace, "Cascadia Code", Menlo, Consolas, monospace;
|
|
4636
|
+
font-size: var(--text-subline);
|
|
4637
|
+
}
|
|
4638
|
+
.glim-list-row-title {
|
|
4639
|
+
min-width: 0;
|
|
4640
|
+
overflow: hidden;
|
|
4641
|
+
text-overflow: ellipsis;
|
|
4642
|
+
}
|
|
4643
|
+
.glim-list-row-tip { display: contents; }
|
|
4644
|
+
.glim-list-row-badges {
|
|
4645
|
+
display: flex;
|
|
4646
|
+
flex: none;
|
|
4647
|
+
flex-wrap: wrap;
|
|
4648
|
+
align-items: center;
|
|
4649
|
+
justify-content: flex-end;
|
|
4650
|
+
gap: 0.35rem;
|
|
4651
|
+
}
|
|
4652
|
+
.glim-list-row-actions {
|
|
4653
|
+
display: flex;
|
|
4654
|
+
flex: none;
|
|
4655
|
+
gap: 0.15rem;
|
|
4656
|
+
opacity: 0;
|
|
4657
|
+
}
|
|
4658
|
+
.glim-list-row:is(:hover, :focus-within) > .glim-list-row-actions { opacity: 1; }
|
|
4659
|
+
@media (hover: none) {
|
|
4660
|
+
.glim-list-row-actions { opacity: 1; }
|
|
4661
|
+
}
|
|
4662
|
+
@media (max-width: 600px) {
|
|
4663
|
+
.glim-list-row-badges { display: none; }
|
|
4664
|
+
}
|
|
4665
|
+
|
|
4666
|
+
/* A glyph in a square in every label mode (IconButton), half its box as any
|
|
4667
|
+
glyph alone (rule 13). It has no ground, so .glim-btn-bare turns the glyph
|
|
4668
|
+
to the tint when it is reached (rule 40). The gap holds the place of a
|
|
4669
|
+
button a row does not have. */
|
|
4670
|
+
.glim-icon-btn {
|
|
4671
|
+
display: grid;
|
|
4672
|
+
flex: none;
|
|
4673
|
+
place-items: center;
|
|
4674
|
+
width: var(--btn-h);
|
|
4675
|
+
height: var(--btn-h);
|
|
4676
|
+
border-radius: var(--radius-control);
|
|
4677
|
+
color: var(--carbon-text-sub);
|
|
4678
|
+
cursor: pointer;
|
|
4679
|
+
}
|
|
4680
|
+
.glim-icon-btn > svg {
|
|
4681
|
+
width: 1rem;
|
|
4682
|
+
height: 1rem;
|
|
4683
|
+
}
|
|
4684
|
+
.glim-icon-btn:disabled {
|
|
4685
|
+
opacity: 0.45;
|
|
4686
|
+
cursor: default;
|
|
4687
|
+
}
|
|
4688
|
+
.glim-icon-btn[aria-pressed="true"] {
|
|
4689
|
+
background-color: var(--accent-soft);
|
|
4690
|
+
color: var(--accent-glyph);
|
|
4691
|
+
}
|
|
4692
|
+
.glim-icon-btn-gap {
|
|
4693
|
+
flex: none;
|
|
4694
|
+
width: var(--btn-h);
|
|
4695
|
+
height: var(--btn-h);
|
|
4696
|
+
}
|
|
4697
|
+
|
|
4698
|
+
/* The reveal eye ("The reveal eye" in the design language): a bare glyph in
|
|
4699
|
+
the field's trailing padding, neutral, and the wrapper as wide as a plain
|
|
4700
|
+
field. Edge draws an eye of its own into every password field, which
|
|
4701
|
+
would stand beside this one. */
|
|
4702
|
+
.glim-secret {
|
|
4703
|
+
position: relative;
|
|
4704
|
+
display: block;
|
|
4705
|
+
width: 100%;
|
|
4706
|
+
min-width: 0;
|
|
4707
|
+
}
|
|
4708
|
+
.glim-secret > .glim-input { padding-inline-end: 2.4rem; }
|
|
4709
|
+
.glim-secret > .glim-input::-ms-reveal { display: none; }
|
|
4710
|
+
.glim-secret-eye {
|
|
4711
|
+
position: absolute;
|
|
4712
|
+
inset-inline-end: 0.35rem;
|
|
4713
|
+
top: 50%;
|
|
4714
|
+
translate: 0 -50%;
|
|
4715
|
+
display: grid;
|
|
4716
|
+
place-items: center;
|
|
4717
|
+
width: 1.6rem;
|
|
4718
|
+
height: 1.6rem;
|
|
4719
|
+
border-radius: var(--radius-control);
|
|
4720
|
+
color: var(--carbon-text-muted);
|
|
4721
|
+
cursor: pointer;
|
|
4722
|
+
}
|
|
4723
|
+
.glim-secret-eye:hover { color: var(--carbon-text); }
|
|
4724
|
+
.glim-secret-eye > svg {
|
|
4725
|
+
width: 0.95rem;
|
|
4726
|
+
height: 0.95rem;
|
|
4727
|
+
}
|
|
4728
|
+
|
|
4729
|
+
/* A value to copy (CopyField): the value in monospace, read-only so it can
|
|
4730
|
+
still be selected and scrolled, and its button beside it. */
|
|
4731
|
+
.glim-copy {
|
|
4732
|
+
display: flex;
|
|
4733
|
+
align-items: center;
|
|
4734
|
+
gap: 0.4rem;
|
|
4735
|
+
width: 100%;
|
|
4736
|
+
min-width: 0;
|
|
4737
|
+
}
|
|
4738
|
+
.glim-copy > .glim-input { flex: 1; }
|
|
4739
|
+
|
|
4740
|
+
/* A field's width (FieldWidth), on the input or on the wrapper that holds it.
|
|
4741
|
+
After the wrappers, whose own width it replaces. */
|
|
4742
|
+
.glim-field--short {
|
|
4743
|
+
flex: none;
|
|
4744
|
+
width: 5.5rem;
|
|
4745
|
+
}
|
|
4746
|
+
.glim-field--medium {
|
|
4747
|
+
flex: none;
|
|
4748
|
+
width: 12rem;
|
|
4749
|
+
max-width: 100%;
|
|
4750
|
+
}
|
|
4751
|
+
.glim-field--wide {
|
|
4752
|
+
flex: none;
|
|
4753
|
+
width: 22rem;
|
|
4754
|
+
max-width: 100%;
|
|
4755
|
+
}
|
|
4756
|
+
.glim-field--grow {
|
|
4757
|
+
flex: 1 1 13rem;
|
|
4758
|
+
width: auto;
|
|
4759
|
+
min-width: 0;
|
|
4760
|
+
}
|
|
4761
|
+
|
|
4762
|
+
/* Words for a screen reader alone, such as the "Copied" a copy button
|
|
4763
|
+
announces. */
|
|
4764
|
+
.glim-sr-only {
|
|
4765
|
+
position: absolute;
|
|
4766
|
+
width: 1px;
|
|
4767
|
+
height: 1px;
|
|
4768
|
+
margin: -1px;
|
|
4769
|
+
overflow: hidden;
|
|
4770
|
+
clip-path: inset(50%);
|
|
4771
|
+
white-space: nowrap;
|
|
4772
|
+
}
|
|
4773
|
+
|
|
4774
|
+
/* The meter (Meter): a level on the third surface, thin beside a row's name
|
|
4775
|
+
or as wide as its column. At its threshold the fill turns to the fault
|
|
4776
|
+
colour. In the active row of a rail it takes the row's contrast ink, as
|
|
4777
|
+
the row's count does. */
|
|
4778
|
+
.glim-meter-track {
|
|
4779
|
+
position: relative;
|
|
4780
|
+
display: block;
|
|
4781
|
+
overflow: hidden;
|
|
4782
|
+
border-radius: var(--radius-pill);
|
|
4783
|
+
background-color: var(--carbon-surface3);
|
|
4784
|
+
}
|
|
4785
|
+
.glim-meter-track--small {
|
|
4786
|
+
display: inline-block;
|
|
4787
|
+
flex: none;
|
|
4788
|
+
width: 2.6rem;
|
|
4789
|
+
height: 0.35rem;
|
|
4790
|
+
vertical-align: middle;
|
|
4791
|
+
}
|
|
4792
|
+
.glim-meter-track--medium {
|
|
4793
|
+
width: 100%;
|
|
4794
|
+
height: 0.55rem;
|
|
4795
|
+
}
|
|
4796
|
+
.glim-meter-fill {
|
|
4797
|
+
display: block;
|
|
4798
|
+
height: 100%;
|
|
4799
|
+
border-radius: inherit;
|
|
4800
|
+
background-color: var(--accent);
|
|
4801
|
+
}
|
|
4802
|
+
/* The quiet meter: slim and grey, for a footer line or a dense list, where
|
|
4803
|
+
an accent bar on every row would outshout the names beside it. Inside a
|
|
4804
|
+
button it takes the accent when the button is reached, as the button's
|
|
4805
|
+
own glyph does (rule 40). The threshold still turns it red. */
|
|
4806
|
+
.glim-meter-track--quiet {
|
|
4807
|
+
height: 0.35rem;
|
|
4808
|
+
background-color: var(--carbon-surface2);
|
|
4809
|
+
}
|
|
4810
|
+
.glim-meter-track--quiet > .glim-meter-fill { background-color: var(--carbon-text-muted); }
|
|
4811
|
+
:is(button, a):is(:hover, :focus-visible) .glim-meter-track--quiet:not(.glim-meter-track--full) > .glim-meter-fill {
|
|
4812
|
+
background-color: var(--accent);
|
|
4813
|
+
}
|
|
4814
|
+
.glim-meter-track--full .glim-meter-fill { background-color: var(--status-fail-solid); }
|
|
4815
|
+
.glim-active .glim-meter-track { background-color: color-mix(in srgb, var(--accent-contrast) 22%, transparent); }
|
|
4816
|
+
.glim-active .glim-meter-fill { background-color: var(--accent-contrast); }
|
|
4817
|
+
|
|
4818
|
+
/* The progress bar (ProgressBar): a thicker track whose fill carries a
|
|
4819
|
+
sheen while the work runs. Paused takes the waiting tone and a failure
|
|
4820
|
+
the fault colour (rule 4). */
|
|
4821
|
+
.glim-progress {
|
|
4822
|
+
position: relative;
|
|
4823
|
+
display: block;
|
|
4824
|
+
width: 100%;
|
|
4825
|
+
height: 0.6rem;
|
|
4826
|
+
overflow: hidden;
|
|
4827
|
+
border-radius: var(--radius-pill);
|
|
4828
|
+
background-color: var(--carbon-surface3);
|
|
4829
|
+
}
|
|
4830
|
+
.glim-progress-fill {
|
|
4831
|
+
position: absolute;
|
|
4832
|
+
inset-block: 0;
|
|
4833
|
+
inset-inline-start: 0;
|
|
4834
|
+
overflow: hidden;
|
|
4835
|
+
border-radius: inherit;
|
|
4836
|
+
background-color: var(--accent);
|
|
4837
|
+
}
|
|
4838
|
+
.glim-progress-fill::after {
|
|
4839
|
+
content: "";
|
|
4840
|
+
position: absolute;
|
|
4841
|
+
inset: 0;
|
|
4842
|
+
background: linear-gradient(100deg, transparent 20%, rgb(255 255 255 / 0.45) 50%, transparent 80%);
|
|
4843
|
+
translate: -100% 0;
|
|
4844
|
+
}
|
|
4845
|
+
.glim-progress--paused .glim-progress-fill { background-color: var(--status-neutral-solid); }
|
|
4846
|
+
.glim-progress--failed .glim-progress-fill { background-color: var(--status-fail-solid); }
|
|
4847
|
+
|
|
4848
|
+
/* Without a value the track shows stripes, which no value could be
|
|
4849
|
+
mistaken for. A progress bar swaps them for a light that crosses the
|
|
4850
|
+
track, set up in the motion gate. */
|
|
4851
|
+
:is(.glim-meter-track--busy, .glim-progress--busy) > :is(.glim-meter-fill, .glim-progress-fill) {
|
|
4852
|
+
position: absolute;
|
|
4853
|
+
inset-block: 0;
|
|
4854
|
+
left: 0;
|
|
4855
|
+
width: 100%;
|
|
4856
|
+
background: repeating-linear-gradient(-45deg, var(--accent) 0 4px, transparent 4px 8px);
|
|
4857
|
+
opacity: 0.5;
|
|
4858
|
+
}
|
|
4859
|
+
.glim-meter-track--quiet.glim-meter-track--busy > .glim-meter-fill {
|
|
4860
|
+
background: repeating-linear-gradient(-45deg, var(--carbon-text-muted) 0 4px, transparent 4px 8px);
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
|
|
4864
|
+
/* Outside the layer, or the house ring's offset would win: inside a menu the
|
|
4865
|
+
ring is drawn on the row, where the menu's edge cannot clip it. */
|
|
4866
|
+
.glim-menu-item:focus-visible,
|
|
4867
|
+
.glim-menu-head-edit:focus-visible,
|
|
4868
|
+
.glim-tree-row:focus-visible,
|
|
4869
|
+
.glim-list-row:focus-visible { outline-offset: -2px; }
|
|
4870
|
+
.glim-menu[data-pointer] :focus-visible { outline: none; }
|
|
4871
|
+
/* Also outside the layer: a field says it has the focus with its fill and its
|
|
4872
|
+
caret, not with a ring (rule 14). */
|
|
4873
|
+
.glim-input:focus-visible,
|
|
4874
|
+
.glim-num-field:focus-visible,
|
|
4875
|
+
.glim-glyph-field-input:focus-visible { outline: none; }
|
|
4876
|
+
/* The ring of a row with slots goes around the row, not around its link alone. */
|
|
4877
|
+
.glim-nav-row-main:focus-visible { outline: none; }
|
|
4878
|
+
.glim-nav-row--slots:has(> .glim-nav-row-main:focus-visible) {
|
|
4879
|
+
outline: 2px solid var(--focus-ring);
|
|
4880
|
+
outline-offset: 2px;
|
|
4881
|
+
}
|
|
4882
|
+
/* An app's own rule for links outranks the layer, so a link with a button's look
|
|
4883
|
+
takes its colour back from there. */
|
|
4884
|
+
a:is(.glim-btn, .glim-icon-btn) {
|
|
4885
|
+
color: revert-layer;
|
|
4886
|
+
text-decoration: none;
|
|
4887
|
+
}
|
|
4888
|
+
/* Under the message, at its end. The stage's floor is for a row of buttons. */
|
|
4889
|
+
.glim-toast-action {
|
|
4890
|
+
align-self: flex-end;
|
|
4891
|
+
min-width: 0;
|
|
4892
|
+
}
|
|
4893
|
+
|
|
4894
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
4895
|
+
.glim-checkbox-box,
|
|
4896
|
+
.glim-rowmark { transition: background-color var(--motion-control-dur) ease; }
|
|
4897
|
+
.glim-list-row-actions { transition: opacity var(--motion-control-dur) ease; }
|
|
4898
|
+
.glim-tree-toggle > svg { transition: rotate var(--motion-control-dur) ease; }
|
|
3818
4899
|
}
|