actual-css 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +214 -1
- package/README.md +13 -11
- package/components.json +668 -0
- package/dist/actual.css +166 -37
- package/dist/actual.full.css +1005 -550
- package/dist/actual.full.js +1 -1
- package/dist/actual.full.min.css +1 -1
- package/dist/actual.js +1 -1
- package/dist/actual.min.css +1 -1
- package/docs/design-notes/accessibility-decisions.md +33 -0
- package/docs/design-notes/browser-support.md +82 -25
- package/docs/design-notes/column-layout.md +3 -3
- package/docs/design-notes/css-anchor.md +75 -21
- package/docs/design-notes/enhancement-contract.md +14 -6
- package/docs/design-notes/grid.md +4 -4
- package/docs/design-notes/naming.md +6 -1
- package/docs/design-notes/platform-alignment.md +99 -2
- package/docs/design-notes/popover-manual-poc.md +328 -0
- package/docs/design-notes/surface-reparenting.md +131 -0
- package/docs/design-notes/tooltip-coordinate-space.md +132 -0
- package/docs/design-notes/widget-primitives.md +9 -6
- package/docs/pages/components/accordion.md +41 -2
- package/docs/pages/components/alert.md +80 -30
- package/docs/pages/components/app-navigation.md +6 -0
- package/docs/pages/components/avatar.md +6 -6
- package/docs/pages/components/badge.md +101 -16
- package/docs/pages/components/button.md +16 -8
- package/docs/pages/components/card.md +10 -10
- package/docs/pages/components/dialog.md +16 -6
- package/docs/pages/components/fab.md +4 -3
- package/docs/pages/components/list.md +42 -4
- package/docs/pages/components/navbar.md +17 -1
- package/docs/pages/components/pagination.md +2 -2
- package/docs/pages/components/steps.md +19 -0
- package/docs/pages/components/table.md +3 -2
- package/docs/pages/enhancements/flyout.md +144 -24
- package/docs/pages/enhancements/overview.md +25 -0
- package/docs/pages/enhancements/status-bar.md +20 -0
- package/docs/pages/enhancements/tabs.md +45 -37
- package/docs/pages/enhancements/tooltip.md +40 -2
- package/docs/pages/examples/overview.md +38 -5
- package/docs/pages/forms/choice-cards.md +6 -2
- package/docs/pages/forms/combobox.md +1 -1
- package/docs/pages/forms/floating-field.md +4 -3
- package/docs/pages/forms/joined-controls.md +22 -0
- package/docs/pages/forms/otp.md +2 -1
- package/docs/pages/forms/overview.md +1 -1
- package/docs/pages/forms/states-and-sizes.md +16 -18
- package/docs/pages/forms/sticky-actions.md +2 -2
- package/docs/pages/forms/switch.md +1 -1
- package/docs/pages/foundations/philosophy.md +67 -22
- package/docs/pages/foundations/theming.md +10 -2
- package/docs/pages/foundations/tokens.md +118 -21
- package/docs/pages/foundations/typography.md +35 -14
- package/docs/pages/guides/introduction.md +11 -9
- package/docs/pages/guides/progressive-enhancement.md +136 -49
- package/docs/pages/guides/tailwind.md +3 -2
- package/docs/pages/layout/media.md +1 -1
- package/docs/pages/layout/overview.md +11 -1
- package/docs/pages/layout/scroll-snap.md +3 -3
- package/docs/pages/layout/stack.md +17 -9
- package/docs/pages/patterns/icon-input.md +4 -2
- package/docs/pages/patterns/icon-slot.md +2 -0
- package/docs/pages/patterns/intent-nesting.md +1 -1
- package/docs/pages/utilities/overview.md +23 -2
- package/docs/pages/utilities/sizing-wrapping.md +1 -1
- package/docs/pages/utilities/spacing.md +10 -8
- package/llms.txt +2 -1
- package/package.json +19 -8
- package/{scripts/reserved-classes.json → reserved-classes.json} +4 -6
- package/src/css/components/accordion.css +42 -3
- package/src/css/components/alert.css +25 -13
- package/src/css/components/app-nav.css +18 -8
- package/src/css/components/avatar.css +13 -1
- package/src/css/components/badge.css +78 -12
- package/src/css/components/breadcrumb.css +2 -3
- package/src/css/components/button.css +9 -16
- package/src/css/components/card.css +9 -2
- package/src/css/components/chat.css +1 -0
- package/src/css/components/data-list.css +1 -1
- package/src/css/components/drawer.css +79 -25
- package/src/css/components/fab.css +0 -6
- package/src/css/components/flyout.css +46 -63
- package/src/css/components/index.css +0 -1
- package/src/css/components/indicator.css +21 -0
- package/src/css/components/join.css +7 -0
- package/src/css/components/key.css +10 -0
- package/src/css/components/list.css +40 -4
- package/src/css/components/menu.css +18 -11
- package/src/css/components/modal.css +48 -33
- package/src/css/components/navbar.css +37 -4
- package/src/css/components/pagination.css +1 -0
- package/src/css/components/spinner.css +6 -6
- package/src/css/components/status-bar.css +0 -5
- package/src/css/components/steps.css +45 -59
- package/src/css/components/tab.css +29 -9
- package/src/css/components/table.css +5 -5
- package/src/css/components/tooltip.css +45 -13
- package/src/css/core/base.css +23 -1
- package/src/css/core/intents.css +17 -6
- package/src/css/core/theme.css +27 -0
- package/src/css/core/tokens.css +35 -15
- package/src/css/core/variants.css +64 -15
- package/src/css/forms/choice-card.css +4 -4
- package/src/css/forms/choice.css +6 -3
- package/src/css/forms/control.css +2 -1
- package/src/css/forms/floating-field.css +3 -3
- package/src/css/forms/form.css +4 -3
- package/src/css/forms/input-icon.css +20 -14
- package/src/css/forms/native.css +6 -1
- package/src/css/forms/otp.css +9 -1
- package/src/css/forms/range.css +2 -0
- package/src/css/forms/select.css +29 -9
- package/src/css/forms/switch.css +19 -5
- package/src/css/layout/app-layout.css +1 -1
- package/src/css/layout/grid.css +50 -76
- package/src/css/layout/scroll-snap.css +11 -7
- package/src/css/layout/scroller.css +3 -4
- package/src/css/layout/stack.css +2 -2
- package/src/css/typography/fluid.css +4 -3
- package/src/css/typography/prose.css +6 -5
- package/src/css/utilities/base.css +2 -1
- package/src/css/utilities/extra.css +20 -17
- package/src/js/context-menu.js +27 -26
- package/src/js/dialog.js +2 -1
- package/src/js/dismiss.js +5 -0
- package/src/js/enhance.js +34 -2
- package/src/js/enhancement-loader.js +36 -43
- package/src/js/events.js +0 -3
- package/src/js/filter.js +0 -1
- package/src/js/floating-space.js +42 -0
- package/src/js/flyout.js +9 -44
- package/src/js/focus-group.js +7 -0
- package/src/js/focus.js +6 -0
- package/src/js/menu.js +10 -1
- package/src/js/selectors.js +5 -9
- package/src/js/status.js +44 -7
- package/src/js/surface.js +106 -132
- package/src/js/tab.js +6 -1
- package/src/js/tooltip.js +152 -53
- package/src/js/validation.js +1 -1
- package/src/css/components/surface.css +0 -49
- package/src/js/floating.js +0 -432
|
@@ -62,8 +62,18 @@ dialog.drawer[open] {
|
|
|
62
62
|
transform var(--drawer-motion-duration) var(--ease-enter);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
/*
|
|
66
|
-
|
|
65
|
+
/* A form is the drawer's content wrapper when actions need method="dialog".
|
|
66
|
+
Span the drawer tracks so the form can keep the header at the top, let the
|
|
67
|
+
body absorb the available height, and keep the footer at the bottom. */
|
|
68
|
+
dialog.drawer > form {
|
|
69
|
+
display: grid;
|
|
70
|
+
grid-row: 1 / -1;
|
|
71
|
+
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
72
|
+
gap: var(--space-40);
|
|
73
|
+
min-block-size: 100%;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* The shared backdrop token keeps drawer and modal scrims consistent. */
|
|
67
77
|
dialog.drawer::backdrop {
|
|
68
78
|
background: var(--backdrop-fill);
|
|
69
79
|
opacity: 0;
|
|
@@ -128,33 +138,33 @@ dialog.drawer nav {
|
|
|
128
138
|
}
|
|
129
139
|
|
|
130
140
|
/* Safari before 16.4 does not support :dir(); keep the ancestor-attribute
|
|
131
|
-
path as the
|
|
141
|
+
path as the Degraded-tier fallback. The :dir() rules are dropped on their
|
|
142
|
+
own there, so they need no wrapper. :dir() follows inherited HTML
|
|
143
|
+
directionality and handles nested direction changes; the explicit ltr rules
|
|
144
|
+
neutralize an outer RTL fallback selector. Each specificity group keeps the
|
|
145
|
+
fallback before the :dir() rules. */
|
|
132
146
|
[dir="rtl"] dialog.drawer {
|
|
133
147
|
--drawer-closed-translate: 100%;
|
|
134
148
|
}
|
|
135
149
|
|
|
136
|
-
|
|
150
|
+
dialog.drawer:dir(ltr) {
|
|
137
151
|
--drawer-closed-translate: -100%;
|
|
138
152
|
}
|
|
139
153
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
dialog.drawer:dir(ltr) {
|
|
144
|
-
--drawer-closed-translate: -100%;
|
|
145
|
-
}
|
|
154
|
+
dialog.drawer:dir(rtl) {
|
|
155
|
+
--drawer-closed-translate: 100%;
|
|
156
|
+
}
|
|
146
157
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
158
|
+
[dir="rtl"] dialog.drawer[data-side="end"] {
|
|
159
|
+
--drawer-closed-translate: -100%;
|
|
160
|
+
}
|
|
150
161
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
162
|
+
dialog.drawer[data-side="end"]:dir(ltr) {
|
|
163
|
+
--drawer-closed-translate: 100%;
|
|
164
|
+
}
|
|
154
165
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
166
|
+
dialog.drawer[data-side="end"]:dir(rtl) {
|
|
167
|
+
--drawer-closed-translate: -100%;
|
|
158
168
|
}
|
|
159
169
|
|
|
160
170
|
@media (prefers-reduced-motion: no-preference) {
|
|
@@ -163,15 +173,59 @@ dialog.drawer nav {
|
|
|
163
173
|
}
|
|
164
174
|
}
|
|
165
175
|
|
|
166
|
-
/* The
|
|
167
|
-
|
|
168
|
-
inline room so the title never runs under it. */
|
|
176
|
+
/* The header reserves inline room so the title never runs under the close
|
|
177
|
+
control. */
|
|
169
178
|
dialog.drawer > header,
|
|
170
179
|
dialog.drawer > form > header {
|
|
171
180
|
padding-inline-end: calc(var(--control-size) + var(--space-30));
|
|
172
181
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
|
|
183
|
+
/* Close control, owned here so a drawer-only build does not depend on
|
|
184
|
+
modal.css. Mirrors the modal's .dialog-close placement: absolute at the
|
|
185
|
+
panel's top inline-end, out of the content flow. */
|
|
186
|
+
.drawer-close {
|
|
187
|
+
--drawer-close-icon-size: 1rem;
|
|
188
|
+
|
|
189
|
+
display: inline-grid;
|
|
190
|
+
place-items: center;
|
|
191
|
+
padding: 0;
|
|
192
|
+
border: 0;
|
|
193
|
+
border-radius: var(--radius);
|
|
194
|
+
color: var(--text-muted);
|
|
195
|
+
cursor: pointer;
|
|
196
|
+
|
|
197
|
+
position: absolute;
|
|
198
|
+
z-index: 1;
|
|
199
|
+
inset-block-start: var(--space-20);
|
|
200
|
+
inset-inline-end: var(--space-20);
|
|
201
|
+
|
|
202
|
+
inline-size: var(--control-size);
|
|
203
|
+
block-size: var(--control-size);
|
|
204
|
+
|
|
205
|
+
background: var(--surface-subtle);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.drawer-close::before {
|
|
209
|
+
content: "";
|
|
210
|
+
inline-size: var(--drawer-close-icon-size);
|
|
211
|
+
block-size: var(--drawer-close-icon-size);
|
|
212
|
+
background: currentColor;
|
|
213
|
+
-webkit-mask: var(--icon-close) center / contain no-repeat;
|
|
214
|
+
mask: var(--icon-close) center / contain no-repeat;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@media (hover: hover) {
|
|
218
|
+
.drawer-close:hover {
|
|
219
|
+
box-shadow: inset 0 0 0 999px var(--hover-overlay);
|
|
220
|
+
color: var(--text);
|
|
176
221
|
}
|
|
177
222
|
}
|
|
223
|
+
|
|
224
|
+
.drawer-close:active {
|
|
225
|
+
box-shadow: inset 0 0 0 999px var(--hover-overlay);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.drawer-close:focus-visible {
|
|
229
|
+
outline: 2px solid transparent;
|
|
230
|
+
box-shadow: var(--focus-ring-shadow);
|
|
231
|
+
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Flyout — floating panel for actions and links.
|
|
3
3
|
*
|
|
4
|
-
* JavaScript
|
|
5
|
-
*
|
|
6
|
-
* panel appearance, item styles,
|
|
4
|
+
* JavaScript promotes the panel to the top layer and chooses viewport or
|
|
5
|
+
* document coordinates from its anchor. It also owns state (.is-open), focus,
|
|
6
|
+
* and keyboard behavior. CSS owns the surfaced panel appearance, item styles,
|
|
7
|
+
* and animation.
|
|
7
8
|
*
|
|
8
|
-
* Runtime
|
|
9
|
-
* .is-sheet marks "auto" resolved to bottom-sheet presentation on coarse
|
|
10
|
-
* pointers. Authors opt into mobile behavior with
|
|
11
|
-
* [data-flyout-mobile="sheet|auto|none|anchored"].
|
|
9
|
+
* Runtime marker (managed by surface.js): .is-open marks an open flyout.
|
|
12
10
|
* --surface-anchor-width is set by surface.js while an open flyout is positioned.
|
|
13
11
|
*
|
|
14
12
|
* Public hooks:
|
|
@@ -17,7 +15,7 @@
|
|
|
17
15
|
*
|
|
18
16
|
* Internal:
|
|
19
17
|
* --menu-item-size (derived from --control-size for menu rows)
|
|
20
|
-
* --available-height (measured by
|
|
18
|
+
* --available-height (measured by the positioner)
|
|
21
19
|
* --surface-anchor-width (measured by surface.js)
|
|
22
20
|
*/
|
|
23
21
|
|
|
@@ -44,8 +42,8 @@
|
|
|
44
42
|
--menu-item-size: var(--control-size);
|
|
45
43
|
z-index: var(--z-menu);
|
|
46
44
|
/* No-JS fallback: below the trigger inside the relative .flyout-trigger.
|
|
47
|
-
surface.js
|
|
48
|
-
|
|
45
|
+
surface.js replaces this with the anchor's coupled position/coordinate
|
|
46
|
+
mode; this only covers a flyout revealed without the runtime. */
|
|
49
47
|
position: absolute;
|
|
50
48
|
inset-block-start: calc(100% + var(--space-10));
|
|
51
49
|
inset-inline-start: 0;
|
|
@@ -73,73 +71,63 @@
|
|
|
73
71
|
box-shadow: var(--shadow-popout);
|
|
74
72
|
list-style: none;
|
|
75
73
|
opacity: 1;
|
|
76
|
-
/*
|
|
77
|
-
|
|
78
|
-
below adds its own translate motion. */
|
|
74
|
+
/* Flyouts fade in and out; scaling around the center would detach the
|
|
75
|
+
anchored edge from its trigger on wide panels. */
|
|
79
76
|
transition: opacity var(--duration-fast) ease;
|
|
80
77
|
}
|
|
81
78
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
opacity: 0;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/* Bottom-sheet presentation. surface.js toggles .is-sheet when the flyout is
|
|
93
|
-
opened on coarse pointer / narrow viewports. */
|
|
94
|
-
.flyout.is-sheet {
|
|
95
|
-
--menu-item-size: var(--control-size-lg);
|
|
79
|
+
/* A popover enters the top layer with UA geometry that conflicts with anchored
|
|
80
|
+
positioning. surface.js sets popover="manual" on every surface it manages,
|
|
81
|
+
so this is the transport's own geometry rather than an opt-in. Kept scoped to
|
|
82
|
+
Actual surfaces so bare [popover] elements retain their platform
|
|
83
|
+
presentation. */
|
|
84
|
+
.flyout[popover] {
|
|
96
85
|
position: fixed;
|
|
97
|
-
inset
|
|
98
|
-
|
|
99
|
-
inset-block-end: 0;
|
|
100
|
-
inline-size: auto;
|
|
101
|
-
min-inline-size: 0;
|
|
102
|
-
max-inline-size: none;
|
|
103
|
-
max-block-size: min(calc(var(--viewport-block) * 0.75), 32rem);
|
|
104
|
-
overflow: auto;
|
|
105
|
-
grid-template-columns: 1fr;
|
|
106
|
-
padding: max(var(--space-30), env(safe-area-inset-top)) var(--space-30)
|
|
107
|
-
max(var(--space-30), env(safe-area-inset-bottom));
|
|
108
|
-
border-end-start-radius: 0;
|
|
109
|
-
border-end-end-radius: 0;
|
|
110
|
-
/* Sheet motion is a directional slide from the viewport edge; it replaces
|
|
111
|
-
the base fade-only recipe. */
|
|
112
|
-
transition:
|
|
113
|
-
opacity var(--duration-fast) ease,
|
|
114
|
-
translate var(--duration-fast) ease;
|
|
86
|
+
inset: auto;
|
|
87
|
+
margin: 0;
|
|
115
88
|
}
|
|
116
89
|
|
|
117
|
-
|
|
90
|
+
/* A presentation class may own its *visible* display type, but must not
|
|
91
|
+
override the platform's hidden state. The UA closes a popover with
|
|
92
|
+
display: none, and an author declaration beats the UA origin whatever the
|
|
93
|
+
specificity — so .flyout's own display: grid would leave a closed popover
|
|
94
|
+
painted at its static position. The opacity is the exit target: with nothing
|
|
95
|
+
to animate, the overlay/display allow-discrete transition below would hold a
|
|
96
|
+
fully opaque panel in the top layer and then snap it away. */
|
|
97
|
+
.flyout[popover]:not(:popover-open) {
|
|
118
98
|
display: none;
|
|
119
99
|
opacity: 0;
|
|
120
100
|
}
|
|
121
101
|
|
|
122
|
-
.
|
|
123
|
-
|
|
102
|
+
/* Both lifecycles in one rule: .is-open for a surface.js panel, :popover-open
|
|
103
|
+
for one an author drives natively with popovertarget. */
|
|
104
|
+
.flyout:is(.is-open, :popover-open) {
|
|
105
|
+
inset: auto;
|
|
124
106
|
}
|
|
125
107
|
|
|
108
|
+
/* @starting-style is above the floor (Safari 17.5), so where it is missing the
|
|
109
|
+
entry simply has no animated origin and the panel appears at full opacity. */
|
|
126
110
|
@starting-style {
|
|
127
|
-
.flyout
|
|
128
|
-
|
|
111
|
+
.flyout:is(.is-open, :popover-open) {
|
|
112
|
+
opacity: 0;
|
|
129
113
|
}
|
|
130
114
|
}
|
|
131
115
|
|
|
116
|
+
.flyout[hidden] {
|
|
117
|
+
display: none;
|
|
118
|
+
opacity: 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* display keeps the exit transition alive for the [hidden] path; overlay does
|
|
122
|
+
the same for the native popover path, where hidePopover() would otherwise
|
|
123
|
+
drop the panel out of the top layer on the first frame and let a parent
|
|
124
|
+
overflow or a dialog clip the fade. An engine that cannot transition either
|
|
125
|
+
property ignores it and the exit is instant. */
|
|
132
126
|
@supports (transition-behavior: allow-discrete) {
|
|
133
127
|
.flyout {
|
|
134
128
|
transition:
|
|
135
129
|
opacity var(--duration-fast) ease,
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.flyout.is-sheet {
|
|
140
|
-
transition:
|
|
141
|
-
opacity var(--duration-fast) ease,
|
|
142
|
-
translate var(--duration-fast) ease,
|
|
130
|
+
overlay var(--duration-fast) allow-discrete,
|
|
143
131
|
display var(--duration-fast) allow-discrete;
|
|
144
132
|
}
|
|
145
133
|
}
|
|
@@ -157,7 +145,7 @@
|
|
|
157
145
|
margin: 0;
|
|
158
146
|
color: var(--text-muted);
|
|
159
147
|
font-size: var(--font-size-xs);
|
|
160
|
-
font-weight: var(--font-weight-
|
|
148
|
+
font-weight: var(--font-weight-semibold);
|
|
161
149
|
}
|
|
162
150
|
|
|
163
151
|
.flyout > section > ul {
|
|
@@ -175,8 +163,3 @@
|
|
|
175
163
|
/* Vertical dividers — .menu-separator (menu.css) is the canonical way to
|
|
176
164
|
separate menu items. Flyout panels that are not menus use auto grid gap
|
|
177
165
|
declared on .flyout itself. */
|
|
178
|
-
@media print {
|
|
179
|
-
.flyout {
|
|
180
|
-
display: none !important;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
@@ -38,10 +38,31 @@
|
|
|
38
38
|
inset-block-end: 0;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/* Safari before 16.4 has no :dir(); the ancestor-attribute path is the
|
|
42
|
+
Degraded-tier fallback and the :dir() rules are dropped on their own there.
|
|
43
|
+
:dir() follows inherited directionality, so the explicit ltr rules
|
|
44
|
+
neutralize an outer RTL fallback for a nested direction change. The rules
|
|
45
|
+
stay grouped by specificity so the fallback never follows the :dir() rules. */
|
|
46
|
+
[dir="rtl"] .indicator-item {
|
|
47
|
+
--indicator-translate-x: -50%;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.indicator-item:dir(ltr) {
|
|
51
|
+
--indicator-translate-x: 50%;
|
|
52
|
+
}
|
|
53
|
+
|
|
41
54
|
.indicator-item:dir(rtl) {
|
|
42
55
|
--indicator-translate-x: -50%;
|
|
43
56
|
}
|
|
44
57
|
|
|
58
|
+
[dir="rtl"] .indicator-item.start {
|
|
59
|
+
--indicator-translate-x: 50%;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.indicator-item.start:dir(ltr) {
|
|
63
|
+
--indicator-translate-x: -50%;
|
|
64
|
+
}
|
|
65
|
+
|
|
45
66
|
.indicator-item.start:dir(rtl) {
|
|
46
67
|
--indicator-translate-x: 50%;
|
|
47
68
|
}
|
|
@@ -63,6 +63,13 @@
|
|
|
63
63
|
border-end-start-radius: var(--join-es);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/* A square icon button has an explicit block size, which otherwise prevents
|
|
67
|
+
align-items: stretch from matching a taller labelled sibling. The button's
|
|
68
|
+
existing min-block-size keeps the standalone square-size invariant intact. */
|
|
69
|
+
.join > .btn.icon-only {
|
|
70
|
+
block-size: auto;
|
|
71
|
+
}
|
|
72
|
+
|
|
66
73
|
.join > :first-child {
|
|
67
74
|
--join-ss: var(--join-radius);
|
|
68
75
|
--join-es: var(--join-radius);
|
|
@@ -27,3 +27,13 @@
|
|
|
27
27
|
vertical-align: 0.08em;
|
|
28
28
|
}
|
|
29
29
|
/* @sync key-recipe */
|
|
30
|
+
|
|
31
|
+
/* .key has a compact typographic default of its own, so its local size roles
|
|
32
|
+
step around that default instead of inheriting the generic mapping. */
|
|
33
|
+
.key.sm {
|
|
34
|
+
font-size: var(--font-size-xs);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.key.lg {
|
|
38
|
+
font-size: var(--font-size-md);
|
|
39
|
+
}
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
--list-divider: var(--border-width) solid var(--border);
|
|
19
19
|
|
|
20
20
|
display: grid;
|
|
21
|
+
grid-template-columns: minmax(0, 1fr);
|
|
21
22
|
gap: 0;
|
|
22
23
|
margin: 0;
|
|
23
24
|
padding: 0;
|
|
@@ -29,10 +30,17 @@
|
|
|
29
30
|
margin: 0;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
/*
|
|
34
|
+
* Flex, not a three-track grid: the leading and trailing regions are optional,
|
|
35
|
+
* and a fixed `auto minmax(0, 1fr) auto` template gives an absent region a
|
|
36
|
+
* track anyway — the content of a row with no leading region lands in the
|
|
37
|
+
* leading track and the trailing control inherits the flexible one, which is
|
|
38
|
+
* the opposite of the intent. Flex drops both the track and its gap when a
|
|
39
|
+
* region is not there, so all four shapes work off one rule.
|
|
40
|
+
*/
|
|
32
41
|
.list > :where(.list-item),
|
|
33
42
|
.list > li > .list-item {
|
|
34
|
-
display:
|
|
35
|
-
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
43
|
+
display: flex;
|
|
36
44
|
/* Regions align to the first line, so leading, title, and trailing controls
|
|
37
45
|
share one horizontal line while supporting text wraps beneath. */
|
|
38
46
|
align-items: start;
|
|
@@ -48,6 +56,7 @@
|
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
a.list-item {
|
|
59
|
+
position: relative;
|
|
51
60
|
color: inherit;
|
|
52
61
|
text-decoration: none;
|
|
53
62
|
}
|
|
@@ -56,7 +65,31 @@ a.list-item:hover {
|
|
|
56
65
|
background: var(--surface-subtle);
|
|
57
66
|
}
|
|
58
67
|
|
|
68
|
+
/* Current row in a navigational list (master/detail). Generic by design: the
|
|
69
|
+
visual treatment only cares that the row is current, so presence is the
|
|
70
|
+
contract — the attribute is set on the current row and removed everywhere
|
|
71
|
+
else, never serialized as aria-current="false". The value (page, location,
|
|
72
|
+
…) stays free for assistive technology.
|
|
73
|
+
Calm by design: the row keeps its normal text metrics and color on a subtle
|
|
74
|
+
surface, and the selected accent lives on an inset inline-start trait only.
|
|
75
|
+
The trait is a real border, so it survives forced colors without a repaint
|
|
76
|
+
block. The positioning context lives on every row link, so becoming current
|
|
77
|
+
never moves an app-positioned decoration to a new containing block. */
|
|
78
|
+
a.list-item[aria-current] {
|
|
79
|
+
background: var(--surface-subtle);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
a.list-item[aria-current]::before {
|
|
83
|
+
content: "";
|
|
84
|
+
position: absolute;
|
|
85
|
+
inset-block: var(--list-item-pad-block);
|
|
86
|
+
inset-inline-start: 0;
|
|
87
|
+
border-inline-start: 2px solid var(--state-selected);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* The content region is the one that flexes, whichever position it holds. */
|
|
59
91
|
.list-item-content {
|
|
92
|
+
flex: 1 1 0;
|
|
60
93
|
min-inline-size: 0;
|
|
61
94
|
}
|
|
62
95
|
|
|
@@ -64,16 +97,19 @@ a.list-item:hover {
|
|
|
64
97
|
.list-item-text {
|
|
65
98
|
display: block;
|
|
66
99
|
margin: 0;
|
|
100
|
+
overflow-wrap: anywhere;
|
|
67
101
|
}
|
|
68
102
|
|
|
69
103
|
.list-item-text {
|
|
70
104
|
color: var(--text-muted);
|
|
71
105
|
font-size: var(--font-size-sm);
|
|
72
|
-
overflow-wrap: anywhere;
|
|
73
106
|
}
|
|
74
107
|
|
|
108
|
+
/* The auto margin keeps the trailing region at the row's end even in a row
|
|
109
|
+
with no content region to absorb the free space. */
|
|
75
110
|
.list-item-trailing {
|
|
76
|
-
|
|
111
|
+
flex: none;
|
|
112
|
+
margin-inline-start: auto;
|
|
77
113
|
min-inline-size: 0;
|
|
78
114
|
}
|
|
79
115
|
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
background: transparent;
|
|
45
45
|
color: var(--intent, var(--text));
|
|
46
46
|
font: inherit;
|
|
47
|
+
font-size: var(--control-font-size);
|
|
47
48
|
text-align: start;
|
|
48
49
|
text-decoration: none;
|
|
49
50
|
white-space: nowrap;
|
|
@@ -75,30 +76,36 @@
|
|
|
75
76
|
/* Checkable menu items are one command with one accessible state. Their
|
|
76
77
|
indicator is generated so authors do not add a second interactive input. */
|
|
77
78
|
.menu-item:is([role="menuitemcheckbox"], [role="menuitemradio"])::before {
|
|
78
|
-
|
|
79
|
+
content: "";
|
|
80
|
+
display: block;
|
|
79
81
|
flex: 0 0 var(--menu-item-icon-size);
|
|
80
82
|
inline-size: var(--menu-item-icon-size);
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.menu-item[role="menuitemcheckbox"]::before {
|
|
85
|
-
content: "";
|
|
83
|
+
block-size: var(--menu-item-icon-size);
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
.menu-item[role="menuitemcheckbox"][aria-checked="true"]::before {
|
|
89
|
-
|
|
87
|
+
background: currentColor;
|
|
88
|
+
-webkit-mask: var(--icon-check) center / contain no-repeat;
|
|
89
|
+
mask: var(--icon-check) center / contain no-repeat;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
.menu-item[role="menuitemcheckbox"][aria-checked="mixed"]::before {
|
|
93
|
-
|
|
93
|
+
background:
|
|
94
|
+
linear-gradient(currentColor 0 0) center / 60% max(var(--border-width), 0.125em) no-repeat;
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
.menu-item[role="menuitemradio"]::before {
|
|
97
|
-
|
|
98
|
+
background: radial-gradient(circle, transparent 0 46%, currentColor 48% 58%, transparent 60%);
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
.menu-item[role="menuitemradio"][aria-checked="true"]::before {
|
|
101
|
-
|
|
102
|
+
background: radial-gradient(
|
|
103
|
+
circle,
|
|
104
|
+
currentColor 0 25%,
|
|
105
|
+
transparent 27% 46%,
|
|
106
|
+
currentColor 48% 58%,
|
|
107
|
+
transparent 60%
|
|
108
|
+
);
|
|
102
109
|
}
|
|
103
110
|
|
|
104
111
|
.menu-item:focus-visible {
|
|
@@ -118,7 +125,7 @@
|
|
|
118
125
|
padding: var(--space-20);
|
|
119
126
|
color: var(--text-muted);
|
|
120
127
|
font-size: var(--font-size-xs);
|
|
121
|
-
font-weight: var(--font-weight-
|
|
128
|
+
font-weight: var(--font-weight-semibold);
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
.menu-separator {
|