@apliteni/apliteni-ui 0.53.4 → 0.55.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/guidelines/colour-and-theming.md +12 -0
- package/guidelines/component-choice.md +1 -1
- package/guidelines/drawer.md +4 -4
- package/package.json +1 -1
- package/react/dist/index.css +37 -21
- package/src/styles/back.css +1 -1
- package/src/styles/badge.css +5 -10
- package/src/styles/button.css +9 -7
- package/src/styles/callout.css +2 -2
- package/src/styles/card.css +15 -5
- package/src/styles/code.css +2 -2
- package/src/styles/command-palette.css +8 -8
- package/src/styles/drawer.css +5 -10
- package/src/styles/dropdown.css +14 -16
- package/src/styles/feedback.css +5 -5
- package/src/styles/input.css +5 -3
- package/src/styles/layout.css +13 -21
- package/src/styles/nav.css +14 -17
- package/src/styles/pagination.css +1 -1
- package/src/styles/segmented.css +10 -5
- package/src/styles/table.css +26 -3
- package/src/styles/tooltip.css +4 -4
- package/src/styles/topbar.css +5 -5
- package/src/tokens/tokens.css +42 -14
|
@@ -54,3 +54,15 @@
|
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
<!-- rule: both-themes -->
|
|
57
|
+
|
|
58
|
+
## Keep text off grey fills
|
|
59
|
+
|
|
60
|
+
<!-- rule: text-surface -->
|
|
61
|
+
|
|
62
|
+
**Rule:** Put text on the page or card surface, never on a grey fill.
|
|
63
|
+
|
|
64
|
+
**Why:** Grey blocks make reading areas look disabled.
|
|
65
|
+
|
|
66
|
+
**Do:** Draw inputs with an edge. Keep grey fills for non-text states, such as disabled tracks and dividers.
|
|
67
|
+
|
|
68
|
+
**Don't:** Put text on grey fields, chips, headers or footers.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
**Why:** A confirm keeps keyboard focus until answered; a callout does not interrupt.
|
|
22
22
|
|
|
23
|
-
**Except:** Use a
|
|
23
|
+
**Except:** Use a content-sized modal for a short form and a drawer for a long form.
|
|
24
24
|
|
|
25
25
|
**Do:** Ask “Rotate this token?” in a confirm with “Keep token” and “Rotate token” buttons.
|
|
26
26
|
|
package/guidelines/drawer.md
CHANGED
|
@@ -26,15 +26,15 @@
|
|
|
26
26
|
|
|
27
27
|
**Don't:** Put each group in a card inside the drawer.
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Header and group dividers
|
|
30
30
|
|
|
31
31
|
<!-- rule: three-lines -->
|
|
32
32
|
|
|
33
|
-
**Rule:**
|
|
33
|
+
**Rule:** Add lines below the header and between groups. Leave the footer unfilled and without a rule.
|
|
34
34
|
|
|
35
|
-
**Why:**
|
|
35
|
+
**Why:** The header line marks the scrolling body; group lines separate content, and actions share the panel surface.
|
|
36
36
|
|
|
37
|
-
**Do:** Separate header
|
|
37
|
+
**Do:** Separate the header and groups.
|
|
38
38
|
|
|
39
39
|
**Don't:** Add dividers between every row.
|
|
40
40
|
|
package/package.json
CHANGED
package/react/dist/index.css
CHANGED
|
@@ -30,8 +30,7 @@
|
|
|
30
30
|
.rx-scrim {
|
|
31
31
|
position: fixed;
|
|
32
32
|
inset: 0;
|
|
33
|
-
background:
|
|
34
|
-
backdrop-filter: blur(2px);
|
|
33
|
+
background: color-mix(in srgb, var(--shadow-ink) 82%, transparent);
|
|
35
34
|
display: grid;
|
|
36
35
|
place-items: center;
|
|
37
36
|
z-index: calc(var(--z-overlay) + 1);
|
|
@@ -42,14 +41,18 @@
|
|
|
42
41
|
opacity: 1;
|
|
43
42
|
}
|
|
44
43
|
.rx-modal {
|
|
45
|
-
width: min(
|
|
44
|
+
width: min(calc(var(--panel-lg) - var(--space-10) * 2), 96vw);
|
|
45
|
+
max-height: 96vh;
|
|
46
|
+
max-height: 96dvh;
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
46
49
|
background: var(--bg-elevated);
|
|
47
50
|
--ring-gap: var(--bg-elevated);
|
|
48
|
-
border:
|
|
49
|
-
box-shadow:
|
|
50
|
-
border-radius: var(--radius-
|
|
51
|
+
border: 0;
|
|
52
|
+
box-shadow: var(--elev-drop);
|
|
53
|
+
border-radius: var(--radius-md);
|
|
51
54
|
overflow: hidden;
|
|
52
|
-
transform: translateY(
|
|
55
|
+
transform: translateY(var(--space-2));
|
|
53
56
|
transition: transform var(--dur-med) var(--ease);
|
|
54
57
|
}
|
|
55
58
|
.rx-scrim.is-open .rx-modal {
|
|
@@ -59,25 +62,38 @@
|
|
|
59
62
|
display: flex;
|
|
60
63
|
align-items: center;
|
|
61
64
|
justify-content: space-between;
|
|
62
|
-
|
|
65
|
+
gap: var(--space-3);
|
|
66
|
+
flex: none;
|
|
67
|
+
padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
|
|
63
68
|
border-bottom: 1px solid var(--border);
|
|
64
69
|
}
|
|
65
70
|
.rx-modal__title {
|
|
66
|
-
font-weight:
|
|
67
|
-
font-size: var(--text-
|
|
71
|
+
font-weight: var(--weight-normal);
|
|
72
|
+
font-size: var(--text-base);
|
|
73
|
+
color: var(--text);
|
|
68
74
|
}
|
|
69
75
|
.rx-modal__body {
|
|
70
|
-
padding:
|
|
76
|
+
padding: var(--space-4);
|
|
71
77
|
display: flex;
|
|
72
78
|
flex-direction: column;
|
|
73
|
-
gap:
|
|
79
|
+
gap: var(--space-4);
|
|
80
|
+
min-height: 0;
|
|
81
|
+
overflow: auto;
|
|
82
|
+
}
|
|
83
|
+
.rx-modal__body > * {
|
|
84
|
+
flex-shrink: 0;
|
|
74
85
|
}
|
|
75
86
|
.rx-modal__foot {
|
|
76
87
|
display: flex;
|
|
77
88
|
justify-content: flex-end;
|
|
78
|
-
gap:
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
gap: var(--space-3);
|
|
90
|
+
flex: none;
|
|
91
|
+
padding: var(--space-4);
|
|
92
|
+
}
|
|
93
|
+
.rx-modal__head > .ui-btn {
|
|
94
|
+
width: calc(var(--space-10) + var(--space-1));
|
|
95
|
+
height: calc(var(--space-10) + var(--space-1));
|
|
96
|
+
flex: none;
|
|
81
97
|
}
|
|
82
98
|
|
|
83
99
|
/* src/DataTable.css */
|
|
@@ -250,8 +266,8 @@
|
|
|
250
266
|
font-family: var(--font-sans);
|
|
251
267
|
font-size: var(--text-base);
|
|
252
268
|
color: var(--strong);
|
|
253
|
-
background: var(--
|
|
254
|
-
border: 1px solid var(--
|
|
269
|
+
background: var(--field-bg);
|
|
270
|
+
border: 1px solid var(--field-edge);
|
|
255
271
|
border-radius: var(--radius-md);
|
|
256
272
|
padding: 12px 15px;
|
|
257
273
|
width: 100%;
|
|
@@ -265,7 +281,7 @@
|
|
|
265
281
|
.ui-input:hover,
|
|
266
282
|
.ui-textarea:hover,
|
|
267
283
|
.ui-select:hover {
|
|
268
|
-
border-color: var(--
|
|
284
|
+
border-color: var(--field-edge-hover);
|
|
269
285
|
}
|
|
270
286
|
.ui-input:focus-visible,
|
|
271
287
|
.ui-textarea:focus-visible,
|
|
@@ -461,16 +477,16 @@
|
|
|
461
477
|
align-items: center;
|
|
462
478
|
gap: 8px;
|
|
463
479
|
padding: 24px;
|
|
464
|
-
border: 1px dashed var(--
|
|
480
|
+
border: 1px dashed var(--field-edge);
|
|
465
481
|
border-radius: var(--radius-md);
|
|
466
|
-
background: var(--
|
|
482
|
+
background: var(--field-bg);
|
|
467
483
|
color: var(--text);
|
|
468
484
|
font-size: var(--text-base);
|
|
469
485
|
text-align: center;
|
|
470
486
|
overflow-wrap: anywhere;
|
|
471
487
|
}
|
|
472
488
|
.ui-file:hover {
|
|
473
|
-
border-color: var(--
|
|
489
|
+
border-color: var(--field-edge-hover);
|
|
474
490
|
}
|
|
475
491
|
.ui-file:focus-within,
|
|
476
492
|
.ui-file.is-dragging {
|
package/src/styles/back.css
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
(0,2,0) wins without !important — the argument `.ui-nav .ui-nav__item` makes
|
|
32
32
|
in nav.css. */
|
|
33
33
|
.ui-back[href] { color: var(--text); }
|
|
34
|
-
.ui-back[href]:hover { color: var(--strong); background: var(--surface
|
|
34
|
+
.ui-back[href]:hover { color: var(--strong); background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
35
35
|
.ui-back:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
|
|
36
36
|
|
|
37
37
|
/* 16px, with the stroke raised to match: the glyph set draws at 1.7 on a 24-unit
|
package/src/styles/badge.css
CHANGED
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
padding: 3px 9px;
|
|
16
16
|
border-radius: var(--radius-pill);
|
|
17
17
|
color: var(--text);
|
|
18
|
-
background: var(--surface
|
|
18
|
+
background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */
|
|
19
19
|
white-space: nowrap;
|
|
20
20
|
}
|
|
21
21
|
/* Status chips take the --chip-* pairs, so the light app's solid fills live in
|
|
22
22
|
tokens.css rather than in a theme override down here: on white the glow-tints
|
|
23
23
|
wash out and the ink has to deepen to clear AA, and that is a token decision. */
|
|
24
24
|
.ui-badge--live { color: var(--chip-success-ink); background: var(--chip-success-fill); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
25
|
-
.ui-badge--soon { color: var(--
|
|
25
|
+
.ui-badge--soon { color: var(--accent); background: var(--surface); /* ring-gap: inherit — translucent wash retains the opaque containing gap. */ }
|
|
26
26
|
.ui-badge--info { color: var(--chip-info-ink); background: var(--chip-info-fill); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
27
27
|
.ui-badge--warn { color: var(--chip-warn-ink); background: var(--chip-warn-fill); }
|
|
28
28
|
.ui-badge--danger { color: var(--chip-danger-ink); background: var(--chip-danger-fill); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
@@ -32,12 +32,7 @@
|
|
|
32
32
|
(paid / verified / pending / failed …). Same chip, mapped to meaning. */
|
|
33
33
|
.ui-badge--success { color: var(--chip-success-ink); background: var(--chip-success-fill); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
34
34
|
.ui-badge--pending { color: var(--chip-warn-ink); background: var(--chip-warn-fill); }
|
|
35
|
-
.ui-badge--neutral { color: var(--text); background: var(--surface
|
|
36
|
-
|
|
37
|
-
/* The two neutral chips are the exception: their light fill is already in the
|
|
38
|
-
surface scale (--surface-3), and only archive uses muted state ink. */
|
|
39
|
-
:root[data-theme="light"] .ui-badge--neutral { background: var(--surface-3); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
40
|
-
:root[data-theme="light"] .ui-badge--archive { /* muted-ink: state — archived record */ color: var(--muted); background: var(--surface-3); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
35
|
+
.ui-badge--neutral { color: var(--text); background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
41
36
|
|
|
42
37
|
/* Pill: same shape, sentence case, a touch larger — a metadata chip */
|
|
43
38
|
.ui-pill {
|
|
@@ -47,7 +42,7 @@
|
|
|
47
42
|
/* rank: chip */
|
|
48
43
|
font-size: var(--text-xs);
|
|
49
44
|
color: var(--text);
|
|
50
|
-
background: var(--surface
|
|
45
|
+
background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */
|
|
51
46
|
border-radius: var(--radius-pill);
|
|
52
47
|
padding: 4px 11px;
|
|
53
48
|
font-weight: var(--weight-semibold);
|
|
@@ -56,7 +51,7 @@
|
|
|
56
51
|
same pair. On its own it was --green on --glow-green, which is 3.97:1 over
|
|
57
52
|
white — under AA, while the badge beside it cleared at 4.64:1. See issue #131. */
|
|
58
53
|
.ui-pill--live { color: var(--chip-success-ink); background: var(--chip-success-fill); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
59
|
-
.ui-pill--soon { color: var(--
|
|
54
|
+
.ui-pill--soon { color: var(--accent); background: var(--surface); /* ring-gap: inherit — translucent wash retains the opaque containing gap. */ }
|
|
60
55
|
|
|
61
56
|
/* Status dot */
|
|
62
57
|
.ui-dot {
|
package/src/styles/button.css
CHANGED
|
@@ -19,8 +19,10 @@
|
|
|
19
19
|
border-radius: var(--radius-sm);
|
|
20
20
|
padding: var(--btn-pad-y) var(--btn-pad-x);
|
|
21
21
|
cursor: pointer;
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
/* Light needs a stronger line here: --border on this fill measures 1.047:1.
|
|
23
|
+
why: docs/specification.md#elevation */
|
|
24
|
+
border: 1px solid var(--control-edge);
|
|
25
|
+
background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
24
26
|
color: var(--text);
|
|
25
27
|
white-space: nowrap;
|
|
26
28
|
transition: background var(--dur-fast) var(--ease),
|
|
@@ -32,7 +34,7 @@
|
|
|
32
34
|
|
|
33
35
|
.ui-btn:hover {
|
|
34
36
|
border-color: var(--accent);
|
|
35
|
-
background: color-mix(in srgb, var(--accent) 14%, var(--surface
|
|
37
|
+
background: color-mix(in srgb, var(--accent) 14%, var(--surface)); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
36
38
|
color: var(--strong);
|
|
37
39
|
}
|
|
38
40
|
.ui-btn:active { transform: translateY(1px); }
|
|
@@ -59,7 +61,7 @@
|
|
|
59
61
|
color: var(--text);
|
|
60
62
|
}
|
|
61
63
|
.ui-btn--ghost:hover {
|
|
62
|
-
background: var(--surface
|
|
64
|
+
background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
63
65
|
border-color: transparent;
|
|
64
66
|
color: var(--strong);
|
|
65
67
|
}
|
|
@@ -108,7 +110,7 @@
|
|
|
108
110
|
}
|
|
109
111
|
/* With no box, the ink is read on whatever is behind it, so the ghost takes an ink
|
|
110
112
|
set for the dullest ground: in dark 7.49 / 6.31 / 7.00 / 5.44 on --bg / --surface /
|
|
111
|
-
--surface-2 / --surface-3, in light 5.
|
|
113
|
+
--surface-2 / --surface-3, in light 5.85 / 6.50 / 5.49 / 5.70. The enabled ghost now uses body
|
|
112
114
|
ink, keeping its words readable without changing the disabled pair. #273 cut this ink to rescue two
|
|
113
115
|
dark pairs from under #220's floor; #295 re-picked --muted against the elevation
|
|
114
116
|
ladder and lifted both clear, so it is the margin now rather than the rescue.
|
|
@@ -135,7 +137,7 @@
|
|
|
135
137
|
.ui-btn[aria-busy="true"],
|
|
136
138
|
.ui-btn[aria-busy="true"]:hover,
|
|
137
139
|
.ui-btn[aria-busy="true"]:active {
|
|
138
|
-
background: var(--surface
|
|
140
|
+
background: var(--surface); /* ring-gap: inherit — busy paint retains the button's containing gap. */
|
|
139
141
|
border-color: var(--border);
|
|
140
142
|
color: var(--text);
|
|
141
143
|
filter: none;
|
|
@@ -158,7 +160,7 @@
|
|
|
158
160
|
.ui-btn[aria-busy="true"].ui-btn--danger,
|
|
159
161
|
.ui-btn[aria-busy="true"].ui-btn--danger:hover,
|
|
160
162
|
.ui-btn[aria-busy="true"].ui-btn--danger:active {
|
|
161
|
-
background: var(--surface
|
|
163
|
+
background: var(--surface); /* ring-gap: inherit — busy paint retains the button's containing gap. */
|
|
162
164
|
border-color: var(--border);
|
|
163
165
|
color: var(--text);
|
|
164
166
|
}
|
package/src/styles/callout.css
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
gap: 12px;
|
|
8
8
|
padding: 15px 17px;
|
|
9
9
|
border-radius: var(--radius-md);
|
|
10
|
-
background: var(--surface
|
|
10
|
+
background: var(--surface); --ring-gap: var(--surface);
|
|
11
11
|
font-size: calc(var(--text-sm) + 0.5px);
|
|
12
12
|
line-height: 1.55;
|
|
13
13
|
color: var(--text);
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
.ui-toast--danger { --toast-accent: var(--pink); --toast-action-ink: var(--chip-danger-ink); --toast-glow: var(--glow-pink); --toast-on: var(--danger-contrast); --toast-solid: var(--signal-solid-danger); }
|
|
57
57
|
.ui-toast--warn { --toast-accent: var(--amber); --toast-action-ink: var(--chip-warn-ink); --toast-glow: color-mix(in srgb, var(--amber) 14%, transparent); --toast-on: var(--signal-contrast); --toast-solid: var(--signal-solid-warn); }
|
|
58
58
|
.ui-toast--info { --toast-accent: var(--cyan); --toast-action-ink: var(--chip-info-ink); --toast-glow: var(--glow-cyan); --toast-on: var(--signal-contrast); --toast-solid: var(--signal-solid-info); }
|
|
59
|
-
.ui-toast--neutral { --toast-accent: var(--muted); --toast-action-ink: var(--text); --toast-glow: var(--surface
|
|
59
|
+
.ui-toast--neutral { --toast-accent: var(--muted); --toast-action-ink: var(--text); --toast-glow: var(--surface); --toast-on: var(--signal-solid-ink); --toast-solid: var(--signal-solid-neutral); }
|
|
60
60
|
|
|
61
61
|
.ui-toast__icon { width: 22px; height: 22px; flex: none; display: grid; place-items: center; background: transparent; color: var(--toast-action-ink); }
|
|
62
62
|
.ui-toast__icon svg { width: var(--space-4); height: var(--space-4); stroke: currentColor; fill: none; stroke-width: 2.25; } /* 16px × 2.25 / 24 = 1.5 CSS px. */
|
package/src/styles/card.css
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
background: var(--surface); --ring-gap: var(--surface);
|
|
10
10
|
border: 1px solid var(--border);
|
|
11
11
|
border-radius: var(--radius-xl);
|
|
12
|
-
|
|
12
|
+
/* Was `var(--space-6) 26px`; 26 is off the scale and broke the column's text edge.
|
|
13
|
+
why: docs/specification.md#spacing-and-rhythm */
|
|
14
|
+
padding: var(--space-6);
|
|
13
15
|
position: relative;
|
|
14
16
|
}
|
|
15
17
|
|
|
@@ -22,17 +24,25 @@
|
|
|
22
24
|
(No `.ui-card + .ui-card` margin: it leaks into grid/flex rows and misaligns.) */
|
|
23
25
|
.ui-card-stack { display: flex; flex-direction: column; gap: var(--space-5); }
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
/* A padding modifier moves the vertical rhythm and keeps the text edge, so cards of
|
|
28
|
+
different padding line up in one column. --pad-lg is the centred landing card, never
|
|
29
|
+
stacked with plain ones, and keeps its own inset.
|
|
30
|
+
why: docs/specification.md#spacing-and-rhythm */
|
|
31
|
+
.ui-card--pad-sm { padding: var(--space-5) var(--space-6); }
|
|
26
32
|
.ui-card--pad-lg { padding: var(--space-8) var(--space-10); }
|
|
27
33
|
|
|
28
34
|
/* An accent-tinted card, e.g. a highlighted plan / success surface. The accent edge is
|
|
29
|
-
the card's own hairline re-coloured: an inset ring over it would draw two. #295
|
|
35
|
+
the card's own hairline re-coloured: an inset ring over it would draw two. #295
|
|
36
|
+
The strength is --card-tint, per theme: light mixes down from white, so a tint that
|
|
37
|
+
works in dark sinks a light card below the page. Each variant edges itself in its own
|
|
38
|
+
colour. why: docs/specification.md#elevation */
|
|
30
39
|
.ui-card--accent {
|
|
31
|
-
background: color-mix(in srgb, var(--accent)
|
|
40
|
+
background: color-mix(in srgb, var(--accent) var(--card-tint), var(--surface)); --ring-gap: color-mix(in srgb, var(--accent) var(--card-tint), var(--surface));
|
|
32
41
|
border-color: color-mix(in srgb, var(--accent) 22%, transparent);
|
|
33
42
|
}
|
|
34
43
|
.ui-card--live {
|
|
35
|
-
background: color-mix(in srgb, var(--green)
|
|
44
|
+
background: color-mix(in srgb, var(--green) var(--card-tint), var(--surface)); --ring-gap: color-mix(in srgb, var(--green) var(--card-tint), var(--surface));
|
|
45
|
+
border-color: color-mix(in srgb, var(--green) 22%, transparent);
|
|
36
46
|
}
|
|
37
47
|
|
|
38
48
|
/* Interactive card (link / button semantics) */
|
package/src/styles/code.css
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* ========================================================================== */
|
|
5
5
|
|
|
6
6
|
.ui-snippet {
|
|
7
|
-
background: var(--surface
|
|
7
|
+
background: var(--surface); --ring-gap: var(--surface);
|
|
8
8
|
border-radius: var(--radius-md);
|
|
9
9
|
overflow: hidden;
|
|
10
10
|
}
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
.ui-code {
|
|
72
72
|
font-family: var(--font-mono);
|
|
73
73
|
font-size: 0.9em;
|
|
74
|
-
background: var(--surface
|
|
74
|
+
background: var(--surface); --ring-gap: var(--surface);
|
|
75
75
|
padding: 2px 6px;
|
|
76
76
|
border-radius: var(--radius-xs);
|
|
77
77
|
color: var(--text);
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
background: none;
|
|
179
179
|
}
|
|
180
180
|
.ui-cmdk__item[hidden] { display: none; } /* motion: still — a row the query no longer answers is gone on the next keystroke */
|
|
181
|
-
.ui-cmdk__item.is-active { background: var(--surface
|
|
181
|
+
.ui-cmdk__item.is-active { outline: 1px solid var(--control-edge); outline-offset: -1px; background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
182
182
|
.ui-cmdk__item.is-active .ui-cmdk__label { color: var(--strong); }
|
|
183
183
|
|
|
184
184
|
.ui-cmdk__ic {
|
|
@@ -239,9 +239,9 @@
|
|
|
239
239
|
.ui-cmdk__item.is-danger.is-active .ui-cmdk__ic { color: var(--pink); }
|
|
240
240
|
|
|
241
241
|
/* A disabled row is painted, never faded. It takes --disabled-ink-bare, the ink
|
|
242
|
-
for a control with no box of its own
|
|
243
|
-
|
|
244
|
-
|
|
242
|
+
for a control with no box of its own. Disabled rows keep the panel's
|
|
243
|
+
surface and their labels remain readable on that ground without
|
|
244
|
+
adding a grey box behind the text.
|
|
245
245
|
why: docs/specification.md#text-ink */
|
|
246
246
|
.ui-cmdk__item.is-disabled { cursor: default; /* muted-ink: state — unavailable control */ color: var(--disabled-ink-bare); }
|
|
247
247
|
.ui-cmdk__item.is-disabled .ui-cmdk__label,
|
|
@@ -256,9 +256,9 @@
|
|
|
256
256
|
padding: 2px 5px;
|
|
257
257
|
border: 1px solid var(--border);
|
|
258
258
|
border-radius: var(--radius-xs);
|
|
259
|
-
/*
|
|
260
|
-
|
|
261
|
-
background: var(--surface
|
|
259
|
+
/* Key caps use an edge on the card surface, keeping the shortcut readable.
|
|
260
|
+
why: docs/specification.md#elevation */
|
|
261
|
+
background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */
|
|
262
262
|
font-family: var(--font-sans);
|
|
263
263
|
font-size: var(--text-xs);
|
|
264
264
|
line-height: 1.5;
|
|
@@ -304,7 +304,7 @@
|
|
|
304
304
|
background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */
|
|
305
305
|
border: 1px solid var(--border);
|
|
306
306
|
}
|
|
307
|
-
.ui-cmdk--roomy .ui-cmdk__item.is-active .ui-cmdk__ic { background: var(--surface
|
|
307
|
+
.ui-cmdk--roomy .ui-cmdk__item.is-active .ui-cmdk__ic { background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
308
308
|
|
|
309
309
|
/* -- Narrow --------------------------------------------------------------- */
|
|
310
310
|
/* At the kit's narrowest step the palette is the page: full width, off the top
|
package/src/styles/drawer.css
CHANGED
|
@@ -127,16 +127,13 @@
|
|
|
127
127
|
.ui-drawer--top.ui-drawer--lg, .ui-drawer--bottom.ui-drawer--lg { --drawer-h: 72vh; }
|
|
128
128
|
|
|
129
129
|
/* -- Slots ----------------------------------------------------------------- */
|
|
130
|
-
/* The header
|
|
131
|
-
long record scrolling, and those two lines are what say where the scrolling body
|
|
132
|
-
ends: the one place inside the panel a line still earns.
|
|
133
|
-
why: docs/specification.md#the-drawer */
|
|
130
|
+
/* The header marks the scroll boundary; actions share the panel surface. */
|
|
134
131
|
.ui-drawer__header {
|
|
135
132
|
display: flex;
|
|
136
133
|
align-items: center;
|
|
137
134
|
justify-content: space-between;
|
|
138
|
-
gap:
|
|
139
|
-
padding:
|
|
135
|
+
gap: var(--space-3);
|
|
136
|
+
padding: var(--space-4) var(--space-5);
|
|
140
137
|
border-bottom: 1px solid var(--border);
|
|
141
138
|
flex: none;
|
|
142
139
|
}
|
|
@@ -188,10 +185,8 @@
|
|
|
188
185
|
display: flex;
|
|
189
186
|
align-items: center;
|
|
190
187
|
justify-content: flex-end;
|
|
191
|
-
gap:
|
|
192
|
-
padding:
|
|
193
|
-
border-top: 1px solid var(--border);
|
|
194
|
-
background: var(--surface-2); --ring-gap: var(--surface-2);
|
|
188
|
+
gap: var(--space-3);
|
|
189
|
+
padding: var(--space-4) var(--space-5);
|
|
195
190
|
flex: none;
|
|
196
191
|
}
|
|
197
192
|
|
package/src/styles/dropdown.css
CHANGED
|
@@ -151,9 +151,9 @@
|
|
|
151
151
|
color: var(--text);
|
|
152
152
|
transition: background var(--dur-fast) var(--ease);
|
|
153
153
|
}
|
|
154
|
-
/*
|
|
155
|
-
.ui-dropdown__item:hover { background: var(--surface
|
|
156
|
-
.ui-dropdown__item:focus-visible { outline: 2px solid transparent; background: var(--surface
|
|
154
|
+
/* Rows keep a reading surface; hover adds an edge. why: docs/specification.md#elevation */
|
|
155
|
+
.ui-dropdown__item:hover { outline: 1px solid var(--control-edge); outline-offset: -1px; background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
156
|
+
.ui-dropdown__item:focus-visible { outline: 2px solid transparent; background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ box-shadow: var(--ring); }
|
|
157
157
|
.ui-dropdown__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
158
158
|
.ui-dropdown__label { font-family: var(--font-sans); font-size: calc(var(--text-sm) - 0.5px); color: var(--strong); font-weight: 600; letter-spacing: 0.01em; }
|
|
159
159
|
.ui-dropdown__desc { font-size: var(--text-xs); color: var(--text); line-height: 1.35; }
|
|
@@ -180,14 +180,14 @@
|
|
|
180
180
|
flex: none;
|
|
181
181
|
color: var(--text);
|
|
182
182
|
/* A chip is the top step. why: docs/specification.md#elevation */
|
|
183
|
-
background: var(--surface
|
|
183
|
+
background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */
|
|
184
184
|
}
|
|
185
185
|
.ui-dropdown__badge.is-live { color: var(--chip-success-ink); background: var(--chip-success-fill); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
186
186
|
/* The accent counter keeps the badge's flat surface and changes only the ink — the shape
|
|
187
|
-
src/styles/nav.css:
|
|
187
|
+
src/styles/nav.css:158 `.ui-nav__item.is-active .ui-nav__badge.is-accent` already holds.
|
|
188
188
|
The accent wash goes on a base surface, never a raised one, and #295 made this panel a
|
|
189
189
|
raised one. why: docs/specification.md#elevation */
|
|
190
|
-
.ui-dropdown__badge.is-accent { color: var(--accent); background: var(--surface
|
|
190
|
+
.ui-dropdown__badge.is-accent { color: var(--accent); background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
191
191
|
|
|
192
192
|
/* Disabled + danger rows */
|
|
193
193
|
.ui-dropdown__item.is-disabled { /* muted-ink: state — unavailable control */ color: var(--disabled-ink); cursor: not-allowed; pointer-events: none; }
|
|
@@ -257,9 +257,9 @@
|
|
|
257
257
|
font: inherit;
|
|
258
258
|
font-size: calc(var(--text-sm) - 0.5px);
|
|
259
259
|
color: var(--strong);
|
|
260
|
-
/*
|
|
261
|
-
background: var(--
|
|
262
|
-
border: 1px solid var(--
|
|
260
|
+
/* The ground and line .ui-input takes. why: docs/specification.md#elevation */
|
|
261
|
+
background: var(--field-bg); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
262
|
+
border: 1px solid var(--field-edge);
|
|
263
263
|
border-radius: var(--radius-sm);
|
|
264
264
|
padding: 8px 12px 8px 34px;
|
|
265
265
|
/* The height Chromium paints (38.25px), stated so the target-size gate, which
|
|
@@ -267,14 +267,12 @@
|
|
|
267
267
|
min-height: 38px;
|
|
268
268
|
transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
|
|
269
269
|
}
|
|
270
|
-
/*
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
why: docs/specification.md#elevation */
|
|
274
|
-
:root[data-theme="light"] .ui-dropdown__search-input { background: var(--bg); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
270
|
+
/* The light-only `background: var(--bg)` override this field used to carry is gone:
|
|
271
|
+
--field-bg says the same thing for every field. Gated by
|
|
272
|
+
stories/dropdown-field-ground.test.js. why: docs/specification.md#elevation */
|
|
275
273
|
|
|
276
274
|
.ui-dropdown__search-input::placeholder { /* muted-ink: placeholder — empty search field */ color: var(--muted); }
|
|
277
|
-
.ui-dropdown__search-input:hover { border-color: var(--
|
|
275
|
+
.ui-dropdown__search-input:hover { border-color: var(--field-edge-hover); }
|
|
278
276
|
.ui-dropdown__search-input:focus-visible { outline: 2px solid transparent; border-color: var(--accent); box-shadow: var(--ring); }
|
|
279
277
|
|
|
280
278
|
.ui-dropdown__list { max-height: 300px; overflow-y: auto; }
|
|
@@ -284,7 +282,7 @@
|
|
|
284
282
|
|
|
285
283
|
/* The row Enter would pick. Focus stays in the field, which carries the ring,
|
|
286
284
|
so this row takes the hover fill and a bar rather than a second ring. */
|
|
287
|
-
.ui-dropdown__item.is-active { background: var(--surface
|
|
285
|
+
.ui-dropdown__item.is-active { background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ box-shadow: inset 2px 0 0 var(--accent); }
|
|
288
286
|
|
|
289
287
|
/* No match — a nudge and no action, per Guidelines / Microcopy. Empty while
|
|
290
288
|
anything matches, so it takes no room. */
|
package/src/styles/feedback.css
CHANGED
|
@@ -76,16 +76,16 @@
|
|
|
76
76
|
.ui-fbc__head { display: flex; align-items: center; gap: 12px; padding: 17px 20px 0; }
|
|
77
77
|
.ui-fbc__chip { display: inline-flex; align-items: center; gap: 8px; color: var(--accent); font-size: var(--text-sm); font-weight: var(--weight-semibold); letter-spacing: .01em; white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
78
78
|
.ui-fbc__chip svg { width: 14px; height: 14px; flex: none; opacity: .85; stroke-width: 2.7; }
|
|
79
|
-
.ui-fbc__x { margin-left: auto; background: var(--surface
|
|
79
|
+
.ui-fbc__x { margin-left: auto; background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ /* muted-ink: glyph — dismiss icon */ color: var(--dim); border: 0; width: 28px; height: 28px; border-radius: 8px; cursor: pointer; display: grid; place-items: center; flex: none; font: inherit; }
|
|
80
80
|
.ui-fbc__x:hover { color: var(--strong); }
|
|
81
81
|
.ui-fbc__x svg { width: 14px; height: 14px; stroke-width: 2.7; }
|
|
82
|
-
.ui-fbc__quote { margin: 14px 20px 0; background: var(--surface
|
|
82
|
+
.ui-fbc__quote { margin: 14px 20px 0; background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ border-radius: 12px; padding: 12px 15px; display: flex; gap: 11px; }
|
|
83
83
|
.ui-fbc__qm { color: var(--accent); font-size: var(--text-xl); font-weight: var(--weight-bold); line-height: .9; flex: none; opacity: .55; }
|
|
84
84
|
.ui-fbc__quote q { quotes: none; color: var(--text); font-style: italic; font-size: calc(var(--text-sm) + 0.5px); line-height: 1.55; }
|
|
85
85
|
.ui-fbc__body { padding: 14px 20px 0; }
|
|
86
86
|
.ui-fbcomposer textarea {
|
|
87
87
|
width: 100%; min-height: 96px; resize: vertical; font-family: var(--font-sans); font-size: var(--text-base); line-height: 1.55;
|
|
88
|
-
color: var(--strong); background: var(--surface
|
|
88
|
+
color: var(--strong); background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ border: 1px solid var(--field-edge); border-radius: 12px; padding: 13px 15px; transition: box-shadow var(--dur-fast) var(--ease);
|
|
89
89
|
}
|
|
90
90
|
.ui-fbcomposer textarea::placeholder { /* muted-ink: placeholder — empty feedback field */ color: var(--muted); }
|
|
91
91
|
.ui-fbcomposer textarea:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
|
|
94
94
|
.ui-fbbtn { font-family: var(--font-sans); font-size: calc(var(--text-sm) + 0.5px); font-weight: var(--weight-semibold); border-radius: 10px; padding: 9px 17px; cursor: pointer; border: 0; transition: filter var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
|
|
95
95
|
.ui-fbbtn.ghost { background: transparent; color: var(--text); }
|
|
96
|
-
.ui-fbbtn.ghost:hover { color: var(--strong); background: var(--surface
|
|
96
|
+
.ui-fbbtn.ghost:hover { color: var(--strong); background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
97
97
|
.ui-fbbtn.primary { background: var(--accent-strong); color: var(--accent-contrast); display: inline-flex; align-items: center; gap: 9px; }
|
|
98
98
|
.ui-fbbtn.primary:hover { filter: brightness(1.08); }
|
|
99
99
|
/* Same flat pair as .ui-btn:disabled, for the same reason (#220). */
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
.ui-fbc__done { padding: 30px 26px 24px; text-align: center; background: radial-gradient(112% 60% at 50% 0%, var(--glow-green), transparent 62%); /* ring-gap: inherit — translucent wash retains the opaque containing gap. */ }
|
|
112
112
|
.ui-fbc__ck { width: 88px; height: 88px; margin: 0 auto 13px; display: grid; place-items: center; }
|
|
113
113
|
.ui-fbck { width: 88px; height: 88px; overflow: visible; display: block; transform-origin: center; animation: uiFbCkSpring 1s cubic-bezier(.22,1,.3,1) both; } /* motion: choreographed — the frame the mark and the comet are timed against */
|
|
114
|
-
.ui-fbck-t { fill: none; stroke: var(--surface
|
|
114
|
+
.ui-fbck-t { fill: none; stroke: var(--surface); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; }
|
|
115
115
|
.ui-fbck-m { fill: none; stroke: var(--green); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 118; stroke-dashoffset: 118; animation: uiFbCkDraw .6s cubic-bezier(.5,0,.3,1) .1s forwards; /* motion: choreographed — the mark draws while the spring is still settling */ }
|
|
116
116
|
.ui-fbck-s { fill: none; stroke: var(--sheen); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 15 400; stroke-dashoffset: 133; filter: drop-shadow(0 0 8px var(--green)) drop-shadow(0 0 15px var(--green)); opacity: 0; animation: uiFbCkComet .6s cubic-bezier(.5,0,.3,1) .1s forwards; /* motion: choreographed — the comet rides the mark, so it shares its duration and delay exactly */ }
|
|
117
117
|
.ui-fbc__done h4 { color: var(--strong); font-size: calc(var(--text-lg) + 1px); font-weight: var(--weight-semibold); letter-spacing: -.01em; margin-bottom: 7px; }
|
package/src/styles/input.css
CHANGED
|
@@ -23,8 +23,10 @@
|
|
|
23
23
|
font-family: var(--font-sans);
|
|
24
24
|
font-size: var(--text-base);
|
|
25
25
|
color: var(--strong);
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
/* Fields use the card surface and an edge in both themes.
|
|
27
|
+
why: docs/specification.md#elevation */
|
|
28
|
+
background: var(--field-bg); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
29
|
+
border: 1px solid var(--field-edge);
|
|
28
30
|
border-radius: var(--radius-md);
|
|
29
31
|
padding: 12px 15px;
|
|
30
32
|
width: 100%;
|
|
@@ -34,7 +36,7 @@
|
|
|
34
36
|
|
|
35
37
|
.ui-input:hover,
|
|
36
38
|
.ui-textarea:hover,
|
|
37
|
-
.ui-select:hover { border-color: var(--
|
|
39
|
+
.ui-select:hover { border-color: var(--field-edge-hover); }
|
|
38
40
|
|
|
39
41
|
.ui-input:focus-visible,
|
|
40
42
|
.ui-textarea:focus-visible,
|
package/src/styles/layout.css
CHANGED
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
.ui-app-page { --ui-app-top: 52px; }
|
|
28
28
|
.ui-app-page .topbar { position: sticky; top: 0; z-index: var(--z-sticky); }
|
|
29
29
|
|
|
30
|
-
/*
|
|
31
|
-
|
|
30
|
+
/* The rail uses the card surface so its labels stay on a reading ground.
|
|
31
|
+
Its border separates navigation from the page in both themes.
|
|
32
32
|
overflow-y, because the box is pinned at the viewport's height for the whole
|
|
33
33
|
scroll of .ui-app — without it a row past that height paints below the fold
|
|
34
34
|
and no amount of document scrolling brings it back. The rail's own padding is
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
gap: var(--space-5);
|
|
40
40
|
padding: var(--space-5) var(--space-4);
|
|
41
41
|
border-right: var(--ui-rail-rule) solid var(--border);
|
|
42
|
-
background: var(--surface
|
|
42
|
+
background: var(--surface); --ring-gap: var(--surface);
|
|
43
43
|
position: sticky;
|
|
44
44
|
top: var(--ui-app-top, 0px);
|
|
45
45
|
height: calc(100vh - var(--ui-app-top, 0px));
|
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
.ui-app__rail > .ui-app__head,
|
|
60
60
|
.ui-app__rail > .ui-app__user,
|
|
61
61
|
.ui-app__rail > .ui-app__foot { width: var(--ui-nav-col); flex: none; }
|
|
62
|
-
/*
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
/* Hover keeps the reading surface and uses the edge declared in nav.css.
|
|
63
|
+
The danger row and the current row are left out by name because this
|
|
64
|
+
rule outranks the states nav.css writes for them.
|
|
65
65
|
*/
|
|
66
|
-
.ui-app__rail .ui-nav__item:not(.is-danger):not(.is-active):hover { background: var(--surface
|
|
66
|
+
.ui-app__rail .ui-nav__item:not(.is-danger):not(.is-active):hover { background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
67
67
|
.ui-app__brand {
|
|
68
68
|
display: flex;
|
|
69
69
|
align-items: center;
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
smallest of three weak signals doing the most work, so it grows with the row. */
|
|
110
110
|
/* Re-tuned at #295, which took the light rail down a step with the page. Below 720px
|
|
111
111
|
the glyph is the whole row, so it is held at text grade rather than at 1.4.11's bar —
|
|
112
|
-
stories/apps/shell-states.test.js:
|
|
112
|
+
stories/apps/shell-states.test.js:1377 `a resting glyph is dimmer but still legible`. */
|
|
113
113
|
.ui-app__rail .ui-nav__ic svg { opacity: 0.66; }
|
|
114
114
|
.ui-app__rail .ui-nav__item.is-active .ui-nav__ic svg,
|
|
115
115
|
.ui-app__rail .ui-nav__item.is-current .ui-nav__ic svg { opacity: 1; stroke: currentColor; } /* motion: still — the glyph brightens with its row, whose own highlight already transitions */
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
width: var(--ui-app-av); height: var(--ui-app-av); flex: none;
|
|
154
154
|
margin-inline-start: calc((var(--ui-nav-strip) - var(--ui-app-av)) / 2);
|
|
155
155
|
border-radius: var(--radius-pill);
|
|
156
|
-
background: var(--surface
|
|
156
|
+
background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */
|
|
157
157
|
color: var(--strong);
|
|
158
158
|
display: grid; place-items: center;
|
|
159
159
|
font-size: calc(var(--text-xs) + 1px);
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
font-weight: inherit;
|
|
188
188
|
letter-spacing: normal;
|
|
189
189
|
}
|
|
190
|
-
.ui-app .ui-app__user-trigger:hover { background: var(--surface
|
|
190
|
+
.ui-app .ui-app__user-trigger:hover { background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
191
191
|
.ui-app__user-trigger .ui-app__who { flex: 1 1 auto; text-align: left; }
|
|
192
192
|
/* The panel is portalled onto <body>, so nothing here may hang off .ui-app: by the
|
|
193
193
|
time it is open it is no longer inside the rail that drew it.
|
|
@@ -269,7 +269,7 @@
|
|
|
269
269
|
why: docs/specification.md#elevation */
|
|
270
270
|
:where(.ui-app.is-collapsed) .ui-app__rail .ui-nav__item:is(:hover, :focus-visible) > .ui-nav__label,
|
|
271
271
|
:where(.ui-app.is-collapsed) .ui-app__rail .ui-app__user-trigger:is(:hover, :focus-visible) > .ui-app__who,
|
|
272
|
-
.ui-app__rail .ui-app__fold:is(:hover, :focus-visible) > .ui-nav__label { position: fixed; left: calc(var(--ui-rail-w) + var(--space-2)); z-index: var(--z-dropdown); width: max-content; max-width: 15rem; margin-block: -7px; padding: 6px 10px; border: 1px solid var(--border-strong); box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop); border-radius: var(--radius-xs); background: var(--surface
|
|
272
|
+
.ui-app__rail .ui-app__fold:is(:hover, :focus-visible) > .ui-nav__label { position: fixed; left: calc(var(--ui-rail-w) + var(--space-2)); z-index: var(--z-dropdown); width: max-content; max-width: 15rem; margin-block: -7px; padding: 6px 10px; border: 1px solid var(--border-strong); box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop); border-radius: var(--radius-xs); background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ color: var(--strong); opacity: 1; pointer-events: none; }
|
|
273
273
|
@supports (anchor-name: --a) and (anchor-scope: --a) {
|
|
274
274
|
.ui-app.is-collapsed,
|
|
275
275
|
.ui-app:has(.ui-app__fold) { anchor-scope: --ui-rail; }
|
|
@@ -352,15 +352,7 @@
|
|
|
352
352
|
font-size: var(--text-sm);
|
|
353
353
|
text-align: start;
|
|
354
354
|
color: var(--text);
|
|
355
|
-
/*
|
|
356
|
-
those sit on a card and this one sits on the band, and the band IS --bg, the
|
|
357
|
-
bottom of the ladder — so a sunken fill has nowhere to go but down into its
|
|
358
|
-
own ground. Measured in light, the field was 1.10:1 BELOW the band and its
|
|
359
|
-
key cap 1.04:1 against the field it sits in; they are 1.08 above and 1.14 now.
|
|
360
|
-
Dark trades the other way and is stated rather than hidden: the cap goes
|
|
361
|
-
1.29 -> 1.16, because --surface-3 and --surface are adjacent rungs there.
|
|
362
|
-
Artur chose this over three alternatives on #318; the survey of what seven
|
|
363
|
-
other systems do is docs/reviews/318-search-field.md.
|
|
355
|
+
/* The band search uses the same reading surface as other text controls.
|
|
364
356
|
why: docs/specification.md#elevation */
|
|
365
357
|
background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
366
358
|
border: 1px solid var(--border);
|
|
@@ -467,7 +459,7 @@
|
|
|
467
459
|
.ui-app__rail .ui-nav__item,
|
|
468
460
|
.ui-app__rail .ui-app__user-trigger { min-height: 44px; }
|
|
469
461
|
.ui-app__rail .ui-nav__item:is(:hover, :focus-visible) > .ui-nav__label,
|
|
470
|
-
.ui-app__rail .ui-app__user-trigger:is(:hover, :focus-visible) > .ui-app__who { position: fixed; left: calc(var(--ui-rail-w) + var(--space-2)); z-index: var(--z-dropdown); width: max-content; max-width: 15rem; margin-block: -7px; padding: 6px 10px; border: 1px solid var(--border-strong); box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop); border-radius: var(--radius-xs); background: var(--surface
|
|
462
|
+
.ui-app__rail .ui-app__user-trigger:is(:hover, :focus-visible) > .ui-app__who { position: fixed; left: calc(var(--ui-rail-w) + var(--space-2)); z-index: var(--z-dropdown); width: max-content; max-width: 15rem; margin-block: -7px; padding: 6px 10px; border: 1px solid var(--border-strong); box-shadow: inset 0 0 0 1px var(--elev-edge, var(--border)), var(--elev-drop); border-radius: var(--radius-xs); background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ color: var(--strong); opacity: 1; pointer-events: none; }
|
|
471
463
|
@supports (anchor-name: --a) and (anchor-scope: --a) {
|
|
472
464
|
.ui-app { anchor-scope: --ui-rail; }
|
|
473
465
|
.ui-app__rail { anchor-name: --ui-rail; }
|
package/src/styles/nav.css
CHANGED
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
|
|
70
70
|
}
|
|
71
71
|
.ui-nav .ui-nav__item { color: var(--text); } /* (0,2,0): a host sheet's a:link is (0,1,1) — why: docs/specification.md#the-page-shell */
|
|
72
|
-
.ui-nav__item:hover { background: var(--surface
|
|
72
|
+
.ui-nav__item:hover { outline: 1px solid var(--control-edge); outline-offset: -1px; background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ color: var(--strong); }
|
|
73
73
|
.ui-nav__item.is-active {
|
|
74
|
-
background: var(--surface
|
|
74
|
+
background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
75
75
|
color: var(--strong);
|
|
76
76
|
font-weight: 500;
|
|
77
77
|
}
|
|
@@ -116,15 +116,10 @@
|
|
|
116
116
|
background and pull its label toward the rail behind it (#220). */
|
|
117
117
|
.ui-nav__item.is-disabled { /* muted-ink: state — unavailable control */ color: var(--disabled-ink); cursor: default; pointer-events: none; }
|
|
118
118
|
|
|
119
|
-
/*
|
|
120
|
-
|
|
121
|
-
reader is standing on. There is no surface above --surface-3, so the step is
|
|
122
|
-
mixed: --text is near-white in dark and near-black in light, and both themes
|
|
123
|
-
raise a surface by moving it away from the page. Written after the danger
|
|
124
|
-
rules so it cannot out-rank them — sign out is never the current row, but a
|
|
125
|
-
rule that could take its wash would be one to argue with later. */
|
|
119
|
+
/* Hover adds an edge without changing the current row's reading surface.
|
|
120
|
+
The danger row keeps its own state treatment. */
|
|
126
121
|
.ui-nav__item.is-active:not(.is-danger):hover {
|
|
127
|
-
background:
|
|
122
|
+
background: var(--surface); outline: 1px solid var(--control-edge); outline-offset: -1px; /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
128
123
|
}
|
|
129
124
|
|
|
130
125
|
/* Per-item badge / counter */
|
|
@@ -140,7 +135,7 @@
|
|
|
140
135
|
font-size: var(--text-xs);
|
|
141
136
|
font-weight: 600;
|
|
142
137
|
line-height: 1;
|
|
143
|
-
background: var(--surface
|
|
138
|
+
background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */
|
|
144
139
|
color: var(--text);
|
|
145
140
|
/* The count fades with the words. It is never lost: sidebarNav() spells it
|
|
146
141
|
into the row's aria-label, so "Pending 3" is what a reader hears at either
|
|
@@ -150,17 +145,17 @@
|
|
|
150
145
|
.ui-nav__badge.is-accent { background: var(--glow-purple); /* ring-gap: inherit — translucent wash retains the opaque containing gap. */ color: var(--accent); }
|
|
151
146
|
.ui-nav__badge.is-live { background: var(--chip-success-fill); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ color: var(--chip-success-ink); }
|
|
152
147
|
.ui-nav__badge.is-danger { background: var(--glow-pink); /* ring-gap: inherit — translucent wash retains the opaque containing gap. */ color: var(--pink); }
|
|
153
|
-
.ui-nav__item.is-active .ui-nav__badge.is-neutral { background: var(--surface
|
|
148
|
+
.ui-nav__item.is-active .ui-nav__badge.is-neutral { background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ color: var(--strong); }
|
|
154
149
|
/* Same shape, one row up: on an active row the accent counter takes the row's
|
|
155
150
|
OWN surface instead of laying its wash over it. An active row is already
|
|
156
|
-
painted --surface
|
|
151
|
+
painted --surface, so an opaque counter avoids stacking tinted fills. Every
|
|
157
152
|
figure here is measured against the tokens this kit now ships. The accent on
|
|
158
153
|
that pair falls under WCAG AA in four of the eight theme x accent cells —
|
|
159
154
|
4.08 in dark Nebula, where the flat surface reads 4.92 — and no alpha reaches
|
|
160
155
|
it, the largest that clears being 0.06 in dark Nebula and 0.02 in light
|
|
161
156
|
Emerald. So the accent wash is painted on a base surface, never a raised one.
|
|
162
157
|
See #157 and docs/specification.md#colour-and-contrast. */
|
|
163
|
-
.ui-nav__item.is-active .ui-nav__badge.is-accent { background: var(--surface
|
|
158
|
+
.ui-nav__item.is-active .ui-nav__badge.is-accent { background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ color: var(--accent); }
|
|
164
159
|
|
|
165
160
|
/* Collapsible group */
|
|
166
161
|
.ui-nav__group { display: flex; flex-direction: column; }
|
|
@@ -294,7 +289,7 @@
|
|
|
294
289
|
|
|
295
290
|
/* pill variant */
|
|
296
291
|
.ui-nav--tabs.is-pill .ui-nav__tab { border-radius: var(--radius-pill); padding: 8px 15px; }
|
|
297
|
-
.ui-nav--tabs.is-pill .ui-nav__tab:hover { background: var(--surface
|
|
292
|
+
.ui-nav--tabs.is-pill .ui-nav__tab:hover { background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
298
293
|
.ui-nav--tabs.is-pill .ui-nav__tab.is-active {
|
|
299
294
|
background: var(--glow-purple); /* ring-gap: inherit — translucent wash retains the opaque containing gap. */
|
|
300
295
|
color: var(--accent);
|
|
@@ -304,7 +299,9 @@
|
|
|
304
299
|
.ui-nav__tab .ui-nav__badge { height: 18px; }
|
|
305
300
|
|
|
306
301
|
/* -- Breadcrumbs --------------------------------------------------------- */
|
|
307
|
-
|
|
302
|
+
/* The chip hangs out by its own padding so the first LABEL lands on the column's edge,
|
|
303
|
+
level with the page title under it. */
|
|
304
|
+
.ui-nav__crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; margin-inline-start: -6px; }
|
|
308
305
|
.ui-nav__crumb-item { display: inline-flex; align-items: center; }
|
|
309
306
|
.ui-nav__crumb-item + .ui-nav__crumb-item::before {
|
|
310
307
|
content: "";
|
|
@@ -329,7 +326,7 @@
|
|
|
329
326
|
does above: a linked crumb is an <a>, and a host stylesheet's `a:link` is
|
|
330
327
|
(0,1,1), which outranks a bare (0,1,0) class. */
|
|
331
328
|
.ui-nav .ui-nav__crumb { color: var(--text); }
|
|
332
|
-
a.ui-nav__crumb:hover { color: var(--strong); background: var(--surface
|
|
329
|
+
a.ui-nav__crumb:hover { color: var(--strong); background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
333
330
|
a.ui-nav__crumb:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
|
|
334
331
|
.ui-nav__crumb.is-current { color: var(--strong); font-weight: 500; }
|
|
335
332
|
.ui-nav__crumb .ui-nav__ic svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2.5; }
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
rule about an ENABLED control out of the disabled-rule sweep in
|
|
70
70
|
stories/guidelines/accessibility-floor.test.js, which reads selector text. */
|
|
71
71
|
.ui-pager__page.is-current:not([disabled]) {
|
|
72
|
-
background: var(--surface
|
|
72
|
+
background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */
|
|
73
73
|
border-color: var(--border);
|
|
74
74
|
color: var(--strong);
|
|
75
75
|
font-weight: var(--weight-semibold);
|
package/src/styles/segmented.css
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/* ============================================================================
|
|
2
2
|
* Segmented control — .ui-seg (the deck's pill switch: theme, Deck/Text, plan)
|
|
3
|
-
* The selected button
|
|
3
|
+
* The selected button keeps the reading surface and gains an accent edge.
|
|
4
4
|
* ========================================================================== */
|
|
5
5
|
|
|
6
6
|
.ui-seg {
|
|
7
7
|
display: inline-flex;
|
|
8
|
-
|
|
8
|
+
/* `inline-flex` sizes the track to its pills, but a flex or grid parent stretches a
|
|
9
|
+
child whatever its display says — and .ui-app__body is a flex column. The control
|
|
10
|
+
states its own alignment; --block and --underline ask for the width back. */
|
|
11
|
+
align-self: start;
|
|
12
|
+
background: var(--surface); --ring-gap: var(--surface);
|
|
9
13
|
border-radius: var(--radius-2xl);
|
|
10
14
|
padding: 3px;
|
|
11
15
|
gap: 2px;
|
|
@@ -30,11 +34,12 @@
|
|
|
30
34
|
.ui-seg button[aria-pressed="true"],
|
|
31
35
|
.ui-seg button[aria-selected="true"] {
|
|
32
36
|
color: var(--strong);
|
|
33
|
-
background: var(--
|
|
37
|
+
background: var(--surface); /* ring-gap: inherit — the button ring meets its containing track. */
|
|
38
|
+
outline: 1px solid var(--accent);
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
.ui-seg--sm button { padding: 5px 13px; font-size: calc(var(--text-xs) + 1px); }
|
|
37
|
-
.ui-seg--block { display: flex; }
|
|
42
|
+
.ui-seg--block { display: flex; align-self: stretch; }
|
|
38
43
|
.ui-seg--block button { flex: 1; }
|
|
39
44
|
|
|
40
45
|
/* Accent picker — round colour swatches, active gets a ring */
|
|
@@ -56,7 +61,7 @@
|
|
|
56
61
|
}
|
|
57
62
|
.ui-accent-picker button:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
|
|
58
63
|
|
|
59
|
-
.ui-seg--underline { background: transparent; --ring-gap: inherit; border-radius: 0; border-bottom: 1px solid var(--border); padding: var(--space-1); overflow: auto; max-width: 100%; }
|
|
64
|
+
.ui-seg--underline { align-self: stretch; background: transparent; --ring-gap: inherit; border-radius: 0; border-bottom: 1px solid var(--border); padding: var(--space-1); overflow: auto; max-width: 100%; }
|
|
60
65
|
.ui-seg--underline button { border-radius: var(--radius-xs); border-bottom: 2px solid transparent; padding: var(--space-3); white-space: nowrap; }
|
|
61
66
|
.ui-seg--underline button.is-active,
|
|
62
67
|
.ui-seg--underline button[aria-pressed="true"] { background: transparent; border-bottom-color: var(--accent); }
|
package/src/styles/table.css
CHANGED
|
@@ -65,10 +65,11 @@
|
|
|
65
65
|
.ui-table--zebra td { border-bottom: 0; }
|
|
66
66
|
.ui-table--zebra tbody tr:nth-child(even) td { background: var(--surface-2); --ring-gap: var(--surface-2); }
|
|
67
67
|
/* The stripe stays full-bleed (the #71 inset above is hover only), but it only reads right
|
|
68
|
-
* if the end cells are inset from the
|
|
68
|
+
* if the end cells are inset from the row's own edge, and `.ui-table td` sets
|
|
69
69
|
* `padding-left: 0`. Only `--dense` supplied that inset, so `--zebra` without `--dense` —
|
|
70
|
-
* `DataTable`'s composition — sat its checkboxes at x=0 of the
|
|
71
|
-
* inset together, or the columns stop lining up.
|
|
70
|
+
* `DataTable`'s composition — sat its checkboxes at x=0 of the row. Head and body are
|
|
71
|
+
* inset together, or the columns stop lining up. Held by src/styles/table.test.js, and
|
|
72
|
+
* kept off the card's text edge by the bleed rule at the end of this file. */
|
|
72
73
|
.ui-table--zebra th:first-child,
|
|
73
74
|
.ui-table--zebra td:first-child { padding-left: var(--space-3); }
|
|
74
75
|
.ui-table--zebra th:last-child,
|
|
@@ -76,6 +77,19 @@
|
|
|
76
77
|
.ui-table--zebra.ui-table--hover tbody tr:hover td,
|
|
77
78
|
.ui-table--zebra tbody tr:hover td { --ring-gap: inherit; background: color-mix(in srgb, var(--accent) 8%, transparent); /* ring-gap: inherit — translucent wash retains the opaque containing gap. */ }
|
|
78
79
|
|
|
80
|
+
/* A link in a cell is a value that happens to open something: the row's ink, underlined
|
|
81
|
+
on hover — what .ui-identity below has always done. Without it, base.css's bare
|
|
82
|
+
`a { color: var(--accent) }` reached the ledger's IDs.
|
|
83
|
+
why: guidelines/density-and-accents.md#give-accents-a-job */
|
|
84
|
+
.ui-table :where(td, th) a:not(.ui-btn):not(.ui-identity) {
|
|
85
|
+
color: inherit;
|
|
86
|
+
text-decoration: none;
|
|
87
|
+
}
|
|
88
|
+
.ui-table :where(td, th) a:not(.ui-btn):not(.ui-identity):hover {
|
|
89
|
+
color: var(--strong);
|
|
90
|
+
text-decoration: underline;
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
.ui-table__num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
80
94
|
.ui-table th.ui-table__num { text-align: right; }
|
|
81
95
|
.ui-table__num--strong { color: var(--strong); font-weight: var(--weight-semibold); }
|
|
@@ -93,6 +107,15 @@
|
|
|
93
107
|
background: var(--table-bg); --ring-gap: var(--table-bg);
|
|
94
108
|
}
|
|
95
109
|
.ui-table tbody tr:hover { outline: 1px solid var(--border-strong); outline-offset: -1px; }
|
|
110
|
+
|
|
111
|
+
/* The end-cell inset above gives a row's highlight room; the bleed is what stops the grid
|
|
112
|
+
paying for it. The table hangs out by the same --space-3, into the card's 20-24px
|
|
113
|
+
padding and never past it, so the columns start on the card's own text edge and the
|
|
114
|
+
scroll region stays empty at rest. why: docs/specification.md#spacing-and-rhythm */
|
|
115
|
+
.ui-card > :where(.ui-table--dense, .ui-table--zebra) {
|
|
116
|
+
width: calc(100% + 2 * var(--space-3));
|
|
117
|
+
margin-inline: calc(-1 * var(--space-3));
|
|
118
|
+
}
|
|
96
119
|
.ui-table td.ui-table__num { text-align: right; }
|
|
97
120
|
.ui-table--compact td { padding: var(--space-1) var(--space-3); font-size: var(--text-sm); line-height: var(--leading-snug); height: 33px; }
|
|
98
121
|
.ui-table--compact th { padding: var(--space-2) var(--space-3); }
|
package/src/styles/tooltip.css
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
/* One number for the mark-to-readout distance, read by both placements here
|
|
15
15
|
and by the wiring's flip test, so above and below cannot drift apart. */
|
|
16
16
|
--ui-tip-gap: 8px;
|
|
17
|
-
--ui-tip-bg: var(--
|
|
17
|
+
--ui-tip-bg: var(--bg-elevated);
|
|
18
18
|
position: absolute;
|
|
19
19
|
top: var(--ui-tip-y, 0px);
|
|
20
20
|
left: var(--ui-tip-x, 50%);
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
visibility var(--dur-fast) linear;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
/*
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
/* The readout uses the floating panel surface in both themes. Its edge
|
|
51
|
+
and shadow separate it from the card underneath.
|
|
52
|
+
why: docs/specification.md#elevation */
|
|
53
53
|
|
|
54
54
|
/* Below the mark: the wiring's flip when above would be clipped, or the
|
|
55
55
|
author's own choice. */
|
package/src/styles/topbar.css
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
display: none;
|
|
49
49
|
align-items: center;
|
|
50
50
|
gap: 2px;
|
|
51
|
-
background: var(--surface
|
|
51
|
+
background: var(--surface); --ring-gap: var(--surface);
|
|
52
52
|
border: 1px solid var(--border);
|
|
53
53
|
border-radius: 24px;
|
|
54
54
|
padding: 3px;
|
|
@@ -179,10 +179,10 @@
|
|
|
179
179
|
font: inherit;
|
|
180
180
|
transition: background var(--dur-fast) var(--ease);
|
|
181
181
|
}
|
|
182
|
-
/*
|
|
182
|
+
/* Menu rows use the reading surface and an edge on hover — see
|
|
183
183
|
src/styles/dropdown.css:155 `.ui-dropdown__item:hover`.
|
|
184
184
|
why: docs/specification.md#elevation */
|
|
185
|
-
.vopt:hover { background: var(--surface
|
|
185
|
+
.vopt:hover { outline: 1px solid var(--control-edge); outline-offset: -1px; background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
186
186
|
.vopt .vname { font-family: var(--font-sans); font-size: calc(var(--text-sm) - 0.5px); color: var(--strong); font-weight: 600; letter-spacing: 0.01em; }
|
|
187
187
|
.vopt .vmeta { font-size: var(--text-xs); color: var(--text); margin-top: 2px; }
|
|
188
188
|
.vopt .vbadge {
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
margin-top: 1px;
|
|
197
197
|
}
|
|
198
198
|
.vbadge.live { color: var(--chip-success-ink); background: var(--chip-success-fill); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
199
|
-
.vbadge.arch { /* muted-ink: state — archived version */ color: var(--muted); background: var(--surface
|
|
199
|
+
.vbadge.arch { /* muted-ink: state — archived version */ color: var(--muted); background: var(--surface); /* ring-gap: inherit — decorative or text-only surface has no nested focus target. */ }
|
|
200
200
|
/* The switcher keeps its glyph and drops its label where the shell folds — the
|
|
201
201
|
same step the rail folds at: docs/specification.md#breakpoints. */
|
|
202
202
|
@media (max-width: 720px) { .vsw__btn .lbl { display: none; } }
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
.amenu .ahead .anm { color: var(--strong); font-size: var(--text-sm); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
259
259
|
.amenu .ahead .aem { color: var(--text); font-size: calc(var(--text-xs) + 0.5px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
260
260
|
.amenu a { display: flex; align-items: center; gap: 11px; padding: 10px 15px; color: var(--text); text-decoration: none; font-family: var(--font-sans); font-size: var(--text-sm); cursor: pointer; }
|
|
261
|
-
.amenu a:hover { background: var(--surface
|
|
261
|
+
.amenu a:hover { outline: 1px solid var(--control-edge); outline-offset: -1px; background: var(--surface); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */ }
|
|
262
262
|
.amenu a.cur { color: var(--accent); }
|
|
263
263
|
.amenu a svg { width: 19px; height: 19px; flex: none; stroke: currentColor; fill: none; stroke-width: 2; opacity: 0.85; }
|
|
264
264
|
.amenu .asep { height: 1px; background: var(--border); margin: 5px 0; }
|
package/src/tokens/tokens.css
CHANGED
|
@@ -139,10 +139,10 @@
|
|
|
139
139
|
line and nothing else in the kit does. why: docs/specification.md#elevation */
|
|
140
140
|
--bg: #0e0d14;
|
|
141
141
|
--table-bg: var(--bg);
|
|
142
|
-
--surface-2: #161520; /*
|
|
142
|
+
--surface-2: #161520; /* non-text sunken marks and tracks */
|
|
143
143
|
--surface: #211e2d; /* the card */
|
|
144
144
|
--bg-elevated: #2a2639; /* FLOATING — menus, panels, drawer, modal, toasts */
|
|
145
|
-
--surface-3: #2d293c; /*
|
|
145
|
+
--surface-3: #2d293c; /* non-text quiet fills */
|
|
146
146
|
--seg-active-bg: #383350; /* raised pill — clearly above the inset track in dark */
|
|
147
147
|
/* The raised handle on a control track (switch knob). White in both themes and under
|
|
148
148
|
every accent: it reads on the plain track AND on the accent fill of an on control. */
|
|
@@ -150,6 +150,16 @@
|
|
|
150
150
|
--border: #332f45;
|
|
151
151
|
--border-strong: #453f5c;
|
|
152
152
|
|
|
153
|
+
/* Fields use the card surface and an edge in both themes. why: docs/specification.md#elevation */
|
|
154
|
+
--field-bg: var(--surface);
|
|
155
|
+
--field-edge: var(--border);
|
|
156
|
+
--field-edge-hover: var(--border-strong);
|
|
157
|
+
--control-edge: var(--border);
|
|
158
|
+
|
|
159
|
+
/* How much of its own colour a tinted card mixes in. Dark mixes upward off a mid-grey
|
|
160
|
+
card, so it can afford this much. why: docs/specification.md#elevation */
|
|
161
|
+
--card-tint: 9%;
|
|
162
|
+
|
|
153
163
|
--text: #e9e7f0;
|
|
154
164
|
--strong: #ffffff;
|
|
155
165
|
--dim: #c6c2d6;
|
|
@@ -164,7 +174,7 @@
|
|
|
164
174
|
ink read on the surface beside it. Held by guidelines/accessibility-floor.test.js.
|
|
165
175
|
why: docs/specification.md#colour-and-contrast */
|
|
166
176
|
--disabled-ink: var(--muted);
|
|
167
|
-
--disabled-surface: var(--surface
|
|
177
|
+
--disabled-surface: var(--surface);
|
|
168
178
|
--disabled-border: var(--border);
|
|
169
179
|
/* The ink of a disabled control that paints no box of its own — a ghost button. With
|
|
170
180
|
no surface beside it, it is read on whatever is behind it, so it is set to clear the
|
|
@@ -281,29 +291,47 @@
|
|
|
281
291
|
--pink: #a92d59;
|
|
282
292
|
--amber: #b5730a;
|
|
283
293
|
|
|
284
|
-
/* The same ladder, run the only way light can run it: nothing is brighter than
|
|
285
|
-
white
|
|
294
|
+
/* The same ladder, run the only way light can run it: nothing is brighter than
|
|
295
|
+
white, so light moves DOWN from it. #307 ran it downwards from the CARD, which
|
|
296
|
+
put the page at #eef0f5 and left the card at #f8f9fc — a grey canvas under a
|
|
297
|
+
surface only 1.08:1 above it, so the grey was what the screen read as and the
|
|
298
|
+
card never arrived. The card takes the white instead, and the page is the
|
|
299
|
+
lightest ground that still leaves it a step: 1.11:1, on a page lighter and less
|
|
300
|
+
blue than the one it replaces. Light spends its white on the surface you read
|
|
301
|
+
ON, and separates the panel that floats over it by role — its two-step edge and
|
|
302
|
+
its drop — rather than by a rung it has nothing left to pay for. See issue #448.
|
|
286
303
|
why: docs/specification.md#elevation */
|
|
287
|
-
--bg: #
|
|
304
|
+
--bg: #f2f3f6;
|
|
288
305
|
--table-bg: #ffffff;
|
|
289
|
-
--surface-2: #
|
|
290
|
-
--surface: #
|
|
306
|
+
--surface-2: #e9ecf3; /* non-text sunken marks and tracks */
|
|
307
|
+
--surface: #ffffff; /* the card */
|
|
291
308
|
--bg-elevated: #ffffff; /* FLOATING — menus, panels, drawer, modal, toasts */
|
|
292
|
-
--surface-3: #
|
|
309
|
+
--surface-3: #eef0f5; /* non-text quiet fills */
|
|
293
310
|
--seg-active-bg: #ffffff; /* white pill raised above the grey track in light */
|
|
294
311
|
--control-knob: #ffffff;
|
|
295
312
|
--border: #e4e7ee;
|
|
296
313
|
--border-strong: #cdd2dc;
|
|
297
314
|
|
|
315
|
+
/* Light draws a field with its EDGE, because since #448 it has no well left to draw it
|
|
316
|
+
with: a card and a panel are both white, the sunken step falls two rungs under either,
|
|
317
|
+
and --border on it measures 1.047:1. why: docs/specification.md#elevation */
|
|
318
|
+
--field-bg: var(--surface);
|
|
319
|
+
--field-edge: var(--border-strong);
|
|
320
|
+
--field-edge-hover: var(--muted);
|
|
321
|
+
--control-edge: var(--border-strong);
|
|
322
|
+
|
|
323
|
+
/* Light mixes DOWN from white, so tint costs lightness: 5% is the most a card can spend
|
|
324
|
+
and stay above the page. why: docs/specification.md#elevation */
|
|
325
|
+
--card-tint: 5%;
|
|
326
|
+
|
|
298
327
|
--text: #1a1e27;
|
|
299
328
|
--strong: #0c0e13;
|
|
300
329
|
--dim: #3a404b;
|
|
301
330
|
--muted: #5c6270;
|
|
302
331
|
|
|
303
|
-
/*
|
|
304
|
-
same reason dark moves it away from the card: a control that is off should sink. */
|
|
332
|
+
/* Disabled text stays on the card surface; its ink marks the unavailable state. */
|
|
305
333
|
--disabled-ink: var(--muted);
|
|
306
|
-
--disabled-surface: var(--surface
|
|
334
|
+
--disabled-surface: var(--surface);
|
|
307
335
|
--disabled-border: var(--border);
|
|
308
336
|
--disabled-ink-bare: #585e6c;
|
|
309
337
|
|
|
@@ -361,8 +389,8 @@
|
|
|
361
389
|
--shadow-ink: #1e1e32;
|
|
362
390
|
--sheen: #ffffff;
|
|
363
391
|
|
|
364
|
-
/* 18% / 10% against dark's 62% / 50%. Light's ink is #1e1e32 on a card
|
|
365
|
-
#
|
|
392
|
+
/* 18% / 10% against dark's 62% / 50%. Light's ink is #1e1e32 on a card that is
|
|
393
|
+
now #ffffff, and 18% is what puts the drop core at #d7d7da — 1.44, the strongest
|
|
366
394
|
separation either theme gets. why: docs/specification.md#elevation */
|
|
367
395
|
--elev-drop:
|
|
368
396
|
0 14px 30px -12px color-mix(in srgb, var(--shadow-ink) 18%, transparent),
|