actual-css 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -1
- package/README.md +24 -9
- package/dist/actual-themes.min.css +1 -0
- package/dist/actual.css +1532 -1114
- package/dist/actual.js +1 -3
- package/dist/actual.min.css +1 -1
- package/dist/optional.css +1048 -0
- package/dist/optional.min.css +1 -0
- package/docs/design-notes/browser-support.md +94 -14
- package/docs/design-notes/cascade-layer.md +7 -6
- package/docs/design-notes/enhancement-contract.md +11 -14
- package/docs/design-notes/forced-colors.md +105 -0
- package/docs/design-notes/naming.md +2 -1
- package/docs/design-notes/platform-alignment.md +492 -0
- package/docs/design-notes/references.md +8 -0
- package/docs/design-notes/widget-primitives.md +37 -1
- package/docs/navigation.json +135 -0
- package/docs/pages/components/accordion.md +80 -0
- package/docs/pages/components/alert.md +203 -0
- package/docs/pages/components/aura.md +35 -0
- package/docs/pages/components/avatar.md +95 -0
- package/docs/pages/components/badge.md +102 -0
- package/docs/pages/components/breadcrumb.md +19 -0
- package/docs/pages/components/button.md +210 -0
- package/docs/pages/components/card.md +195 -0
- package/docs/pages/components/chat.md +50 -0
- package/docs/pages/components/dialog.md +367 -0
- package/docs/pages/components/drawer.md +113 -0
- package/docs/pages/components/fab.md +118 -0
- package/docs/pages/components/key.md +33 -0
- package/docs/pages/components/meter.md +23 -0
- package/docs/pages/components/navbar.md +92 -0
- package/docs/pages/components/pagination.md +55 -0
- package/docs/pages/components/progress.md +29 -0
- package/docs/pages/components/skeleton.md +38 -0
- package/docs/pages/components/spinner.md +93 -0
- package/docs/pages/components/table.md +102 -0
- package/docs/pages/enhancements/flyout.md +391 -0
- package/docs/pages/enhancements/overview.md +36 -0
- package/docs/pages/enhancements/scrollspy.md +71 -0
- package/docs/pages/enhancements/status-bar.md +72 -0
- package/docs/pages/enhancements/tabs.md +80 -0
- package/docs/pages/enhancements/tooltip.md +130 -0
- package/docs/pages/examples/overview.md +43 -0
- package/docs/pages/forms/choice-cards.md +102 -0
- package/docs/pages/forms/controls.md +32 -0
- package/docs/pages/forms/detached-actions.md +59 -0
- package/docs/pages/forms/floating-field.md +88 -0
- package/docs/pages/forms/form-actions.md +56 -0
- package/docs/pages/forms/input-policy.md +91 -0
- package/docs/pages/forms/joined-controls.md +37 -0
- package/docs/pages/forms/labels.md +42 -0
- package/docs/pages/forms/otp.md +50 -0
- package/docs/pages/forms/overview.md +188 -0
- package/docs/pages/forms/password.md +40 -0
- package/docs/pages/forms/range.md +17 -0
- package/docs/pages/forms/states-and-sizes.md +321 -0
- package/docs/pages/forms/sticky-actions.md +187 -0
- package/docs/pages/forms/switch.md +31 -0
- package/docs/pages/forms/validation.md +241 -0
- package/docs/{mental-model.md → pages/foundations/philosophy.md} +33 -18
- package/docs/pages/foundations/theming.md +99 -0
- package/docs/pages/foundations/tokens.md +421 -0
- package/docs/{typography.md → pages/foundations/typography.md} +27 -9
- package/docs/pages/guides/bootstrap.md +438 -0
- package/docs/pages/guides/introduction.md +157 -0
- package/docs/pages/guides/optional-components.md +33 -0
- package/docs/pages/guides/progressive-enhancement.md +686 -0
- package/docs/pages/guides/tailwind.md +455 -0
- package/docs/pages/layout/app-shell.md +25 -0
- package/docs/pages/layout/center.md +29 -0
- package/docs/pages/layout/cluster.md +59 -0
- package/docs/pages/layout/frame.md +30 -0
- package/docs/pages/layout/grid.md +142 -0
- package/docs/pages/layout/list.md +41 -0
- package/docs/pages/layout/media.md +28 -0
- package/docs/pages/layout/overview.md +37 -0
- package/docs/pages/layout/scroll-snap.md +54 -0
- package/docs/pages/layout/sidebar-layout.md +27 -0
- package/docs/pages/layout/stack.md +55 -0
- package/docs/pages/layout/switcher.md +36 -0
- package/docs/pages/layout/topbar.md +23 -0
- package/docs/pages/patterns/actions.md +52 -0
- package/docs/pages/patterns/code-block.md +36 -0
- package/docs/pages/patterns/exclusive-accordion.md +16 -0
- package/docs/pages/patterns/hierarchical-nav.md +26 -0
- package/docs/pages/patterns/icon-input.md +25 -0
- package/docs/pages/patterns/intent-nesting.md +3 -0
- package/docs/pages/patterns/navigation-list.md +235 -0
- package/docs/pages/patterns/overview.md +58 -0
- package/docs/pages/patterns/structured-lists.md +47 -0
- package/docs/pages/utilities/accessibility.md +34 -0
- package/docs/pages/utilities/flex.md +105 -0
- package/docs/pages/utilities/links.md +18 -0
- package/docs/pages/utilities/list.md +32 -0
- package/docs/pages/utilities/overflow.md +43 -0
- package/docs/pages/utilities/overview.md +18 -0
- package/docs/pages/utilities/shape.md +25 -0
- package/docs/pages/utilities/sizing-wrapping.md +115 -0
- package/docs/pages/utilities/spacing.md +79 -0
- package/docs/pages/utilities/text.md +43 -0
- package/llms.txt +4 -4
- package/package.json +21 -12
- package/src/css/actual.css +16 -2
- package/src/css/base.css +3 -5
- package/src/css/components/accordion.css +18 -30
- package/src/css/components/actions.css +4 -1
- package/src/css/components/alert.css +139 -102
- package/src/css/components/avatar.css +16 -10
- package/src/css/components/badge.css +69 -42
- package/src/css/components/breadcrumb.css +7 -15
- package/src/css/components/busy.css +6 -0
- package/src/css/components/button.css +84 -34
- package/src/css/components/card.css +26 -38
- package/src/css/components/drawer.css +30 -13
- package/src/css/components/flyout.css +39 -109
- package/src/css/components/index.css +1 -0
- package/src/css/components/join.css +14 -2
- package/src/css/components/key.css +2 -0
- package/src/css/components/menu.css +125 -0
- package/src/css/components/meter.css +0 -23
- package/src/css/components/modal.css +162 -7
- package/src/css/components/navbar.css +30 -23
- package/src/css/components/overline.css +8 -9
- package/src/css/components/pagination.css +1 -1
- package/src/css/components/progress.css +8 -26
- package/src/css/components/skeleton.css +7 -0
- package/src/css/components/spinner.css +6 -7
- package/src/css/components/status-bar.css +15 -24
- package/src/css/components/surface.css +2 -8
- package/src/css/components/tab.css +19 -48
- package/src/css/components/table.css +7 -5
- package/src/css/components/tooltip.css +14 -7
- package/src/css/focus.css +14 -38
- package/src/css/forms/choice-card.css +13 -14
- package/src/css/forms/choice.css +21 -27
- package/src/css/forms/control.css +18 -17
- package/src/css/forms/custom-select.css +9 -11
- package/src/css/forms/form-actions.css +14 -3
- package/src/css/forms/form.css +7 -4
- package/src/css/forms/index.css +4 -4
- package/src/css/forms/input-icon.css +30 -12
- package/src/css/forms/native.css +50 -11
- package/src/css/forms/range.css +17 -9
- package/src/css/forms/select.css +8 -8
- package/src/css/forms/switch.css +14 -12
- package/src/css/forms/validation.css +32 -5
- package/src/css/grid.css +32 -18
- package/src/css/intents.css +2 -2
- package/src/css/layout.css +45 -2
- package/src/css/optional/aura.css +93 -0
- package/src/css/optional/chat.css +105 -0
- package/src/css/optional/fab.css +104 -0
- package/src/css/optional/floating-field.css +87 -0
- package/src/css/optional/index.css +5 -0
- package/src/css/optional/layout-extra.css +7 -4
- package/src/css/optional/otp.css +115 -0
- package/src/css/optional/scroll-snap.css +6 -0
- package/src/css/optional/scroller.css +13 -7
- package/src/css/optional/typography-fluid.css +5 -0
- package/src/css/optional/utilities-extra.css +17 -2
- package/src/css/prose.css +18 -8
- package/src/css/reset.css +0 -10
- package/src/css/theme.css +21 -5
- package/src/css/themes/cyberpunk.css +1 -1
- package/src/css/themes/dim.css +3 -3
- package/src/css/themes/edge.css +8 -10
- package/src/css/themes/index.css +8 -4
- package/src/css/themes/{dark.css → indigo.css} +5 -4
- package/src/css/themes/neon.css +5 -5
- package/src/css/themes/square.css +0 -3
- package/src/css/tokens.css +74 -20
- package/src/css/utilities.css +8 -10
- package/src/css/variants.css +51 -66
- package/src/js/command.js +1 -3
- package/src/js/context-menu.js +67 -35
- package/src/js/dialog.js +68 -79
- package/src/js/dismiss.js +15 -0
- package/src/js/enhance.js +54 -23
- package/src/js/enhancement-loader.js +301 -0
- package/src/js/events.js +3 -0
- package/src/js/filter.js +3 -3
- package/src/js/floating.js +101 -131
- package/src/js/flyout.js +104 -87
- package/src/js/focus-group.js +116 -0
- package/src/js/focus.js +6 -1
- package/src/js/index.js +4 -2
- package/src/js/input.js +1 -1
- package/src/js/keys.js +27 -0
- package/src/js/mask.js +7 -6
- package/src/js/menu.js +87 -34
- package/src/js/parse-config.js +47 -0
- package/src/js/password.js +9 -1
- package/src/js/scrollspy.js +12 -4
- package/src/js/selectors.js +0 -7
- package/src/js/status.js +3 -1
- package/src/js/surface.js +187 -136
- package/src/js/tab.js +36 -53
- package/src/js/tooltip.js +70 -35
- package/src/js/validation.js +34 -8
- package/dist/actual.js.map +0 -31
- package/docs/README.md +0 -28
- package/docs/components.md +0 -860
- package/docs/design-notes/previous-work.md +0 -5
- package/docs/forms.md +0 -1265
- package/docs/javascript.md +0 -496
- package/docs/layout.md +0 -480
- package/docs/patterns.md +0 -504
- package/docs/reserved.md +0 -7
- package/docs/tokens.md +0 -455
- package/docs/ui.md +0 -929
- package/docs/utilities.md +0 -384
- package/src/css/dialog-fallback.css +0 -56
- package/src/js/dialog-fallback.js +0 -163
|
@@ -9,19 +9,40 @@
|
|
|
9
9
|
* Disabled state uses the native disabled attribute for buttons and inputs.
|
|
10
10
|
* Anchors have no native disabled state, so a.btn uses aria-disabled="true"
|
|
11
11
|
* for disabled styling and activation guards.
|
|
12
|
+
*
|
|
13
|
+
* Public hooks:
|
|
14
|
+
* --btn-font-size
|
|
15
|
+
* --btn-min-size
|
|
16
|
+
* --btn-pad-x
|
|
17
|
+
* --btn-radius
|
|
18
|
+
* --btn-focus-color
|
|
19
|
+
* --btn-gap
|
|
20
|
+
* --btn-hover-overlay
|
|
21
|
+
* --btn-default-bg
|
|
22
|
+
* --btn-default-fg
|
|
23
|
+
* --btn-default-border
|
|
24
|
+
* --btn-border-color
|
|
25
|
+
*
|
|
26
|
+
* Internal:
|
|
27
|
+
* --btn-bg
|
|
28
|
+
* --btn-fg
|
|
29
|
+
* --btn-border
|
|
30
|
+
* --btn-default-hover-bg
|
|
31
|
+
* --btn-focus-ring-color
|
|
32
|
+
* --btn-border-block-end-color
|
|
33
|
+
* --btn-border-block-end-width
|
|
34
|
+
* --spinner-width
|
|
12
35
|
*/
|
|
13
36
|
|
|
14
37
|
/* Intent boundary — inherited intents do not tint this component.
|
|
15
38
|
Local intent classes still win because :where() has zero specificity. */
|
|
16
39
|
:where(.btn) {
|
|
17
|
-
/* @sync intent-boundary */
|
|
18
40
|
--intent: initial;
|
|
19
41
|
--intent-fg: initial;
|
|
20
42
|
--ui-bg: initial;
|
|
21
43
|
--ui-fg: initial;
|
|
22
44
|
--ui-border: initial;
|
|
23
45
|
--ui-hover-bg: initial;
|
|
24
|
-
/* @sync intent-boundary */
|
|
25
46
|
}
|
|
26
47
|
|
|
27
48
|
.btn {
|
|
@@ -31,19 +52,20 @@
|
|
|
31
52
|
--btn-bg: var(--ui-bg, var(--btn-default-bg, var(--intent, var(--neutral))));
|
|
32
53
|
--btn-fg: var(--ui-fg, var(--btn-default-fg, var(--intent-fg, var(--neutral-fg))));
|
|
33
54
|
--btn-border: var(--ui-border, var(--btn-default-border, transparent));
|
|
55
|
+
--btn-default-hover-bg: var(--btn-bg);
|
|
34
56
|
--btn-radius: var(--radius);
|
|
35
57
|
--btn-focus-color: var(--intent, var(--focus));
|
|
36
|
-
--btn-hover-bg: var(--ui-hover-bg, var(--btn-bg));
|
|
37
58
|
--btn-hover-overlay: var(--hover-overlay, rgb(0 0 0 / 0.08));
|
|
38
59
|
|
|
60
|
+
/* Positioning context for indicators, overlays, and grouped states. */
|
|
39
61
|
position: relative;
|
|
40
62
|
display: inline-flex;
|
|
41
63
|
align-items: center;
|
|
42
64
|
justify-content: center;
|
|
43
|
-
gap: 0.375em;
|
|
65
|
+
gap: var(--btn-gap, 0.375em);
|
|
44
66
|
min-block-size: var(--btn-min-size);
|
|
45
|
-
padding-block: var(--space-
|
|
46
|
-
padding-block: max(var(--space-
|
|
67
|
+
padding-block: var(--space-20);
|
|
68
|
+
padding-block: max(var(--space-10), calc((var(--btn-min-size) - 1lh) / 2));
|
|
47
69
|
padding-inline: var(--btn-pad-x);
|
|
48
70
|
border: var(--border-width) solid var(--btn-border-color, var(--btn-border));
|
|
49
71
|
border-block-end-color: var(
|
|
@@ -68,6 +90,11 @@
|
|
|
68
90
|
transform var(--duration);
|
|
69
91
|
}
|
|
70
92
|
|
|
93
|
+
.btn.icon-only {
|
|
94
|
+
inline-size: var(--btn-min-size);
|
|
95
|
+
padding-inline: 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
71
98
|
@supports (color: color-mix(in oklch, red, white)) {
|
|
72
99
|
.btn {
|
|
73
100
|
--btn-focus-ring-color: color-mix(in oklch, var(--btn-focus-color) 28%, transparent);
|
|
@@ -78,7 +105,7 @@
|
|
|
78
105
|
fallbacks make .btn solid by default; .ghost/.link are .btn-only variants. */
|
|
79
106
|
.btn.ghost {
|
|
80
107
|
--ui-bg: transparent;
|
|
81
|
-
--ui-fg: var(--intent,
|
|
108
|
+
--ui-fg: var(--intent, currentColor);
|
|
82
109
|
--ui-border: transparent;
|
|
83
110
|
}
|
|
84
111
|
|
|
@@ -92,22 +119,46 @@
|
|
|
92
119
|
--btn-hover-overlay: transparent;
|
|
93
120
|
}
|
|
94
121
|
|
|
95
|
-
/*
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
122
|
+
/* Shared hover recipe — sets --ui-hover-bg consumed by the hover rule below.
|
|
123
|
+
Declared outside :hover: the variables resolve only when the hover rule
|
|
124
|
+
reads them, so the values are inert until interaction. */
|
|
125
|
+
.btn:is(.outline, .ghost) {
|
|
126
|
+
--ui-hover-bg: transparent;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@supports (color: color-mix(in oklch, red, white)) {
|
|
130
|
+
.btn {
|
|
131
|
+
--btn-default-hover-bg: color-mix(in oklch, var(--btn-bg) 88%, black);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.btn.soft {
|
|
135
|
+
--ui-hover-bg: color-mix(
|
|
136
|
+
in oklch,
|
|
137
|
+
var(--surface) calc(var(--soft-bg-mix) - var(--soft-hover-alpha)),
|
|
138
|
+
var(--intent, var(--neutral))
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.btn.outline,
|
|
143
|
+
.btn.ghost {
|
|
144
|
+
--ui-hover-bg: color-mix(in oklch, currentColor 10%, transparent);
|
|
101
145
|
}
|
|
102
146
|
}
|
|
103
147
|
|
|
148
|
+
/* The .soft/.outline/.ghost hover recipe (--ui-hover-bg) is set locally above;
|
|
149
|
+
the overlay darkening for solid/soft is .btn-specific. */
|
|
150
|
+
.btn:not(:where(:disabled, [aria-disabled="true"])):hover {
|
|
151
|
+
background: var(--ui-hover-bg, var(--btn-default-hover-bg));
|
|
152
|
+
box-shadow: inset 0 0 0 999px var(--btn-hover-overlay);
|
|
153
|
+
}
|
|
154
|
+
|
|
104
155
|
.btn:not(:where(:disabled, [aria-disabled="true"])):active {
|
|
105
156
|
transform: translateY(1px);
|
|
106
157
|
}
|
|
107
158
|
|
|
108
159
|
.btn.link {
|
|
109
160
|
--ui-bg: transparent;
|
|
110
|
-
--ui-fg: var(--intent,
|
|
161
|
+
--ui-fg: var(--intent, currentColor);
|
|
111
162
|
--ui-border: transparent;
|
|
112
163
|
--btn-radius: var(--radius-sm);
|
|
113
164
|
--btn-border-block-end-color: transparent;
|
|
@@ -115,6 +166,8 @@
|
|
|
115
166
|
|
|
116
167
|
min-block-size: auto;
|
|
117
168
|
padding-inline: 0;
|
|
169
|
+
inline-size: fit-content;
|
|
170
|
+
max-inline-size: 100%;
|
|
118
171
|
border-color: transparent;
|
|
119
172
|
text-decoration: underline;
|
|
120
173
|
text-underline-offset: 0.18em;
|
|
@@ -123,16 +176,13 @@
|
|
|
123
176
|
/* .btn.circle needs no local rule: the .circle utility (utilities.css) loads
|
|
124
177
|
after components and overrides border-radius at equal specificity. */
|
|
125
178
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
color: var(--intent, var(--text));
|
|
130
|
-
text-decoration-thickness: 0.12em;
|
|
131
|
-
}
|
|
179
|
+
.btn.link:not(:where(:disabled, [aria-disabled="true"])):hover {
|
|
180
|
+
background: transparent;
|
|
181
|
+
text-decoration-thickness: 0.12em;
|
|
132
182
|
}
|
|
133
183
|
|
|
134
184
|
.btn:focus-visible {
|
|
135
|
-
outline:
|
|
185
|
+
outline: 2px solid transparent;
|
|
136
186
|
box-shadow: 0 0 0 var(--focus-ring-width) var(--btn-focus-ring-color, var(--focus-ring));
|
|
137
187
|
}
|
|
138
188
|
|
|
@@ -166,13 +216,15 @@ a.btn[aria-disabled="true"] {
|
|
|
166
216
|
--spinner-width: 0.15em;
|
|
167
217
|
}
|
|
168
218
|
|
|
169
|
-
/* Toggle
|
|
170
|
-
|
|
171
|
-
button keeps its intent background and foreground while hovered.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
--btn-
|
|
219
|
+
/* Toggle and current state.
|
|
220
|
+
State must outrank the shared .outline/.ghost hover recipes: a pressed or
|
|
221
|
+
current button keeps its intent background and foreground while hovered.
|
|
222
|
+
aria-current="page" is the pagination current-page marker; aria-pressed
|
|
223
|
+
covers toggle buttons. */
|
|
224
|
+
.btn:is([aria-pressed="true"], [aria-current="page"]):not(.link) {
|
|
225
|
+
--btn-bg: var(--intent, var(--state-selected));
|
|
226
|
+
--btn-fg: var(--intent-fg, var(--state-selected-fg));
|
|
227
|
+
--btn-border: var(--intent, var(--state-selected));
|
|
176
228
|
--ui-hover-bg: var(--btn-bg);
|
|
177
229
|
}
|
|
178
230
|
|
|
@@ -190,18 +242,16 @@ a.btn[aria-disabled="true"] {
|
|
|
190
242
|
color: LinkText;
|
|
191
243
|
}
|
|
192
244
|
|
|
193
|
-
.btn:is([aria-pressed="true"], [aria-current
|
|
245
|
+
.btn:is([aria-pressed="true"], [aria-current="page"]):not(.link) {
|
|
194
246
|
border-color: Highlight;
|
|
195
247
|
background: Highlight;
|
|
196
248
|
color: HighlightText;
|
|
197
249
|
forced-color-adjust: none;
|
|
198
250
|
}
|
|
199
251
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
outline-offset: 2px;
|
|
204
|
-
}
|
|
252
|
+
.btn:hover:not(:where(:disabled, [aria-disabled="true"], .link)) {
|
|
253
|
+
outline: var(--border-width) solid ButtonText;
|
|
254
|
+
outline-offset: 2px;
|
|
205
255
|
}
|
|
206
256
|
|
|
207
257
|
.btn:disabled,
|
|
@@ -4,29 +4,45 @@
|
|
|
4
4
|
* Surface, border, radius, padding, density, and elevation stay local here.
|
|
5
5
|
* Direct header/footer children are structural slots. Page layout remains the
|
|
6
6
|
* job of markup and layout primitives outside the card.
|
|
7
|
+
*
|
|
8
|
+
* Public hooks:
|
|
9
|
+
* --card-pad
|
|
10
|
+
* --card-radius
|
|
11
|
+
* --card-max-inline-size
|
|
12
|
+
*
|
|
13
|
+
* Child contract:
|
|
14
|
+
* Direct .bleed children escape --card-pad (negative inset, wider media);
|
|
15
|
+
* edge children inherit the card corners. .bleed must be a direct child.
|
|
16
|
+
*
|
|
17
|
+
* Internal:
|
|
18
|
+
* --card-bg
|
|
19
|
+
* --card-fg
|
|
20
|
+
* --heading
|
|
21
|
+
* --busy-overlay-bg
|
|
7
22
|
*/
|
|
8
23
|
/* Intent boundary — inherited intents do not tint this component.
|
|
9
24
|
Local intent classes still win because :where() has zero specificity. */
|
|
10
25
|
:where(.card) {
|
|
11
|
-
/* @sync intent-boundary */
|
|
12
|
-
--intent: initial;
|
|
13
|
-
--intent-fg: initial;
|
|
14
26
|
--ui-bg: initial;
|
|
15
27
|
--ui-fg: initial;
|
|
16
28
|
--ui-border: initial;
|
|
17
|
-
--ui-hover-bg: initial;
|
|
18
|
-
/* @sync intent-boundary */
|
|
19
29
|
}
|
|
20
30
|
|
|
21
31
|
.card {
|
|
22
|
-
--card-pad: var(--space-
|
|
32
|
+
--card-pad: var(--space-40);
|
|
23
33
|
--card-radius: var(--radius-lg);
|
|
24
34
|
--card-max-inline-size: none;
|
|
35
|
+
--card-bg: var(--ui-bg, var(--surface-raised));
|
|
36
|
+
--card-fg: var(--ui-fg, var(--text));
|
|
37
|
+
|
|
38
|
+
/* Keep contextual descendants tied to the surface this card actually owns. */
|
|
39
|
+
--heading: var(--card-fg);
|
|
40
|
+
--busy-overlay-bg: var(--card-bg);
|
|
25
41
|
|
|
26
42
|
max-inline-size: var(--card-max-inline-size);
|
|
27
43
|
padding: var(--card-pad);
|
|
28
|
-
background: var(--
|
|
29
|
-
color: var(--
|
|
44
|
+
background: var(--card-bg);
|
|
45
|
+
color: var(--card-fg);
|
|
30
46
|
border: var(--border-width) solid var(--ui-border, var(--border));
|
|
31
47
|
border-radius: var(--card-radius);
|
|
32
48
|
}
|
|
@@ -40,7 +56,7 @@
|
|
|
40
56
|
flex-wrap: wrap;
|
|
41
57
|
align-items: var(--items-align, center);
|
|
42
58
|
justify-content: space-between;
|
|
43
|
-
gap: var(--space-
|
|
59
|
+
gap: var(--space-30);
|
|
44
60
|
min-inline-size: 0;
|
|
45
61
|
}
|
|
46
62
|
|
|
@@ -67,16 +83,8 @@
|
|
|
67
83
|
.card.subtle {
|
|
68
84
|
background: var(--surface-subtle);
|
|
69
85
|
}
|
|
70
|
-
.card.inverted {
|
|
71
|
-
background: var(--surface-solid);
|
|
72
|
-
color: var(--surface);
|
|
73
|
-
border-color: transparent;
|
|
74
|
-
--heading: var(--surface);
|
|
75
|
-
--busy-overlay-bg: var(--surface-solid);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
86
|
.card.compact {
|
|
79
|
-
--card-pad: var(--space-
|
|
87
|
+
--card-pad: var(--space-20);
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
/* Full-bleed children */
|
|
@@ -118,23 +126,3 @@
|
|
|
118
126
|
.card > :where(header, footer, figure).bleed {
|
|
119
127
|
padding: var(--card-pad);
|
|
120
128
|
}
|
|
121
|
-
|
|
122
|
-
@media (forced-colors: active) {
|
|
123
|
-
.card {
|
|
124
|
-
border-color: ButtonText;
|
|
125
|
-
background: Canvas;
|
|
126
|
-
color: CanvasText;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.card.raised {
|
|
130
|
-
box-shadow: none;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.card.inverted {
|
|
134
|
-
--heading: CanvasText;
|
|
135
|
-
|
|
136
|
-
border-color: ButtonText;
|
|
137
|
-
background: Canvas;
|
|
138
|
-
color: CanvasText;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
@@ -6,16 +6,30 @@
|
|
|
6
6
|
* discrete display/overlay transitions. The drawer is a layout shell only —
|
|
7
7
|
* navigation content inside uses .nav-link and .accordion, which carry their
|
|
8
8
|
* own link/summary styling.
|
|
9
|
+
*
|
|
10
|
+
* Public hooks:
|
|
11
|
+
* --drawer-size
|
|
12
|
+
* --drawer-pad
|
|
13
|
+
*
|
|
14
|
+
* Internal:
|
|
15
|
+
* --drawer-closed-translate (side/RTL positioning state)
|
|
9
16
|
*/
|
|
10
17
|
dialog.drawer {
|
|
11
18
|
--drawer-size: 20rem;
|
|
12
|
-
--drawer-pad: var(--space-
|
|
19
|
+
--drawer-pad: var(--space-40);
|
|
13
20
|
--drawer-closed-translate: -100%;
|
|
14
21
|
|
|
22
|
+
/* Keep the surface anchored to the viewport in the top layer. This also
|
|
23
|
+
provides the containing block for the absolutely positioned close button.
|
|
24
|
+
A percentage height resolves against the fixed containing viewport, while
|
|
25
|
+
dynamic viewport units can be stale in embedded previews. */
|
|
26
|
+
position: fixed;
|
|
27
|
+
inset-block-start: 0;
|
|
28
|
+
|
|
15
29
|
inline-size: min(calc(var(--viewport-inline) * 0.9), var(--drawer-size));
|
|
16
|
-
block-size:
|
|
30
|
+
block-size: 100%;
|
|
17
31
|
max-inline-size: none;
|
|
18
|
-
max-block-size:
|
|
32
|
+
max-block-size: 100%;
|
|
19
33
|
margin: 0;
|
|
20
34
|
padding: var(--drawer-pad);
|
|
21
35
|
border: 0;
|
|
@@ -34,7 +48,7 @@ dialog.drawer {
|
|
|
34
48
|
dialog.drawer[open] {
|
|
35
49
|
display: grid;
|
|
36
50
|
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
37
|
-
gap: var(--space-
|
|
51
|
+
gap: var(--space-40);
|
|
38
52
|
opacity: 1;
|
|
39
53
|
transform: translateX(0);
|
|
40
54
|
}
|
|
@@ -105,18 +119,21 @@ dialog.drawer nav {
|
|
|
105
119
|
}
|
|
106
120
|
|
|
107
121
|
@media (forced-colors: active) {
|
|
108
|
-
dialog.drawer {
|
|
109
|
-
border-inline-end-color: ButtonText;
|
|
122
|
+
dialog.drawer::backdrop {
|
|
110
123
|
background: Canvas;
|
|
111
|
-
color: CanvasText;
|
|
112
|
-
box-shadow: none;
|
|
113
124
|
}
|
|
125
|
+
}
|
|
114
126
|
|
|
115
|
-
|
|
116
|
-
|
|
127
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
128
|
+
dialog.drawer.is-static {
|
|
129
|
+
animation: actual-dialog-static var(--duration-slow) var(--ease);
|
|
117
130
|
}
|
|
131
|
+
}
|
|
118
132
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
133
|
+
/* The close button shares the modal's interior placement (modal.css): absolute
|
|
134
|
+
at the panel's top inline-end, out of the content flow. The header reserves
|
|
135
|
+
inline room so the title never runs under it. */
|
|
136
|
+
dialog.drawer > header,
|
|
137
|
+
dialog.drawer > form > header {
|
|
138
|
+
padding-inline-end: calc(var(--control-size) + var(--space-30));
|
|
122
139
|
}
|
|
@@ -9,7 +9,16 @@
|
|
|
9
9
|
* .is-sheet marks "auto" resolved to bottom-sheet presentation on coarse
|
|
10
10
|
* pointers. Authors opt into mobile behavior with
|
|
11
11
|
* [data-flyout-mobile="sheet|auto|none|anchored"].
|
|
12
|
-
* --
|
|
12
|
+
* --surface-anchor-width is set by surface.js while an open flyout is positioned.
|
|
13
|
+
*
|
|
14
|
+
* Public hooks:
|
|
15
|
+
* --flyout-inline-size
|
|
16
|
+
* --flyout-max-inline-size
|
|
17
|
+
*
|
|
18
|
+
* Internal:
|
|
19
|
+
* --menu-item-size (derived from --control-size for menu rows)
|
|
20
|
+
* --available-height (measured by floating.js)
|
|
21
|
+
* --surface-anchor-width (measured by surface.js)
|
|
13
22
|
*/
|
|
14
23
|
|
|
15
24
|
.flyout-trigger {
|
|
@@ -32,28 +41,32 @@
|
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
.flyout {
|
|
44
|
+
--menu-item-size: var(--control-size);
|
|
35
45
|
z-index: var(--z-menu);
|
|
36
46
|
/* No-JS fallback: below the trigger inside the relative .flyout-trigger.
|
|
37
47
|
surface.js switches an open flyout to position: fixed with measured
|
|
38
48
|
coordinates; this only covers a flyout revealed without the runtime. */
|
|
39
49
|
position: absolute;
|
|
40
|
-
inset-block-start: calc(100% + var(--space-
|
|
50
|
+
inset-block-start: calc(100% + var(--space-10));
|
|
41
51
|
inset-inline-start: 0;
|
|
42
52
|
display: grid;
|
|
43
|
-
gap: var(--space-
|
|
53
|
+
gap: var(--space-10);
|
|
44
54
|
inline-size: var(--flyout-inline-size, max-content);
|
|
45
55
|
min-inline-size: min(
|
|
46
|
-
var(--
|
|
47
|
-
min(var(--flyout-max-inline-size, 20rem), calc(var(--viewport-inline) - var(--space-
|
|
56
|
+
var(--surface-anchor-width, 0px),
|
|
57
|
+
min(var(--flyout-max-inline-size, 20rem), calc(var(--viewport-inline) - var(--space-60)))
|
|
48
58
|
);
|
|
49
59
|
max-inline-size: min(
|
|
50
60
|
var(--flyout-max-inline-size, 20rem),
|
|
51
|
-
calc(var(--viewport-inline) - var(--space-
|
|
61
|
+
calc(var(--viewport-inline) - var(--space-60))
|
|
62
|
+
);
|
|
63
|
+
max-block-size: min(
|
|
64
|
+
24rem,
|
|
65
|
+
var(--available-height, calc(var(--viewport-block) - var(--space-60)))
|
|
52
66
|
);
|
|
53
|
-
max-block-size: min(24rem, var(--available-height, calc(var(--viewport-block) - var(--space-6))));
|
|
54
67
|
overflow: auto;
|
|
55
68
|
margin: 0;
|
|
56
|
-
padding: var(--space-
|
|
69
|
+
padding: var(--space-10);
|
|
57
70
|
border: var(--border-width) solid var(--border);
|
|
58
71
|
border-radius: var(--radius);
|
|
59
72
|
background: var(--surface-raised);
|
|
@@ -62,9 +75,9 @@
|
|
|
62
75
|
opacity: 1;
|
|
63
76
|
scale: 1;
|
|
64
77
|
transition:
|
|
65
|
-
opacity var(--duration-fast
|
|
66
|
-
scale var(--duration-fast
|
|
67
|
-
translate var(--duration-fast
|
|
78
|
+
opacity var(--duration-fast) var(--ease),
|
|
79
|
+
scale var(--duration-fast) var(--ease),
|
|
80
|
+
translate var(--duration-fast) var(--ease);
|
|
68
81
|
}
|
|
69
82
|
|
|
70
83
|
.flyout.is-open:not(.is-sheet) {
|
|
@@ -81,6 +94,7 @@
|
|
|
81
94
|
/* Bottom-sheet presentation. surface.js toggles .is-sheet when the flyout is
|
|
82
95
|
opened on coarse pointer / narrow viewports. */
|
|
83
96
|
.flyout.is-sheet {
|
|
97
|
+
--menu-item-size: var(--control-size-lg);
|
|
84
98
|
position: fixed;
|
|
85
99
|
inset-inline: 0;
|
|
86
100
|
inset-block-start: auto;
|
|
@@ -91,8 +105,8 @@
|
|
|
91
105
|
max-block-size: min(calc(var(--viewport-block) * 0.75), 32rem);
|
|
92
106
|
overflow: auto;
|
|
93
107
|
grid-template-columns: 1fr;
|
|
94
|
-
padding: max(var(--space-
|
|
95
|
-
max(var(--space-
|
|
108
|
+
padding: max(var(--space-30), env(safe-area-inset-top)) var(--space-30)
|
|
109
|
+
max(var(--space-30), env(safe-area-inset-bottom));
|
|
96
110
|
border-end-start-radius: 0;
|
|
97
111
|
border-end-end-radius: 0;
|
|
98
112
|
}
|
|
@@ -105,23 +119,23 @@
|
|
|
105
119
|
|
|
106
120
|
.flyout.is-sheet[hidden] {
|
|
107
121
|
scale: 1;
|
|
108
|
-
translate: 0 var(--space-
|
|
122
|
+
translate: 0 var(--space-30);
|
|
109
123
|
}
|
|
110
124
|
|
|
111
125
|
@starting-style {
|
|
112
126
|
.flyout.is-sheet.is-open {
|
|
113
127
|
scale: 1;
|
|
114
|
-
translate: 0 var(--space-
|
|
128
|
+
translate: 0 var(--space-30);
|
|
115
129
|
}
|
|
116
130
|
}
|
|
117
131
|
|
|
118
132
|
@supports (transition-behavior: allow-discrete) {
|
|
119
133
|
.flyout {
|
|
120
134
|
transition:
|
|
121
|
-
opacity var(--duration-fast
|
|
122
|
-
scale var(--duration-fast
|
|
123
|
-
translate var(--duration-fast
|
|
124
|
-
display var(--duration-fast
|
|
135
|
+
opacity var(--duration-fast) var(--ease),
|
|
136
|
+
scale var(--duration-fast) var(--ease),
|
|
137
|
+
translate var(--duration-fast) var(--ease),
|
|
138
|
+
display var(--duration-fast) allow-discrete;
|
|
125
139
|
}
|
|
126
140
|
}
|
|
127
141
|
|
|
@@ -131,7 +145,7 @@
|
|
|
131
145
|
|
|
132
146
|
.flyout > :where(section, footer) {
|
|
133
147
|
min-inline-size: 0;
|
|
134
|
-
padding: var(--space-
|
|
148
|
+
padding: var(--space-20);
|
|
135
149
|
}
|
|
136
150
|
|
|
137
151
|
.flyout > section > :where(h1, h2, h3, h4, h5, h6) {
|
|
@@ -143,8 +157,8 @@
|
|
|
143
157
|
|
|
144
158
|
.flyout > section > ul {
|
|
145
159
|
display: grid;
|
|
146
|
-
gap: var(--space-
|
|
147
|
-
margin: var(--space-
|
|
160
|
+
gap: var(--space-10);
|
|
161
|
+
margin: var(--space-10) 0 0;
|
|
148
162
|
padding: 0;
|
|
149
163
|
list-style: none;
|
|
150
164
|
}
|
|
@@ -153,90 +167,6 @@
|
|
|
153
167
|
margin: 0;
|
|
154
168
|
}
|
|
155
169
|
|
|
156
|
-
/*
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
:where(li) keeps specificity at a single class (0,1,0) so consumer
|
|
160
|
-
overrides behave the same as a plain .flyout > rule. */
|
|
161
|
-
:is(.flyout, .flyout :where(li)) > :where(button, a, [role="menuitem"]) {
|
|
162
|
-
display: flex;
|
|
163
|
-
align-items: center;
|
|
164
|
-
justify-content: flex-start;
|
|
165
|
-
gap: var(--space-2);
|
|
166
|
-
inline-size: 100%;
|
|
167
|
-
min-block-size: var(--control-size);
|
|
168
|
-
padding-inline: var(--space-2);
|
|
169
|
-
border: 0;
|
|
170
|
-
border-radius: var(--radius-sm);
|
|
171
|
-
background: none;
|
|
172
|
-
color: var(--text);
|
|
173
|
-
font: inherit;
|
|
174
|
-
font-weight: var(--font-weight);
|
|
175
|
-
text-decoration: none;
|
|
176
|
-
text-align: start;
|
|
177
|
-
white-space: nowrap;
|
|
178
|
-
cursor: pointer;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
:is(.flyout.is-sheet, .flyout.is-sheet :where(li)) > :where(button, a, [role="menuitem"]) {
|
|
182
|
-
min-block-size: var(--control-size-lg);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
:is(.flyout, .flyout :where(li)) > :where(button, a, [role="menuitem"]):focus-visible {
|
|
186
|
-
background: var(--surface-subtle);
|
|
187
|
-
outline: var(--focus-outline);
|
|
188
|
-
outline-offset: var(--focus-outline-offset);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
:is(.flyout, .flyout :where(li))
|
|
192
|
-
> :where(button, a, [role="menuitem"]):is(:disabled, [aria-disabled="true"]) {
|
|
193
|
-
cursor: not-allowed;
|
|
194
|
-
opacity: var(--disabled-opacity);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
:is(.flyout, .flyout :where(li)) > :where(a, [role="menuitem"])[aria-disabled="true"] {
|
|
198
|
-
pointer-events: none;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
@media (hover: hover) {
|
|
202
|
-
:is(.flyout, .flyout :where(li))
|
|
203
|
-
> :where(button, a, [role="menuitem"]):hover:not(
|
|
204
|
-
:where(:focus-visible, :disabled, [aria-disabled="true"])
|
|
205
|
-
) {
|
|
206
|
-
background: var(--surface-subtle);
|
|
207
|
-
outline: none;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.flyout > hr,
|
|
212
|
-
.flyout > li > hr {
|
|
213
|
-
inline-size: 100%;
|
|
214
|
-
margin: 0;
|
|
215
|
-
margin-block: var(--space-1);
|
|
216
|
-
border: 0;
|
|
217
|
-
border-block-start: var(--border-width) solid var(--border);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
@media (forced-colors: active) {
|
|
221
|
-
.flyout {
|
|
222
|
-
border-color: ButtonText;
|
|
223
|
-
background: Canvas;
|
|
224
|
-
color: CanvasText;
|
|
225
|
-
box-shadow: none;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
:is(.flyout, .flyout :where(li)) > :where(button, a, [role="menuitem"]):focus-visible {
|
|
229
|
-
background: Canvas;
|
|
230
|
-
color: CanvasText;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
@media (hover: hover) {
|
|
234
|
-
:is(.flyout, .flyout :where(li))
|
|
235
|
-
> :where(button, a, [role="menuitem"]):hover:not(:where(:disabled, [aria-disabled="true"])) {
|
|
236
|
-
outline: var(--border-width) solid ButtonText;
|
|
237
|
-
outline-offset: -1px;
|
|
238
|
-
background: Canvas;
|
|
239
|
-
color: CanvasText;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
170
|
+
/* Vertical dividers — .menu-separator (menu.css) is the canonical way to
|
|
171
|
+
separate menu items. Flyout panels that are not menus use auto grid gap
|
|
172
|
+
declared on .flyout itself. */
|
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
* Cascade note: .join writes border-radius longhands on its direct children.
|
|
8
8
|
* Keep this file loaded after control/component styles so those corners win at
|
|
9
9
|
* equal specificity.
|
|
10
|
+
*
|
|
11
|
+
* Public hooks:
|
|
12
|
+
* --join-radius
|
|
13
|
+
*
|
|
14
|
+
* Internal:
|
|
15
|
+
* --join-ss
|
|
16
|
+
* --join-se
|
|
17
|
+
* --join-es
|
|
18
|
+
* --join-ee
|
|
19
|
+
* --control-border
|
|
20
|
+
* --control-bg
|
|
21
|
+
* --control-fg
|
|
10
22
|
*/
|
|
11
23
|
.join {
|
|
12
24
|
--join-radius: var(--radius);
|
|
@@ -34,7 +46,7 @@
|
|
|
34
46
|
display: inline-flex;
|
|
35
47
|
justify-content: center;
|
|
36
48
|
min-block-size: var(--control-size);
|
|
37
|
-
padding-inline: var(--space-
|
|
49
|
+
padding-inline: var(--space-30);
|
|
38
50
|
border: var(--border-width) solid var(--control-border);
|
|
39
51
|
border-radius: var(--radius);
|
|
40
52
|
background: var(--control-bg);
|
|
@@ -95,7 +107,7 @@
|
|
|
95
107
|
focus, and unsupported :has() browsers retain the control's normal ring. */
|
|
96
108
|
.join:has(> :is(.input, .textarea, .select):focus-visible) {
|
|
97
109
|
border-radius: var(--join-radius);
|
|
98
|
-
outline:
|
|
110
|
+
outline: 2px solid transparent;
|
|
99
111
|
box-shadow: var(--focus-ring-shadow);
|
|
100
112
|
}
|
|
101
113
|
|