actual-css 0.5.0 → 0.6.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 +17 -1
- package/dist/actual.css +1 -0
- package/dist/actual.full.css +480 -117
- package/dist/actual.full.js +1 -1
- package/dist/actual.full.min.css +1 -1
- package/dist/actual.min.css +1 -1
- package/docs/design-notes/browser-support.md +14 -14
- package/docs/design-notes/enhancement-contract.md +30 -13
- package/docs/design-notes/forced-colors.md +11 -7
- package/docs/design-notes/grid.md +4 -4
- package/docs/design-notes/naming.md +15 -9
- package/docs/design-notes/platform-alignment.md +9 -0
- package/docs/design-notes/references.md +4 -0
- package/docs/design-notes/steps.md +748 -0
- package/docs/design-notes/widget-primitives.md +32 -15
- package/docs/navigation.json +1 -0
- package/docs/pages/components/alert.md +13 -8
- package/docs/pages/components/aura.md +102 -6
- package/docs/pages/components/avatar.md +9 -6
- package/docs/pages/components/badge.md +11 -7
- package/docs/pages/components/button.md +17 -17
- package/docs/pages/components/card.md +15 -8
- package/docs/pages/components/chat.md +1 -1
- package/docs/pages/components/dialog.md +10 -7
- package/docs/pages/components/drawer.md +1 -1
- package/docs/pages/components/fab.md +12 -10
- package/docs/pages/components/indicator.md +6 -6
- package/docs/pages/components/list.md +11 -2
- package/docs/pages/components/navbar.md +1 -1
- package/docs/pages/components/pagination.md +1 -1
- package/docs/pages/components/rating.md +4 -4
- package/docs/pages/components/skeleton.md +1 -1
- package/docs/pages/components/spinner.md +1 -1
- package/docs/pages/components/steps.md +376 -52
- package/docs/pages/components/table.md +5 -5
- package/docs/pages/enhancements/flyout.md +12 -10
- package/docs/pages/enhancements/overview.md +2 -2
- package/docs/pages/enhancements/scrollspy.md +1 -1
- package/docs/pages/enhancements/tabs.md +1 -1
- package/docs/pages/examples/overview.md +2 -0
- package/docs/pages/forms/choice-cards.md +4 -4
- package/docs/pages/forms/combobox.md +87 -0
- package/docs/pages/forms/floating-field.md +5 -3
- package/docs/pages/forms/joined-controls.md +4 -4
- package/docs/pages/forms/labels.md +8 -5
- package/docs/pages/forms/overview.md +25 -18
- package/docs/pages/forms/password.md +3 -2
- package/docs/pages/forms/range.md +13 -2
- package/docs/pages/forms/states-and-sizes.md +6 -4
- package/docs/pages/forms/validation.md +13 -9
- package/docs/pages/foundations/tokens.md +9 -6
- package/docs/pages/foundations/typography.md +1 -1
- package/docs/pages/guides/bootstrap.md +3 -3
- package/docs/pages/guides/introduction.md +1 -1
- package/docs/pages/guides/modular-import.md +21 -10
- package/docs/pages/guides/progressive-enhancement.md +75 -54
- package/docs/pages/guides/tailwind.md +2 -2
- package/docs/pages/layout/app-shell.md +4 -4
- package/docs/pages/layout/choosing.md +10 -6
- package/docs/pages/layout/grid.md +11 -10
- package/docs/pages/layout/stack.md +10 -6
- package/docs/pages/patterns/structured-lists.md +7 -7
- package/docs/pages/utilities/accessibility.md +1 -1
- package/docs/pages/utilities/flex.md +20 -13
- package/docs/pages/utilities/links.md +1 -1
- package/docs/pages/utilities/list.md +1 -1
- package/docs/pages/utilities/overflow.md +14 -7
- package/docs/pages/utilities/overview.md +22 -0
- package/docs/pages/utilities/shape.md +1 -1
- package/docs/pages/utilities/sizing-wrapping.md +10 -8
- package/docs/pages/utilities/spacing.md +26 -19
- package/docs/pages/utilities/text.md +1 -1
- package/llms.txt +27 -4
- package/package.json +3 -2
- package/scripts/reserved-classes.json +4 -1
- package/src/css/components/fab.css +44 -8
- package/src/css/components/list.css +3 -1
- package/src/css/components/steps.css +277 -69
- package/src/css/core/tokens.css +1 -0
- package/src/css/effects/aura.css +101 -11
- package/src/css/forms/custom-select.css +1 -1
- package/src/css/forms/floating-field.css +8 -6
- package/src/css/layout/container-query.css +37 -13
- package/src/css/layout/grid.css +7 -7
- package/src/css/layout/index.css +1 -1
- package/src/js/password.js +1 -1
|
@@ -1,65 +1,389 @@
|
|
|
1
1
|
# Steps
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Progress through a short multi-step flow.
|
|
4
4
|
|
|
5
|
-
Use an `<ol>` because order is part of the meaning. Add `.complete` to
|
|
6
|
-
steps and `aria-current="step"` to
|
|
7
|
-
|
|
5
|
+
Use an `<ol>` because the order is part of the meaning. Add `.step-complete` to
|
|
6
|
+
finished steps and `aria-current="step"` to the current one. Unmarked steps are
|
|
7
|
+
upcoming.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
Orientation and labels are two independent choices.
|
|
10
|
+
|
|
11
|
+
`.steps` is the component; the orientation is a second class, and it is always
|
|
12
|
+
required:
|
|
13
|
+
|
|
14
|
+
| Markup | Orientation | Stages |
|
|
15
|
+
| ------------------------------------- | ----------- | -------- |
|
|
16
|
+
| `<ol class="steps steps-horizontal">` | horizontal | 2 to 5 |
|
|
17
|
+
| `<ol class="steps steps-vertical">` | vertical | no limit |
|
|
18
|
+
|
|
19
|
+
Neither orientation is the default, so `.steps` on its own is incomplete markup.
|
|
20
|
+
Everything a step *is* — `.step-label`, `.step-complete`, `aria-current="step"`,
|
|
21
|
+
the marker and its states — comes from `.steps` and is identical in both. The
|
|
22
|
+
second class only decides how the sequence is laid out.
|
|
23
|
+
|
|
24
|
+
For a horizontal sequence longer than five stages, use `.steps-vertical` or
|
|
25
|
+
another progression pattern.
|
|
26
|
+
|
|
27
|
+
Step labels are then the other choice, and it is **optional in either
|
|
28
|
+
orientation**. A sequence is either entirely labelled or entirely unlabelled:
|
|
29
|
+
|
|
30
|
+
| | Empty steps | `.step-label` on every step |
|
|
31
|
+
| -------------- | ------------------- | ------------------------------------- |
|
|
32
|
+
| **horizontal** | compact progression | named sequence, stacked or inline |
|
|
33
|
+
| **vertical** | compact rail | named sequence, labels beside markers |
|
|
34
|
+
|
|
35
|
+
- **Unlabelled steps are visual progress markers.** The surrounding interface
|
|
36
|
+
communicates the current step and position.
|
|
37
|
+
- **Labelled steps carry the sequence names themselves**, and may use
|
|
38
|
+
`a.step-label` for navigation. Actual CSS never hides an authored label to
|
|
39
|
+
solve a layout constraint.
|
|
40
|
+
|
|
41
|
+
The component needs no JavaScript.
|
|
14
42
|
|
|
15
43
|
**Related terms:** stepper, progress steps, step indicator, wizard steps, multi-step progress.
|
|
16
44
|
|
|
17
|
-
##
|
|
45
|
+
## Basic usage
|
|
46
|
+
|
|
47
|
+
```html demo
|
|
48
|
+
<ol class="steps steps-horizontal">
|
|
49
|
+
<li class="step-complete"><span class="step-label">Account</span></li>
|
|
50
|
+
<li aria-current="step"><span class="step-label">Payment</span></li>
|
|
51
|
+
<li><span class="step-label">Confirm</span></li>
|
|
52
|
+
</ol>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The three states stay distinct even without a checkmark:
|
|
56
|
+
|
|
57
|
+
- **Upcoming** — neutral marker
|
|
58
|
+
- **Complete** — filled marker and completed connector
|
|
59
|
+
- **Current** — outlined marker with a stronger ring
|
|
60
|
+
|
|
61
|
+
Only one step should use `aria-current="step"`.
|
|
62
|
+
|
|
63
|
+
The marker carries the state, so the label sits a notch below it: one size
|
|
64
|
+
smaller than body text, and neutral in weight. Only the current step's label is
|
|
65
|
+
emphasised — it is where you are now. A completed step needs no bold text; its
|
|
66
|
+
filled marker already says as much.
|
|
67
|
+
|
|
68
|
+
## Horizontal steps
|
|
69
|
+
|
|
70
|
+
`.steps-horizontal` is designed for **2 to 5 stages**.
|
|
71
|
+
|
|
72
|
+
### Without labels — visual progress only
|
|
73
|
+
|
|
74
|
+
Leave the items empty when the surrounding interface already says where the
|
|
75
|
+
user is. The row is then a drawn `3 / 5`, and the page carries the words:
|
|
76
|
+
|
|
77
|
+
```html demo
|
|
78
|
+
<div class="stack">
|
|
79
|
+
<hgroup>
|
|
80
|
+
<p class="overline">Step 3 of 5</p>
|
|
81
|
+
<h3>Validation</h3>
|
|
82
|
+
</hgroup>
|
|
83
|
+
|
|
84
|
+
<ol class="steps steps-horizontal" aria-hidden="true">
|
|
85
|
+
<li class="step-complete"></li>
|
|
86
|
+
<li class="step-complete"></li>
|
|
87
|
+
<li aria-current="step"></li>
|
|
88
|
+
<li></li>
|
|
89
|
+
<li></li>
|
|
90
|
+
</ol>
|
|
91
|
+
</div>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
●────────●────────③────────○────────○
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This form fits from phone width to desktop with no container query and no
|
|
99
|
+
variant class: with no label to make room for, a step only needs its marker.
|
|
100
|
+
|
|
101
|
+
The track runs edge to edge, so it lines up with the text around it. There is
|
|
102
|
+
no label to centre a marker against, so each marker takes the start of its own
|
|
103
|
+
share of the row and its connector fills the rest.
|
|
104
|
+
|
|
105
|
+
Hide it from assistive technology with `aria-hidden="true"`. A list of empty
|
|
106
|
+
`<li>`s whose numbers come from CSS is not a useful sequence to announce, and
|
|
107
|
+
the `hgroup` above already carries the accessible information — position and
|
|
108
|
+
step name. An unlabelled step is never interactive, so nothing focusable is
|
|
109
|
+
being hidden.
|
|
110
|
+
|
|
111
|
+
> An empty step means genuinely empty — no text, not even whitespace.
|
|
112
|
+
> `<li></li>` is a marker; `<li> </li>` is not. Same rule as `.badge:empty`.
|
|
18
113
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
| `[aria-current="step"]` | State | The current step: outlined marker. |
|
|
114
|
+
### With labels — the sequence carries the names
|
|
115
|
+
|
|
116
|
+
Add `.step-label` to every step when the stepper itself should expose the step
|
|
117
|
+
names, or when a step should be navigable:
|
|
24
118
|
|
|
25
119
|
```html demo
|
|
26
|
-
<ol class="steps">
|
|
27
|
-
<li class="complete">Account</li>
|
|
28
|
-
<li
|
|
29
|
-
<li>
|
|
120
|
+
<ol class="steps steps-horizontal" aria-label="Checkout progress">
|
|
121
|
+
<li class="step-complete"><span class="step-label">Account</span></li>
|
|
122
|
+
<li class="step-complete"><span class="step-label">Profile</span></li>
|
|
123
|
+
<li aria-current="step"><span class="step-label">Validation</span></li>
|
|
124
|
+
<li><span class="step-label">Payment</span></li>
|
|
30
125
|
</ol>
|
|
31
126
|
```
|
|
32
127
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
128
|
+
**Actual CSS never hides an authored step label.** Labels stay visible at every
|
|
129
|
+
width. If a labelled row does not fit its space, it scrolls — and the honest
|
|
130
|
+
answers to that are more room, fewer stages, or `.steps-vertical`.
|
|
131
|
+
|
|
132
|
+
Since scrolling is the fallback, a labelled row is worth pairing with
|
|
133
|
+
`.scroller`, which gives the native scrollbar the theme's density and colour
|
|
134
|
+
instead of the OS default:
|
|
135
|
+
|
|
136
|
+
```html
|
|
137
|
+
<ol class="steps steps-horizontal scroller">
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Steps does not apply it for you, because scrollbar treatment is an app-wide
|
|
141
|
+
decision rather than a per-component one. Every other scroll container —
|
|
142
|
+
`.table`, a `.flyout`, a scrolling `dialog` — leaves the scrollbar alone too,
|
|
143
|
+
so a page that thinned only its stepper would show two kinds of scrollbar. Put
|
|
144
|
+
`.scroller` on whatever scrolls, once. See the sizing and wrapping page for its
|
|
145
|
+
hooks.
|
|
146
|
+
|
|
147
|
+
Do not add `.stable-gutter` here. It reserves gutter on the inline axis, for a
|
|
148
|
+
vertical scrollbar this row never draws, so it narrows the row instead of
|
|
149
|
+
steadying its height.
|
|
150
|
+
|
|
151
|
+
### One presentation enhancement
|
|
152
|
+
|
|
153
|
+
With generous room, a labelled row moves marker and label inline and lets the
|
|
154
|
+
connector absorb the free space between groups:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
normal space
|
|
158
|
+
✓──────────2──────────3
|
|
159
|
+
Account Payment Confirm
|
|
160
|
+
|
|
161
|
+
generous space
|
|
162
|
+
✓ Account ───────── 2 Payment ───────── 3 Confirm
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Stacked is the baseline and is fully functional on its own. The inline form is
|
|
166
|
+
an enhancement, and it needs an `actual-container` size context the author
|
|
167
|
+
grants.
|
|
168
|
+
|
|
169
|
+
Resize the demo below. The 3-step flow needs less room than the supported
|
|
170
|
+
5-step maximum.
|
|
171
|
+
|
|
172
|
+
```html demo resize
|
|
173
|
+
<div class="stack">
|
|
174
|
+
<ol class="steps steps-horizontal container-query scroller" style="--step-complete-mark: '✓'">
|
|
175
|
+
<li class="step-complete"><span class="step-label">Identification</span></li>
|
|
176
|
+
<li aria-current="step"><span class="step-label">Confirmation</span></li>
|
|
177
|
+
<li><span class="step-label">Finalisation</span></li>
|
|
178
|
+
</ol>
|
|
179
|
+
|
|
180
|
+
<ol class="steps steps-horizontal container-query scroller" style="--step-complete-mark: '✓'">
|
|
181
|
+
<li class="step-complete"><span class="step-label">Account</span></li>
|
|
182
|
+
<li class="step-complete"><span class="step-label">Details</span></li>
|
|
183
|
+
<li aria-current="step"><span class="step-label">Payment</span></li>
|
|
184
|
+
<li><span class="step-label">Review</span></li>
|
|
185
|
+
<li><span class="step-label">Confirm</span></li>
|
|
186
|
+
</ol>
|
|
187
|
+
</div>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`.container-query` is only a convenience helper. You can grant the same shared
|
|
191
|
+
context in your own CSS:
|
|
192
|
+
|
|
193
|
+
```css
|
|
194
|
+
.checkout-steps {
|
|
195
|
+
container: actual-container / inline-size;
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
A named wrapper works too; the stepper responds to the nearest
|
|
200
|
+
`actual-container` region.
|
|
201
|
+
|
|
202
|
+
One threshold decides it: from **60rem**, a labelled row goes inline; below it,
|
|
203
|
+
stacked. That is calibrated on five stages, the widest supported row, because
|
|
204
|
+
it is where a five-stage row still leaves its connector a real region rather
|
|
205
|
+
than a stub. Inline is a bonus for generous room, so switching late costs
|
|
206
|
+
nothing, and the same threshold then serves every stage count.
|
|
207
|
+
|
|
208
|
+
The step count changes nothing else. Whether a row has two stages or five, its
|
|
209
|
+
labels stay visible and it scrolls if it must.
|
|
210
|
+
|
|
211
|
+
Without an `actual-container`, or without container-query / `:has()` support,
|
|
212
|
+
the stacked layout remains fully functional. The unlabelled form needs neither:
|
|
213
|
+
it is compact by structure, not by query.
|
|
214
|
+
|
|
215
|
+
> `.container-query` uses inline-size containment. Put it where width comes from
|
|
216
|
+
> the layout context, not on a shrink-to-fit box. See the container-query helper
|
|
217
|
+
> for the full containment guidance.
|
|
218
|
+
|
|
219
|
+
## Vertical steps
|
|
220
|
+
|
|
221
|
+
Vertical steps are an explicit orientation, not a mobile fallback, and they are
|
|
222
|
+
not bound by the horizontal 2–5 stage limit.
|
|
223
|
+
|
|
224
|
+
Use `.steps steps-vertical` when the surrounding layout is naturally vertical —
|
|
225
|
+
for example a wizard sidebar or a narrow process panel. It is a peer of
|
|
226
|
+
`.steps-horizontal`, not a modifier on it: never write the two together.
|
|
227
|
+
|
|
228
|
+
```html demo
|
|
229
|
+
<ol class="steps steps-vertical" style="--step-complete-mark: '✓'">
|
|
230
|
+
<li class="step-complete"><span class="step-label">Basic details</span></li>
|
|
231
|
+
<li class="step-complete"><span class="step-label">Company details</span></li>
|
|
232
|
+
<li aria-current="step"><span class="step-label">Subscription plan</span></li>
|
|
233
|
+
<li><span class="step-label">Payment details</span></li>
|
|
234
|
+
</ol>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The state model is identical to horizontal steps. The composition is simply
|
|
238
|
+
different: markers form a vertical track and labels sit beside them.
|
|
239
|
+
|
|
240
|
+
### A compact rail
|
|
241
|
+
|
|
242
|
+
Leaving the items empty works here too, and gives a marker rail — useful for a
|
|
243
|
+
narrow sticky sidebar next to content that names the step:
|
|
244
|
+
|
|
245
|
+
```html demo
|
|
246
|
+
<div class="cluster">
|
|
247
|
+
<ol class="steps steps-vertical" aria-hidden="true">
|
|
248
|
+
<li class="step-complete"></li>
|
|
249
|
+
<li class="step-complete"></li>
|
|
250
|
+
<li aria-current="step"></li>
|
|
251
|
+
<li></li>
|
|
252
|
+
<li></li>
|
|
253
|
+
</ol>
|
|
254
|
+
|
|
255
|
+
<hgroup>
|
|
256
|
+
<p class="overline">Step 3 of 5</p>
|
|
257
|
+
<h3>Validation</h3>
|
|
258
|
+
</hgroup>
|
|
259
|
+
</div>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The rail is exactly as wide as its markers, so it costs nothing in a
|
|
263
|
+
shrink-to-fit column.
|
|
264
|
+
|
|
265
|
+
Vertical steps stay vertical at every width. The container query only refines
|
|
266
|
+
the horizontal orientation.
|
|
267
|
+
|
|
268
|
+
There is no fixed stage count for the vertical orientation. A longer sequence is
|
|
269
|
+
fine as long as it remains useful and readable in its surrounding layout.
|
|
270
|
+
|
|
271
|
+
## Connectors
|
|
272
|
+
|
|
273
|
+
Steps uses a line between markers by default.
|
|
274
|
+
|
|
275
|
+
`--step-connector` controls the default horizontal connector background. It
|
|
276
|
+
accepts a complete CSS background value, so a theme can replace the line with a
|
|
277
|
+
gradient, image or nothing at all.
|
|
278
|
+
|
|
279
|
+
In the wide horizontal representation, the connector expands into the free
|
|
280
|
+
space between marker + label groups. A theme can replace only that representation
|
|
281
|
+
with `--step-inline-connector`, for example a custom chevron SVG:
|
|
282
|
+
|
|
283
|
+
```css
|
|
284
|
+
.checkout-steps {
|
|
285
|
+
--step-inline-connector:
|
|
286
|
+
url("../icons/chevron.svg") center / 1rem 1rem no-repeat;
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Vertical steps have no connector hook of their own. The vertical geometry is
|
|
291
|
+
different, so a horizontal value cannot transpose onto it — override
|
|
292
|
+
`.steps-vertical > li::after` directly if a design ever needs to.
|
|
293
|
+
|
|
294
|
+
Connectors are decorative. The ordered list and its labels carry the meaning of
|
|
295
|
+
the sequence.
|
|
296
|
+
|
|
297
|
+
## Navigation
|
|
298
|
+
|
|
299
|
+
Steps are informational by default, and **only a labelled step can be
|
|
300
|
+
navigable**: navigation is expressed by making a `.step-label` an `<a href>`.
|
|
301
|
+
Markers are never interactive, so an unlabelled row is visual progress and
|
|
302
|
+
nothing more.
|
|
303
|
+
|
|
304
|
+
The `<a href>` is the whole interactive surface: a `<button>` or any other
|
|
305
|
+
focusable element inside a step is outside the component contract. Only make a
|
|
306
|
+
label a link when the workflow genuinely allows navigation to that step:
|
|
307
|
+
|
|
308
|
+
```html demo resize
|
|
309
|
+
<ol class="steps steps-horizontal container-query scroller">
|
|
310
|
+
<li class="step-complete">
|
|
311
|
+
<a class="step-label" href="#">Account</a>
|
|
312
|
+
</li>
|
|
313
|
+
<li class="step-complete">
|
|
314
|
+
<a class="step-label" href="#">Details</a>
|
|
315
|
+
</li>
|
|
316
|
+
<li aria-current="step">
|
|
317
|
+
<span class="step-label">Payment</span>
|
|
318
|
+
</li>
|
|
319
|
+
<li>
|
|
320
|
+
<span class="step-label">Confirm</span>
|
|
321
|
+
</li>
|
|
322
|
+
</ol>
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Keep `aria-current="step"` on the current `<li>`.
|
|
326
|
+
|
|
327
|
+
A step link keeps the colour of its own state rather than the theme's `--link`,
|
|
328
|
+
so the marker states stay the strongest signal in the row. Its underline, hover
|
|
329
|
+
and focus ring are untouched — that is what marks it as navigable. If a touch
|
|
330
|
+
target needs to be more generous, put `.touch-target` on the anchor rather than
|
|
331
|
+
growing the stepper.
|
|
332
|
+
|
|
333
|
+
## Hooks
|
|
334
|
+
|
|
335
|
+
On `.steps`, so both orientations read them:
|
|
336
|
+
|
|
337
|
+
- `--step-size` — marker diameter
|
|
338
|
+
- `--step-inline-gap` — spacing between marker, label and connector inline
|
|
339
|
+
- `--step-line-size` — connector thickness
|
|
340
|
+
- `--step-marker-radius` — marker corner radius
|
|
341
|
+
- `--step-complete-mark` — content used instead of the number on completed steps
|
|
342
|
+
|
|
343
|
+
`.steps-horizontal` only:
|
|
344
|
+
|
|
345
|
+
- `--step-min` — minimum item width in the stacked horizontal layout
|
|
346
|
+
- `--step-gap` — marker-to-label space in the stacked horizontal layout
|
|
347
|
+
- `--step-connector` — default horizontal connector background
|
|
348
|
+
- `--step-inline-connector` — optional connector background for wide horizontal steps
|
|
349
|
+
|
|
350
|
+
`.steps-vertical` only:
|
|
351
|
+
|
|
352
|
+
- `--step-vertical-gap` — space between vertical steps
|
|
353
|
+
|
|
354
|
+
## Notes
|
|
355
|
+
|
|
356
|
+
Do not mix labelled and unlabelled steps in one sequence. Each step is sized on
|
|
357
|
+
its own content, so a mixed sequence renders a narrow marker between reading-
|
|
358
|
+
width steps — it lays out, but it reads as a gap rather than as progress.
|
|
359
|
+
|
|
360
|
+
A step name belongs in a `.step-label`. Bare text in an `<li>` is outside the
|
|
361
|
+
contract: it is content, so it gets a reading width like a label, but no rule
|
|
362
|
+
places or aligns it.
|
|
363
|
+
|
|
364
|
+
The **2 to 5** range applies to the horizontal orientation, and the inline
|
|
365
|
+
threshold is calibrated for it. A longer horizontal sequence is out of
|
|
366
|
+
contract: it still renders, but the geometry was never designed for that count.
|
|
367
|
+
|
|
368
|
+
The vertical orientation has no equivalent hard limit; its practical limit is
|
|
369
|
+
the surrounding layout and whether the sequence remains useful to scan.
|
|
370
|
+
|
|
371
|
+
An unlabelled sequence intentionally leaves presentation of the current step
|
|
372
|
+
name to the surrounding interface. If a narrow layout needs every step name
|
|
373
|
+
visible at once, a labelled `.steps-vertical` is usually the better
|
|
374
|
+
composition.
|
|
375
|
+
|
|
376
|
+
In Windows forced-colors mode the accent fill is dropped, so a completed marker
|
|
377
|
+
and an upcoming one both render as a ringed disc with a number. Set
|
|
378
|
+
`--step-complete-mark` — a checkmark, for instance — if your flow needs the two
|
|
379
|
+
to stay distinguishable there. Steps deliberately ships no forced-colors
|
|
380
|
+
override of its own: painting the marker `Highlight` makes the number or glyph
|
|
381
|
+
inside it unreadable, which is worse than the ambiguity it removes.
|
|
382
|
+
|
|
383
|
+
The inline threshold is calibrated to the default `--step-min`. Container
|
|
384
|
+
queries cannot read custom properties, so changing `--step-min` moves the
|
|
385
|
+
scroll budget but not the threshold.
|
|
386
|
+
|
|
387
|
+
See [Steps representations and thresholds](https://github.com/lekoala/actual-css/blob/master/docs/design-notes/steps.md)
|
|
388
|
+
for why the contract is shaped this way, and which alternatives were measured
|
|
389
|
+
and rejected.
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
|
|
13
13
|
## Class reference
|
|
14
14
|
|
|
15
|
-
| Class
|
|
16
|
-
|
|
17
|
-
| `.table-wrap`
|
|
18
|
-
| `.table`
|
|
19
|
-
| `.table.compact
|
|
15
|
+
| Class | Kind | Description |
|
|
16
|
+
| ---------------- | --------- | ------------------------------------------------------------ |
|
|
17
|
+
| `.table-wrap` | Component | Scroll container and outer chrome (surface, border, radius). |
|
|
18
|
+
| `.table` | Component | The table itself; row and cell rules. |
|
|
19
|
+
| `.table.compact` | Density | Tighter cell padding; typography is unchanged. |
|
|
20
20
|
|
|
21
21
|
## Basic usage
|
|
22
22
|
|
|
@@ -6,16 +6,18 @@
|
|
|
6
6
|
|
|
7
7
|
## Class reference
|
|
8
8
|
|
|
9
|
-
| Class | Kind | Description
|
|
10
|
-
|
|
11
|
-
| `.flyout-trigger` | Composition | Positioning wrapper for
|
|
12
|
-
| `.stretch` | Modifier |
|
|
13
|
-
| `.flyout` | Component | Floating
|
|
14
|
-
| `.menu` | Component | Action-list primitive
|
|
15
|
-
| `.menu-item` | Component | One action row;
|
|
16
|
-
| `.menu-item-icon` | Slot | Fixed leading column for
|
|
17
|
-
| `.menu-item-text` | Slot | Flexible label column; truncates
|
|
18
|
-
| `.menu-item-end` | Slot | Trailing
|
|
9
|
+
| Class | Kind | Description |
|
|
10
|
+
| ----------------- | ----------- | ------------------------------------------- |
|
|
11
|
+
| `.flyout-trigger` | Composition | Positioning wrapper for trigger and panel. |
|
|
12
|
+
| `.stretch` | Modifier | Spans a `.flyout-trigger` to its container. |
|
|
13
|
+
| `.flyout` | Component | Floating surface, positioned by JavaScript. |
|
|
14
|
+
| `.menu` | Component | Action-list primitive. |
|
|
15
|
+
| `.menu-item` | Component | One action row; joins roving focus. |
|
|
16
|
+
| `.menu-item-icon` | Slot | Fixed leading column for an icon. |
|
|
17
|
+
| `.menu-item-text` | Slot | Flexible label column; truncates. |
|
|
18
|
+
| `.menu-item-end` | Slot | Trailing shortcut, badge or status. |
|
|
19
|
+
|
|
20
|
+
`.menu` has a strict `.menu > li > .menu-item` anatomy.
|
|
19
21
|
| `.menu-label` | Variant | Muted section heading inside a menu; not interactive. |
|
|
20
22
|
| `.menu-separator` | Variant | Divider between menu groups (`<hr role="separator">`). |
|
|
21
23
|
| `.sm` / `.lg` | Variant | Compact or large density. |
|
|
@@ -15,7 +15,7 @@ class API, shared tokens, and progressive enhancement.
|
|
|
15
15
|
|
|
16
16
|
## Modules
|
|
17
17
|
|
|
18
|
-
The full runtime is `actual-css/js`. Each enhancer is also importable on its own
|
|
18
|
+
The full runtime is `actual-css/js/full`. Each enhancer is also importable on its own
|
|
19
19
|
for projects that use custom components or want a smaller behavior surface:
|
|
20
20
|
|
|
21
21
|
```js
|
|
@@ -32,5 +32,5 @@ is a no-op until the module is loaded again with a DOM.
|
|
|
32
32
|
|
|
33
33
|
Each interactive component has its own page documenting the exact markup its
|
|
34
34
|
enhancement expects: Dialog, Drawer, Flyout, Tooltip, Tabs, Scrollspy, and
|
|
35
|
-
Status Bar. The
|
|
35
|
+
Status Bar. The full runtime is loaded on the docs pages, so the examples
|
|
36
36
|
work with the documented markup alone.
|
|
@@ -9,7 +9,7 @@ or style `[aria-current]` yourself.
|
|
|
9
9
|
## Class reference
|
|
10
10
|
|
|
11
11
|
| Class | Kind | Description |
|
|
12
|
-
|
|
12
|
+
| ------------ | ----------- | --------------------------------------------------------------- |
|
|
13
13
|
| `.scrollspy` | Component | Marks the nav region for the enhancer; adds no visual styles. |
|
|
14
14
|
| `.nav-list` | Composition | Vertical list of navigation links. |
|
|
15
15
|
| `.nav-link` | Component | Navigation link whose active state comes from `[aria-current]`. |
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
## Class reference
|
|
6
6
|
|
|
7
7
|
| Class | Kind | Description |
|
|
8
|
-
|
|
8
|
+
| ---------- | --------- | -------------------------------------------- |
|
|
9
9
|
| `.tabs` | Component | Tab strip; pairs with `role="tablist"`. |
|
|
10
10
|
| `.tab` | Component | One tab trigger; pairs with `role="tab"`. |
|
|
11
11
|
| `.primary` | Intent | Tints the selected tab's indicator and text. |
|
|
@@ -22,6 +22,8 @@ and `actual.full.js` from `dist/`, plus the theme palettes bundle from
|
|
|
22
22
|
- [Layout reference](../../demo/templates/layouts.html) - canonical compositions built only with the layout primitives
|
|
23
23
|
- [Grid density](../../demo/templates/grid.html) - the grid contracts on resizable stages, with the pitfalls called out
|
|
24
24
|
- [Density](../../demo/templates/density.html) - compact control density
|
|
25
|
+
- [Data grid](../../demo/templates/data-grid.html) - an external data grid component themed with Actual tokens (sort, filter, search, selection)
|
|
26
|
+
- [Combobox](../../demo/templates/combobox.html) - an external combobox themed with Actual tokens (search, tags, autocomplete)
|
|
25
27
|
|
|
26
28
|
## Sites
|
|
27
29
|
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
## Class reference
|
|
6
6
|
|
|
7
|
-
| Class | Kind | Description
|
|
8
|
-
|
|
9
|
-
| `.choice-card` | Component | Card-style `<label>`
|
|
10
|
-
| `.primary` / `.secondary` | Intent |
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
| ------------------------- | --------- | --------------------------------------------- |
|
|
9
|
+
| `.choice-card` | Component | Card-style `<label>` around a native control. |
|
|
10
|
+
| `.primary` / `.secondary` | Intent | Accent for the selected state. |
|
|
11
11
|
|
|
12
12
|
- Use `.choice-card` on a `<label>` wrapping a native `<input type="radio">` or `<input type="checkbox">`. The input is visually hidden; in browsers without `:has()` it stays visible so selection state never disappears.
|
|
13
13
|
- Selected items show a primary border, subtle background tint, and a checkmark badge at the top-right corner — round for radio, rounded square for checkbox.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Combobox
|
|
2
|
+
|
|
3
|
+
> A searchable or multi-value combobox is not shipped by the framework — the native `<select>` and `<datalist>` stay the baseline. Theme an external combobox with Actual tokens instead.
|
|
4
|
+
|
|
5
|
+
The `.select` class keeps the native baseline with a CSS chevron, and the optional
|
|
6
|
+
`custom-select` module adds the `appearance: base-select` native picker where the
|
|
7
|
+
browser supports it. Beyond those, apply the framework's judgment from the
|
|
8
|
+
[data grid template](../../demo/templates/data-grid.html) to the problem: when a
|
|
9
|
+
real product needs a JavaScript combobox (searchable select, removable tags,
|
|
10
|
+
autocomplete suggestions), load a dedicated component and bridge its custom
|
|
11
|
+
properties onto Actual's tokens.
|
|
12
|
+
|
|
13
|
+
**Related terms:** combo box, combobox, autocomplete, datalist, searchable select, enhanced select, multiple select, tags, chips, tag input, pill input.
|
|
14
|
+
|
|
15
|
+
## Theme bridge
|
|
16
|
+
|
|
17
|
+
The [combobox template](../../demo/templates/combobox.html) themes
|
|
18
|
+
[`@lekoala/combobox`](https://github.com/lekoala/combobox) entirely with Actual
|
|
19
|
+
tokens: the control mirrors `.input`, chips re-derive the `.badge` soft recipe,
|
|
20
|
+
and the picker popover follows `--surface-raised` and `--shadow-popout`. No
|
|
21
|
+
adapter, no compatibility layer — a handful of `--cb-*` assignments and shared
|
|
22
|
+
mix tokens.
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<label class="field actual-combobox">
|
|
26
|
+
<span class="field-label">Skills</span>
|
|
27
|
+
<combo-box placeholder="Search or add a skill…">
|
|
28
|
+
<select class="select" name="skills[]" multiple>
|
|
29
|
+
<option value="design" selected>Design</option>
|
|
30
|
+
<option value="css" selected>CSS</option>
|
|
31
|
+
<option value="javascript" selected>JavaScript</option>
|
|
32
|
+
</select>
|
|
33
|
+
</combo-box>
|
|
34
|
+
</label>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The card in the template documents the full token map of this recipe.
|
|
38
|
+
|
|
39
|
+
## Lightweight pass-through
|
|
40
|
+
|
|
41
|
+
Most of the skin is three one-line token bridges. The visible vocabulary —
|
|
42
|
+
surface, border, radius, focus ring, danger, hover overlay and the `--soft-*`
|
|
43
|
+
mix — stays the Actual one, so light/dark mode, the preset themes and their
|
|
44
|
+
contrast contracts apply to the combobox for free:
|
|
45
|
+
|
|
46
|
+
```css
|
|
47
|
+
.actual-combobox {
|
|
48
|
+
--cb-bg: var(--surface);
|
|
49
|
+
--cb-color: var(--text);
|
|
50
|
+
--cb-border-color: var(--border);
|
|
51
|
+
--cb-border-radius: var(--radius);
|
|
52
|
+
--cb-focus-color: var(--focus);
|
|
53
|
+
--cb-muted-color: var(--text-muted);
|
|
54
|
+
--cb-error-color: var(--danger);
|
|
55
|
+
--cb-chip-bg: transparent;
|
|
56
|
+
--cb-control-height: var(--control-size);
|
|
57
|
+
--cb-option-min-height: var(--control-size);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.actual-combobox .cb-control:focus-within,
|
|
61
|
+
.actual-combobox .cb-text-control:focus {
|
|
62
|
+
outline: 2px solid transparent;
|
|
63
|
+
box-shadow: var(--focus-ring-shadow);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.actual-combobox .cb-chip-remove:focus-visible {
|
|
67
|
+
outline: 2px solid transparent;
|
|
68
|
+
box-shadow: 0 0 0 2px var(--focus-ring);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.actual-combobox .cb-chip {
|
|
72
|
+
border: var(--border-width) solid
|
|
73
|
+
color-mix(in oklab, var(--surface) var(--soft-border-mix), var(--primary));
|
|
74
|
+
border-radius: var(--radius-full);
|
|
75
|
+
background: color-mix(in oklab, var(--surface) var(--soft-bg-mix), var(--primary));
|
|
76
|
+
color: color-mix(in oklab, var(--primary) var(--soft-fg-mix), var(--text));
|
|
77
|
+
font-size: var(--font-size-xs);
|
|
78
|
+
font-weight: var(--font-weight-strong);
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The composite focus ring follows any internal focus, not just the search
|
|
83
|
+
input: focus a chip or its remove × and the control shows the same field ring,
|
|
84
|
+
with the local `:focus-visible` indicator on the chip or its × on top.
|
|
85
|
+
|
|
86
|
+
The same approach works for any widget that exposes a custom-property skin —
|
|
87
|
+
keep the widget's behavior, restyle its tokens through the shared vocabulary.
|
|
@@ -7,9 +7,11 @@ the label rests inside the control and floats to the top when the control is
|
|
|
7
7
|
focused or filled. It composes the existing `.field` layout and the text
|
|
8
8
|
controls (`.input`, `.textarea`, `.select`) with zero JavaScript.
|
|
9
9
|
|
|
10
|
-
The cell holds
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
The cell holds exactly one control and its label, with the control before the
|
|
11
|
+
label. Label placement is linked through the general sibling combinator, so an
|
|
12
|
+
injected node between the two (a password manager, an extension wrapper) is
|
|
13
|
+
tolerated. Help and error messages stay in the surrounding `.field`, otherwise
|
|
14
|
+
the resting label centers on the whole field instead of the control.
|
|
13
15
|
|
|
14
16
|
```html demo
|
|
15
17
|
<div class="field">
|