@glimstone/core 4.1.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/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
 
@@ -1935,6 +1946,11 @@ body {
1935
1946
  .glim-btn-sm { min-width: var(--btn-w-sm); }
1936
1947
  .glim-btn-md { min-width: var(--btn-w-md); }
1937
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; }
1938
1954
 
1939
1955
  /* Rule 40. A surface-filled button's hovered ground takes 22% of the tint and
1940
1956
  its glyph all of it; its words keep the text colour, which the accent on a
@@ -1956,7 +1972,7 @@ body {
1956
1972
  .glim-btn-bare:not(:disabled):is(:hover, :focus-visible) {
1957
1973
  color: var(--btn-tint);
1958
1974
  }
1959
- .glim-btn-bare:is(:hover, :focus-visible) {
1975
+ .glim-btn-bare:not([aria-pressed="true"]):is(:hover, :focus-visible) {
1960
1976
  background-color: transparent;
1961
1977
  }
1962
1978
 
@@ -2291,14 +2307,17 @@ body {
2291
2307
  height, sized by its glyph. In a mode that shows words it is an ordinary
2292
2308
  button with its label (see `ButtonVariant` in packages/react/src/Button.tsx). */
2293
2309
  .glim-btn-icon {
2294
- width: var(--btn-h);
2295
- min-width: 0;
2310
+ min-width: var(--btn-h);
2296
2311
  padding-inline: 0;
2297
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
+ }
2298
2317
 
2299
2318
  /* A row action promoted to a key control stays square at the other height. */
2300
2319
  .glim-btn-icon.glim-btn-key {
2301
- width: var(--btn-h-key);
2320
+ min-width: var(--btn-h-key);
2302
2321
  }
2303
2322
 
2304
2323
  /* A glyph alone in a square fills half its box, as on a 32px icon badge with a
@@ -2588,6 +2607,13 @@ body {
2588
2607
  outline: 2px solid var(--focus-ring);
2589
2608
  outline-offset: 1px;
2590
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); }
2591
2617
  .glim-select-trigger[data-disabled] { opacity: 0.5; cursor: default; }
2592
2618
  /* Busy: the trigger keeps its focus and takes no input until the answer is back. */
2593
2619
  .glim-select-trigger[data-readonly] { opacity: 0.5; cursor: progress; }
@@ -2756,6 +2782,37 @@ body {
2756
2782
  @media (pointer: coarse) {
2757
2783
  .glim-select-item { min-height: 2.75rem; }
2758
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
+ }
2759
2816
  .glim-select-empty {
2760
2817
  padding: 0.5rem 0.75rem;
2761
2818
  color: var(--carbon-text-muted);
@@ -2795,6 +2852,7 @@ body {
2795
2852
  .glim-slider-thumb[data-dragging] { cursor: grabbing; }
2796
2853
  .glim-slider-thumb[data-disabled] { opacity: 0.5; cursor: default; }
2797
2854
  .glim-slider-value {
2855
+ margin-inline-start: auto;
2798
2856
  color: var(--carbon-text);
2799
2857
  font-size: var(--text-body);
2800
2858
  font-variant-numeric: tabular-nums;
@@ -2813,7 +2871,7 @@ body {
2813
2871
  :where([class*="glim-"]) :where(*, ::before, ::after) {
2814
2872
  box-sizing: border-box;
2815
2873
  }
2816
- :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) {
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) {
2817
2875
  margin: 0;
2818
2876
  padding: 0;
2819
2877
  border: 0 solid;
@@ -2905,11 +2963,20 @@ body {
2905
2963
  }
2906
2964
  .glim-modal-foot {
2907
2965
  display: flex;
2966
+ flex-wrap: wrap;
2908
2967
  align-items: center;
2909
2968
  justify-content: flex-end;
2910
2969
  gap: 0.75rem;
2911
2970
  padding: 1rem 1.25rem;
2912
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; }
2913
2980
 
2914
2981
  /* The fills a button can take (ButtonTone). `ok`, `danger` and `warn` put the
2915
2982
  solid status tokens under the ground's ink: in both themes the solid values
@@ -2957,7 +3024,7 @@ body {
2957
3024
  width: 2.25rem;
2958
3025
  height: 1.25rem;
2959
3026
  border-radius: var(--radius-pill);
2960
- background-color: var(--carbon-surface3);
3027
+ background-color: var(--toggle-off);
2961
3028
  transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
2962
3029
  }
2963
3030
  .glim-toggle-track[aria-checked="true"] { background-color: var(--accent); }
@@ -3328,7 +3395,7 @@ body {
3328
3395
  display: flex;
3329
3396
  align-items: flex-start;
3330
3397
  gap: 0.625rem;
3331
- width: 20rem;
3398
+ width: 24rem;
3332
3399
  max-width: calc(100vw - 2rem);
3333
3400
  padding: 0.75rem 0.875rem;
3334
3401
  border-radius: var(--radius-card);
@@ -3345,14 +3412,32 @@ body {
3345
3412
  .glim-toast-glyph--success { color: var(--status-ok-solid); }
3346
3413
  .glim-toast-glyph--warn { color: var(--status-warn-solid); }
3347
3414
  .glim-toast-glyph--fail { color: var(--status-fail-solid); }
3348
- .glim-toast-message {
3415
+ .glim-toast-body {
3416
+ display: flex;
3349
3417
  flex: 1 1 0%;
3418
+ flex-direction: column;
3419
+ gap: 0.5rem;
3350
3420
  min-width: 0;
3421
+ }
3422
+ .glim-toast-message {
3351
3423
  margin: 0;
3424
+ text-wrap: pretty;
3352
3425
  font-size: 0.875rem;
3353
3426
  line-height: 1.375;
3354
3427
  overflow-wrap: break-word;
3355
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
+ }
3356
3441
  .glim-toast-dismiss {
3357
3442
  flex-shrink: 0;
3358
3443
  margin: -0.25rem;
@@ -3527,7 +3612,12 @@ body {
3527
3612
  so two always fit a row. */
3528
3613
  .glim-sel--pairs { align-items: stretch; }
3529
3614
  @media (max-width: 600px) {
3530
- .glim-sel--pairs { --seg-basis: calc(50% - 0.25rem); }
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); }
3531
3621
  }
3532
3622
 
3533
3623
  .glim-sel-seg {
@@ -3635,6 +3725,7 @@ body {
3635
3725
  .glim-sel-label--wrap {
3636
3726
  white-space: normal;
3637
3727
  text-wrap: balance;
3728
+ overflow-wrap: break-word;
3638
3729
  }
3639
3730
 
3640
3731
  /* Under a finger a 20px pill is too small to hit. A well is a row of
@@ -3650,7 +3741,8 @@ body {
3650
3741
  its glyph reads the fill's ink. */
3651
3742
  .glim-sel-seg.glim-hue-icon:not(.glim-active) > svg,
3652
3743
  .glim-sel-tile.glim-hue-icon:not(.glim-active) > svg,
3653
- .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 {
3654
3746
  color: var(--accent-glyph);
3655
3747
  }
3656
3748
 
@@ -3780,6 +3872,46 @@ body {
3780
3872
  .glim-nav-row:not(.glim-active):hover:dir(rtl) { translate: -2px 0; }
3781
3873
  }
3782
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
+ }
3783
3915
  .glim-nav-label {
3784
3916
  min-width: 0;
3785
3917
  overflow: hidden;
@@ -3929,8 +4061,12 @@ body {
3929
4061
  gap: 1rem;
3930
4062
  padding-top: 1.75rem;
3931
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. */
3932
4066
  .glim-window-start {
3933
- margin-inline-end: auto;
4067
+ flex: 1 1 0;
4068
+ min-width: min(4rem, 100%);
4069
+ overflow-wrap: anywhere;
3934
4070
  font-size: var(--text-meta);
3935
4071
  color: var(--carbon-text-muted);
3936
4072
  }
@@ -4147,6 +4283,11 @@ body {
4147
4283
  /* The data pill (Pill): one value of a row, quiet at rest. A state takes a
4148
4284
  wash of its solid colour over the second surface, so the text keeps the
4149
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
+ }
4150
4291
  .glim-pill {
4151
4292
  display: inline-flex;
4152
4293
  flex: none;
@@ -4154,15 +4295,15 @@ body {
4154
4295
  height: 1.35rem;
4155
4296
  padding-inline: 0.55rem;
4156
4297
  border-radius: var(--radius-pill);
4157
- background-color: var(--carbon-surface2);
4298
+ background-color: var(--pill-ground, var(--carbon-surface2));
4158
4299
  font-size: var(--text-meta);
4159
4300
  color: var(--carbon-text-sub);
4160
4301
  white-space: nowrap;
4161
4302
  }
4162
- .glim-pill--state { background-color: var(--carbon-surface3); color: var(--carbon-text); }
4163
- .glim-pill--ok { background-color: color-mix(in srgb, var(--carbon-surface2), var(--status-ok-solid) 30%); color: var(--carbon-text); }
4164
- .glim-pill--warn { background-color: color-mix(in srgb, var(--carbon-surface2), var(--status-warn-solid) 35%); color: var(--carbon-text); }
4165
- .glim-pill--fail { background-color: color-mix(in srgb, var(--carbon-surface2), var(--status-fail-solid) 35%); color: var(--carbon-text); }
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); }
4166
4307
 
4167
4308
  /* A text field (PasswordField, CopyField): borderless and filled (rule 14),
4168
4309
  a step up the ramp on focus and inside a sub-card, like the number field.
@@ -4179,8 +4320,12 @@ body {
4179
4320
  line-height: 1.25rem;
4180
4321
  }
4181
4322
  .glim-input:focus,
4182
- .glim-well .glim-input { background-color: var(--carbon-surface3); }
4183
- .glim-well .glim-input:focus { background-color: var(--carbon-hover-raised); }
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); }
4184
4329
  .glim-input:disabled {
4185
4330
  opacity: 0.5;
4186
4331
  cursor: not-allowed;
@@ -4192,6 +4337,364 @@ body {
4192
4337
  text-overflow: ellipsis;
4193
4338
  }
4194
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
+
4195
4698
  /* The reveal eye ("The reveal eye" in the design language): a bare glyph in
4196
4699
  the field's trailing padding, neutral, and the wrapper as wide as a plain
4197
4700
  field. Edge draws an eye of its own into every password field, which
@@ -4234,6 +4737,28 @@ body {
4234
4737
  }
4235
4738
  .glim-copy > .glim-input { flex: 1; }
4236
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
+
4237
4762
  /* Words for a screen reader alone, such as the "Copied" a copy button
4238
4763
  announces. */
4239
4764
  .glim-sr-only {
@@ -4339,9 +4864,36 @@ body {
4339
4864
  /* Outside the layer, or the house ring's offset would win: inside a menu the
4340
4865
  ring is drawn on the row, where the menu's edge cannot clip it. */
4341
4866
  .glim-menu-item:focus-visible,
4342
- .glim-menu-head-edit:focus-visible { outline-offset: -2px; }
4867
+ .glim-menu-head-edit:focus-visible,
4868
+ .glim-tree-row:focus-visible,
4869
+ .glim-list-row:focus-visible { outline-offset: -2px; }
4343
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
+ }
4344
4893
 
4345
4894
  @media (prefers-reduced-motion: no-preference) {
4346
- .glim-checkbox-box { transition: background-color var(--motion-control-dur) ease; }
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; }
4347
4899
  }