actual-css 0.3.1 → 0.4.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 +109 -3
- package/README.md +35 -30
- package/dist/actual.css +66 -4958
- package/dist/actual.full.css +7548 -0
- package/dist/actual.full.js +1 -0
- package/dist/actual.full.min.css +1 -0
- package/dist/actual.js +1 -1
- package/dist/actual.min.css +1 -1
- package/docs/design-notes/app-ui.md +33 -0
- package/docs/design-notes/cascade-layer.md +34 -13
- package/docs/design-notes/column-layout.md +677 -0
- package/docs/design-notes/enhancement-contract.md +25 -0
- package/docs/design-notes/forced-colors.md +3 -0
- package/docs/design-notes/grid.md +785 -0
- package/docs/design-notes/naming.md +15 -0
- package/docs/design-notes/references.md +1 -1
- package/docs/design-notes/widget-primitives.md +1 -0
- package/docs/navigation.json +12 -2
- package/docs/pages/components/alert.md +21 -14
- package/docs/pages/components/app-navigation.md +34 -0
- package/docs/pages/components/aura.md +1 -1
- package/docs/pages/components/avatar.md +16 -6
- package/docs/pages/components/badge.md +9 -7
- package/docs/pages/components/button.md +46 -16
- package/docs/pages/components/card.md +17 -9
- package/docs/pages/components/chat.md +8 -8
- package/docs/pages/components/dialog.md +7 -7
- package/docs/pages/components/drawer.md +3 -3
- package/docs/pages/components/fab.md +9 -7
- package/docs/pages/components/indicator.md +52 -0
- package/docs/pages/components/list.md +62 -0
- package/docs/pages/components/navbar.md +15 -8
- package/docs/pages/components/pagination.md +4 -3
- package/docs/pages/components/rating.md +68 -0
- package/docs/pages/components/skeleton.md +4 -4
- package/docs/pages/components/spinner.md +5 -5
- package/docs/pages/components/steps.md +57 -0
- package/docs/pages/components/table.md +30 -5
- package/docs/pages/enhancements/flyout.md +15 -15
- package/docs/pages/enhancements/overview.md +1 -1
- package/docs/pages/enhancements/scrollspy.md +6 -6
- package/docs/pages/enhancements/status-bar.md +5 -1
- package/docs/pages/enhancements/tabs.md +7 -8
- package/docs/pages/enhancements/tooltip.md +1 -1
- package/docs/pages/examples/overview.md +47 -22
- package/docs/pages/forms/choice-cards.md +11 -6
- package/docs/pages/forms/controls.md +1 -1
- package/docs/pages/forms/detached-actions.md +1 -1
- package/docs/pages/forms/floating-field.md +10 -5
- package/docs/pages/forms/form-actions.md +1 -1
- package/docs/pages/forms/input-policy.md +1 -1
- package/docs/pages/forms/joined-controls.md +4 -4
- package/docs/pages/forms/labels.md +6 -6
- package/docs/pages/forms/otp.md +33 -1
- package/docs/pages/forms/overview.md +19 -19
- package/docs/pages/forms/password.md +1 -1
- package/docs/pages/forms/range.md +1 -1
- package/docs/pages/forms/states-and-sizes.md +44 -48
- package/docs/pages/forms/sticky-actions.md +3 -3
- package/docs/pages/forms/switch.md +110 -2
- package/docs/pages/forms/validation.md +9 -9
- package/docs/pages/foundations/philosophy.md +1 -1
- package/docs/pages/foundations/theming.md +17 -2
- package/docs/pages/foundations/tokens.md +22 -10
- package/docs/pages/foundations/typography.md +50 -20
- package/docs/pages/guides/bootstrap.md +11 -11
- package/docs/pages/guides/integrating-actual-css.md +192 -0
- package/docs/pages/guides/introduction.md +23 -26
- package/docs/pages/guides/modular-import.md +173 -0
- package/docs/pages/guides/progressive-enhancement.md +81 -78
- package/docs/pages/guides/tailwind.md +6 -8
- package/docs/pages/layout/app-layout.md +57 -0
- package/docs/pages/layout/app-shell.md +28 -7
- package/docs/pages/layout/center.md +12 -1
- package/docs/pages/layout/choosing.md +54 -0
- package/docs/pages/layout/column-layout.md +206 -0
- package/docs/pages/layout/frame.md +6 -1
- package/docs/pages/layout/grid.md +133 -102
- package/docs/pages/layout/media.md +1 -1
- package/docs/pages/layout/overview.md +15 -2
- package/docs/pages/layout/scroll-snap.md +2 -2
- package/docs/pages/layout/scroll-target.md +45 -0
- package/docs/pages/layout/sidebar-layout.md +38 -18
- package/docs/pages/layout/stack.md +70 -1
- package/docs/pages/layout/switcher.md +10 -26
- package/docs/pages/layout/topbar.md +2 -2
- package/docs/pages/patterns/actions.md +1 -1
- package/docs/pages/patterns/code-block.md +1 -1
- package/docs/pages/patterns/exclusive-accordion.md +1 -1
- package/docs/pages/patterns/hierarchical-nav.md +1 -1
- package/docs/pages/patterns/icon-input.md +1 -1
- package/docs/pages/patterns/icon-slot.md +61 -0
- package/docs/pages/patterns/intent-nesting.md +1 -1
- package/docs/pages/patterns/navigation-list.md +1 -1
- package/docs/pages/patterns/overview.md +1 -1
- package/docs/pages/patterns/structured-lists.md +38 -40
- package/docs/pages/utilities/accessibility.md +3 -3
- package/docs/pages/utilities/flex.md +15 -15
- package/docs/pages/utilities/links.md +4 -4
- package/docs/pages/utilities/list.md +8 -8
- package/docs/pages/utilities/overflow.md +8 -8
- package/docs/pages/utilities/overview.md +1 -1
- package/docs/pages/utilities/shape.md +3 -3
- package/docs/pages/utilities/sizing-wrapping.md +23 -16
- package/docs/pages/utilities/spacing.md +20 -20
- package/docs/pages/utilities/text.md +10 -10
- package/llms.txt +46 -4
- package/package.json +43 -13
- package/scripts/reserved-classes.json +278 -0
- package/src/cli/actual-css.js +133 -0
- package/src/css/actual.css +1 -31
- package/src/css/actual.full.css +11 -2
- package/src/css/components/alert.css +17 -4
- package/src/css/components/app-nav.css +76 -0
- package/src/css/components/avatar.css +4 -0
- package/src/css/components/badge.css +19 -19
- package/src/css/components/breadcrumb.css +1 -1
- package/src/css/components/button.css +20 -32
- package/src/css/components/card.css +34 -9
- package/src/css/{optional → components}/chat.css +0 -6
- package/src/css/components/drawer.css +24 -5
- package/src/css/{optional → components}/fab.css +1 -7
- package/src/css/components/flyout.css +5 -0
- package/src/css/components/index.css +37 -27
- package/src/css/components/indicator.css +47 -0
- package/src/css/components/join.css +8 -1
- package/src/css/components/key.css +2 -0
- package/src/css/components/list.css +83 -0
- package/src/css/components/menu.css +11 -8
- package/src/css/components/meter.css +4 -1
- package/src/css/components/modal.css +5 -17
- package/src/css/components/navbar.css +6 -15
- package/src/css/components/pagination.css +11 -0
- package/src/css/components/rating.css +101 -0
- package/src/css/components/spinner.css +5 -0
- package/src/css/components/status-bar.css +5 -0
- package/src/css/components/steps.css +122 -0
- package/src/css/components/surface.css +5 -0
- package/src/css/components/tab.css +20 -22
- package/src/css/components/table.css +6 -0
- package/src/css/components/tooltip.css +3 -7
- package/src/css/{focus.css → core/focus.css} +0 -8
- package/src/css/core/index.css +9 -0
- package/src/css/core/print.css +18 -0
- package/src/css/{theme.css → core/theme.css} +19 -19
- package/src/css/{tokens.css → core/tokens.css} +16 -4
- package/src/css/{variants.css → core/variants.css} +3 -2
- package/src/css/{optional → effects}/aura.css +1 -10
- package/src/css/effects/index.css +2 -0
- package/src/css/forms/base.css +8 -0
- package/src/css/forms/choice-card.css +7 -15
- package/src/css/forms/choice.css +49 -37
- package/src/css/forms/control.css +4 -1
- package/src/css/forms/custom-select.css +2 -0
- package/src/css/{optional → forms}/floating-field.css +25 -7
- package/src/css/forms/index.css +10 -13
- package/src/css/forms/native.css +15 -2
- package/src/css/{optional → forms}/otp.css +25 -16
- package/src/css/forms/range.css +14 -4
- package/src/css/forms/switch.css +31 -29
- package/src/css/layout/app-layout.css +102 -0
- package/src/css/layout/app-shell.css +6 -0
- package/src/css/layout/center.css +14 -0
- package/src/css/layout/cluster.css +21 -0
- package/src/css/layout/column-layout.css +144 -0
- package/src/css/layout/container-query.css +15 -0
- package/src/css/layout/frame.css +19 -0
- package/src/css/layout/grid.css +155 -0
- package/src/css/layout/index.css +44 -0
- package/src/css/layout/measure.css +9 -0
- package/src/css/layout/media.css +10 -0
- package/src/css/layout/scroll-target.css +15 -0
- package/src/css/layout/scroller.css +41 -0
- package/src/css/layout/sidebar-layout.css +52 -0
- package/src/css/layout/stack.css +21 -0
- package/src/css/layout/switcher.css +23 -0
- package/src/css/{optional/layout-extra.css → layout/topbar.css} +0 -20
- package/src/css/typography/index.css +5 -0
- package/src/css/typography/lead.css +7 -0
- package/src/css/{components → typography}/overline.css +2 -2
- package/src/css/{prose.css → typography/prose.css} +57 -38
- package/src/css/{utilities.css → utilities/base.css} +2 -0
- package/src/css/utilities/index.css +3 -0
- package/src/js/escape.js +36 -0
- package/src/js/flyout.js +22 -12
- package/src/js/full.js +26 -0
- package/src/js/index.js +5 -21
- package/src/js/surface.js +1 -31
- package/src/js/tooltip.js +48 -19
- package/src/js/validation.js +1 -1
- package/src/tooling/css-bundle.js +308 -0
- package/dist/actual-themes.min.css +0 -1
- package/dist/optional.css +0 -1048
- package/dist/optional.min.css +0 -1
- package/docs/pages/guides/optional-components.md +0 -33
- package/docs/pages/layout/list.md +0 -41
- package/src/css/grid.css +0 -109
- package/src/css/layout.css +0 -123
- package/src/css/optional/index.css +0 -10
- package/src/css/optional/scroller.css +0 -63
- package/src/css/print.css +0 -47
- package/src/css/themes/corporate.css +0 -60
- package/src/css/themes/cyberpunk.css +0 -60
- package/src/css/themes/dim.css +0 -33
- package/src/css/themes/edge.css +0 -117
- package/src/css/themes/forest.css +0 -65
- package/src/css/themes/gradient.css +0 -97
- package/src/css/themes/index.css +0 -47
- package/src/css/themes/indigo.css +0 -33
- package/src/css/themes/lavender.css +0 -66
- package/src/css/themes/mono.css +0 -60
- package/src/css/themes/neon.css +0 -66
- package/src/css/themes/ocean.css +0 -60
- package/src/css/themes/petrol.css +0 -64
- package/src/css/themes/spruce.css +0 -64
- package/src/css/themes/square.css +0 -65
- package/src/css/themes/sunset.css +0 -66
- /package/src/css/{base.css → core/base.css} +0 -0
- /package/src/css/{intents.css → core/intents.css} +0 -0
- /package/src/css/{reset.css → core/reset.css} +0 -0
- /package/src/css/{optional → layout}/scroll-snap.css +0 -0
- /package/src/css/{optional/typography-fluid.css → typography/fluid.css} +0 -0
- /package/src/css/{optional/utilities-extra.css → utilities/extra.css} +0 -0
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
## Class reference
|
|
6
6
|
|
|
7
|
-
| Class
|
|
8
|
-
|
|
9
|
-
| `.field`
|
|
10
|
-
| `.field-label`
|
|
11
|
-
| `.required-mark` | Composition | Visual required marker (`aria-hidden`) added inside a label.
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|------------------|-------------|----------------------------------------------------------------------------------------------|
|
|
9
|
+
| `.field` | Composition | Field wrapper; canonical on `<label>` or `<div>`. |
|
|
10
|
+
| `.field-label` | Composition | Label text, element-agnostic — works on `<span>`, a detached `<label for>`, or a `<legend>`. |
|
|
11
|
+
| `.required-mark` | Composition | Visual required marker (`aria-hidden`) added inside a label. |
|
|
12
12
|
|
|
13
13
|
Use a **wrapped label** for simple hand-authored forms. The whole label area becomes the click target, there is no `id` noise, and the markup is harder to break.
|
|
14
14
|
|
|
@@ -39,4 +39,4 @@ Use **`for`/`id`** when the layout needs the label and control in different grid
|
|
|
39
39
|
</div>
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
The mixed shape `<label for="x">…<input id="x"></label>` is allowed by the spec but rarely useful. Prefer either pure wrapped or pure `for`/`id`.
|
|
42
|
+
The mixed shape `<label for="x">…<input id="x"></label>` is allowed by the spec but rarely useful. Prefer either pure wrapped or pure `for`/`id`.
|
package/docs/pages/forms/otp.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# One-time code input
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **Module** — import `actual-css/css/forms/otp` or `actual-css/css/forms/all`.
|
|
4
4
|
|
|
5
5
|
OTP presents one native input as separate visual cells. Keeping a single input
|
|
6
6
|
preserves paste, selection, autofill, password-manager, and
|
|
@@ -40,6 +40,38 @@ The component follows shared `.sm` and `.lg` density through `--control-size`.
|
|
|
40
40
|
Use `aria-invalid="true"` for explicit invalid state, or place it in the
|
|
41
41
|
standard `.needs-validation.was-validated` form flow.
|
|
42
42
|
|
|
43
|
+
The `<input>` must be the **first** direct child, with one `<span>` per
|
|
44
|
+
character after it — the state rules (focus, invalid, disabled) select the
|
|
45
|
+
cells as following siblings, so that order is part of the contract.
|
|
46
|
+
|
|
47
|
+
## Disabled
|
|
48
|
+
|
|
49
|
+
Set `disabled` on the input. The cells rest on `--surface-subtle` with a muted
|
|
50
|
+
`--state-disabled` border at `--disabled-opacity`, the code glyph turns
|
|
51
|
+
`--state-disabled`, and the cursor is `not-allowed` — a clearly distinct,
|
|
52
|
+
non-interactive look that follows the shared disabled contract. A disabled
|
|
53
|
+
`<fieldset>` disables it the same way.
|
|
54
|
+
|
|
55
|
+
```html demo
|
|
56
|
+
<div class="otp" aria-label="Disabled verification code">
|
|
57
|
+
<input
|
|
58
|
+
class="input"
|
|
59
|
+
type="text"
|
|
60
|
+
autocomplete="one-time-code"
|
|
61
|
+
inputmode="numeric"
|
|
62
|
+
maxlength="6"
|
|
63
|
+
disabled
|
|
64
|
+
aria-label="Disabled verification code"
|
|
65
|
+
/>
|
|
66
|
+
<span aria-hidden="true"></span>
|
|
67
|
+
<span aria-hidden="true"></span>
|
|
68
|
+
<span aria-hidden="true"></span>
|
|
69
|
+
<span aria-hidden="true"></span>
|
|
70
|
+
<span aria-hidden="true"></span>
|
|
71
|
+
<span aria-hidden="true"></span>
|
|
72
|
+
</div>
|
|
73
|
+
```
|
|
74
|
+
|
|
43
75
|
## CSS hooks
|
|
44
76
|
|
|
45
77
|
- `--otp-cell-size` — width and height of every cell; follows `--control-size`.
|
|
@@ -12,23 +12,23 @@
|
|
|
12
12
|
|
|
13
13
|
## Class reference
|
|
14
14
|
|
|
15
|
-
| Class
|
|
16
|
-
|
|
17
|
-
| `.input`
|
|
18
|
-
| `.textarea`
|
|
19
|
-
| `.select`
|
|
20
|
-
| `.check`
|
|
21
|
-
| `.radio`
|
|
22
|
-
| `.switch`
|
|
23
|
-
| `.range`
|
|
24
|
-
| `.file`
|
|
25
|
-
| `.color`
|
|
26
|
-
| `.field`
|
|
27
|
-
| `.field-label`
|
|
28
|
-
| `.field-help`
|
|
29
|
-
| `.field-error`
|
|
30
|
-
| `.field-group`
|
|
31
|
-
| `.choice`
|
|
15
|
+
| Class | Kind | Description |
|
|
16
|
+
|-----------------|-------------|-------------------------------------------------------------------------------|
|
|
17
|
+
| `.input` | Component | Text input; shares the text-control recipe with `.textarea` and `.select`. |
|
|
18
|
+
| `.textarea` | Component | Multi-line text control. |
|
|
19
|
+
| `.select` | Component | Dropdown — native baseline with a CSS chevron and an opt-in enhanced picker. |
|
|
20
|
+
| `.check` | Component | Styled checkbox. |
|
|
21
|
+
| `.radio` | Component | Styled radio button. |
|
|
22
|
+
| `.switch` | Component | Toggle switch on a checkbox input with `role="switch"`. |
|
|
23
|
+
| `.range` | Component | Native range slider with a theme-aware accent color. |
|
|
24
|
+
| `.file` | Component | Native file input with a themed picker button. |
|
|
25
|
+
| `.color` | Component | Native color picker in a control-sized box. |
|
|
26
|
+
| `.field` | Composition | Field wrapper that works on `<label>` and `<div>`. |
|
|
27
|
+
| `.field-label` | Composition | Label text; element-agnostic — `<span>`, detached `<label>`, or `<legend>`. |
|
|
28
|
+
| `.field-help` | Composition | Supporting helper text under a control. |
|
|
29
|
+
| `.field-error` | Composition | Inline error message shown while the field is invalid. |
|
|
30
|
+
| `.field-group` | Composition | Grouped `<fieldset>` container with a tunable legend gutter. |
|
|
31
|
+
| `.choice` | Composition | Choice-label layout wrapping a `.check`, `.radio`, or `.switch`. |
|
|
32
32
|
| `.form-actions` | Composition | Class-only flex row that closes a form; works inside or outside the `<form>`. |
|
|
33
33
|
|
|
34
34
|
## Example form
|
|
@@ -91,7 +91,7 @@ A full form using the control classes, field wrappers, and form actions:
|
|
|
91
91
|
|
|
92
92
|
<fieldset class="field-group">
|
|
93
93
|
<legend class="field-label">Availability</legend>
|
|
94
|
-
<div class="stack">
|
|
94
|
+
<div class="stack sm">
|
|
95
95
|
<label class="choice">
|
|
96
96
|
<input class="radio" type="radio" name="availability" value="available" checked />
|
|
97
97
|
<span>Available for work</span>
|
|
@@ -185,4 +185,4 @@ form[data-required-marks="auto"]
|
|
|
185
185
|
}
|
|
186
186
|
```
|
|
187
187
|
|
|
188
|
-
`required` remains the accessible source of truth; this recipe adds only a visual cue. Use `data-required-mark="none"` on a `.field` when a required control should not receive the generated marker.
|
|
188
|
+
`required` remains the accessible source of truth; this recipe adds only a visual cue. Use `data-required-mark="none"` on a `.field` when a required control should not receive the generated marker.
|
|
@@ -37,4 +37,4 @@ the attribute instead:
|
|
|
37
37
|
A revealed value does not survive navigation: a non-canceled form submit and
|
|
38
38
|
`pagehide` both revert the input to hidden, so back navigation cannot land on
|
|
39
39
|
a readable password. A canceled submit (failed validation, ajax) keeps the
|
|
40
|
-
value revealed.
|
|
40
|
+
value revealed.
|
|
@@ -4,21 +4,28 @@
|
|
|
4
4
|
|
|
5
5
|
## Class reference
|
|
6
6
|
|
|
7
|
-
| Class | Kind
|
|
8
|
-
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|-------|----------|------------------------------------------------------------------------------------------|
|
|
9
9
|
| `.sm` | Modifier | Compact control height and spacing rhythm; sets `--control-size` to `--control-size-sm`. |
|
|
10
|
-
| `.lg` | Modifier | Large control height and spacing rhythm; sets `--control-size` to `--control-size-lg`.
|
|
10
|
+
| `.lg` | Modifier | Large control height and spacing rhythm; sets `--control-size` to `--control-size-lg`. |
|
|
11
11
|
|
|
12
12
|
Use `readonly` for text-like values that can still be focused, selected, and submitted. Use `disabled` for unavailable controls that should not receive focus or submit a value.
|
|
13
13
|
|
|
14
|
-
The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, selects, textareas,
|
|
14
|
+
The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, selects, textareas, and buttons. Put the modifier on the control itself, or on a `.field` wrapper when the whole field should share that size.
|
|
15
|
+
|
|
16
|
+
Inline choices — `.check`, `.radio`, `.switch` — are the exception. They sit on
|
|
17
|
+
a line of text rather than standing as a field, so they are sized off the
|
|
18
|
+
control typography (`--choice-control-size`, an em value) and `.sm` / `.lg`
|
|
19
|
+
leave them alone: density changes field heights, not type. Resizing the control
|
|
20
|
+
without its label would only break the alignment. Scale them by scaling their
|
|
21
|
+
type instead.
|
|
15
22
|
|
|
16
23
|
```html demo
|
|
17
24
|
<form novalidate>
|
|
18
25
|
<fieldset class="field-group">
|
|
19
26
|
<legend class="field-label">Text control states</legend>
|
|
20
|
-
<div class="stack
|
|
21
|
-
<div class="grid
|
|
27
|
+
<div class="stack" style="--grid-min: 14rem;">
|
|
28
|
+
<div class="grid items-start">
|
|
22
29
|
<label class="field">
|
|
23
30
|
<span class="field-label">Editable</span>
|
|
24
31
|
<input class="input" type="text" value="Ocean Beach Clinic" />
|
|
@@ -37,7 +44,7 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
37
44
|
</label>
|
|
38
45
|
</div>
|
|
39
46
|
|
|
40
|
-
<div class="grid
|
|
47
|
+
<div class="grid items-start">
|
|
41
48
|
<label class="field">
|
|
42
49
|
<span class="field-label">Editable notes</span>
|
|
43
50
|
<textarea class="textarea">Patient asked for an invoice copy.</textarea>
|
|
@@ -58,8 +65,8 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
58
65
|
|
|
59
66
|
<fieldset class="field-group">
|
|
60
67
|
<legend class="field-label">Choice and select states</legend>
|
|
61
|
-
<div class="stack
|
|
62
|
-
<div class="grid
|
|
68
|
+
<div class="stack" style="--grid-min: 14rem;">
|
|
69
|
+
<div class="grid items-start">
|
|
63
70
|
<label class="field">
|
|
64
71
|
<span class="field-label">Editable select</span>
|
|
65
72
|
<select class="select">
|
|
@@ -89,7 +96,7 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
89
96
|
</label>
|
|
90
97
|
</div>
|
|
91
98
|
|
|
92
|
-
<div class="grid
|
|
99
|
+
<div class="grid items-start">
|
|
93
100
|
<label class="choice">
|
|
94
101
|
<input class="check" type="checkbox" />
|
|
95
102
|
<span>
|
|
@@ -126,12 +133,12 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
126
133
|
<input class="check" type="checkbox" id="indet-demo" />
|
|
127
134
|
<span>
|
|
128
135
|
<span class="field-label">Indeterminate checkbox</span>
|
|
129
|
-
<span class="field-help">Partially selected — set via <code>element.indeterminate = true</code>. Try it: <button class="btn
|
|
136
|
+
<span class="field-help">Partially selected — set via <code>element.indeterminate = true</code>. Try it: <button class="btn link sm" type="button" onclick="document.getElementById('indet-demo').indeterminate = !document.getElementById('indet-demo').indeterminate">toggle</button></span>
|
|
130
137
|
</span>
|
|
131
138
|
</label>
|
|
132
139
|
</div>
|
|
133
140
|
|
|
134
|
-
<div class="grid
|
|
141
|
+
<div class="grid items-start">
|
|
135
142
|
<label class="choice">
|
|
136
143
|
<input class="radio" type="radio" name="demo-radio-state" />
|
|
137
144
|
<span>
|
|
@@ -165,7 +172,7 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
165
172
|
</label>
|
|
166
173
|
</div>
|
|
167
174
|
|
|
168
|
-
<div class="grid
|
|
175
|
+
<div class="grid items-start">
|
|
169
176
|
<label class="choice">
|
|
170
177
|
<input class="switch" type="checkbox" role="switch" />
|
|
171
178
|
<span>
|
|
@@ -203,8 +210,8 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
203
210
|
|
|
204
211
|
<fieldset class="field-group">
|
|
205
212
|
<legend class="field-label">Control sizes</legend>
|
|
206
|
-
<div class="stack
|
|
207
|
-
<div class="grid
|
|
213
|
+
<div class="stack" style="--grid-min: 14rem;">
|
|
214
|
+
<div class="grid items-start">
|
|
208
215
|
<label class="field sm">
|
|
209
216
|
<span class="field-label">Small field</span>
|
|
210
217
|
<input class="input" type="text" value="sm" />
|
|
@@ -221,7 +228,7 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
221
228
|
</label>
|
|
222
229
|
</div>
|
|
223
230
|
|
|
224
|
-
<div class="grid
|
|
231
|
+
<div class="grid items-start">
|
|
225
232
|
<label class="field sm">
|
|
226
233
|
<span class="field-label">Small select</span>
|
|
227
234
|
<select class="select">
|
|
@@ -244,7 +251,7 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
244
251
|
</label>
|
|
245
252
|
</div>
|
|
246
253
|
|
|
247
|
-
<div class="grid
|
|
254
|
+
<div class="grid items-start">
|
|
248
255
|
<label class="field sm">
|
|
249
256
|
<span class="field-label">Small textarea</span>
|
|
250
257
|
<textarea class="textarea" rows="2">Short note</textarea>
|
|
@@ -261,61 +268,50 @@ The `.sm` and `.lg` modifiers set the shared control tokens used by inputs, sele
|
|
|
261
268
|
</label>
|
|
262
269
|
</div>
|
|
263
270
|
|
|
264
|
-
<div class="grid
|
|
271
|
+
<div class="grid items-start">
|
|
265
272
|
<button class="btn outline sm" type="button">Small</button>
|
|
266
273
|
<button class="btn outline" type="button">Default</button>
|
|
267
274
|
<button class="btn outline lg" type="button">Large</button>
|
|
268
275
|
</div>
|
|
269
276
|
|
|
270
|
-
|
|
277
|
+
<!-- Density is a deliberate no-op on inline choices: these three are
|
|
278
|
+
identical even though the modifiers differ. -->
|
|
279
|
+
<div class="grid items-start">
|
|
271
280
|
<label class="choice sm">
|
|
272
281
|
<input class="check" type="checkbox" checked />
|
|
273
|
-
<span
|
|
282
|
+
<span>.sm checkbox</span>
|
|
274
283
|
</label>
|
|
275
284
|
<label class="choice">
|
|
276
|
-
<input class="
|
|
277
|
-
<span>Default
|
|
285
|
+
<input class="radio" type="radio" name="demo-radio-size" checked />
|
|
286
|
+
<span>Default radio</span>
|
|
278
287
|
</label>
|
|
279
288
|
<label class="choice lg">
|
|
280
|
-
<input class="
|
|
281
|
-
<span
|
|
289
|
+
<input class="switch" type="checkbox" role="switch" checked />
|
|
290
|
+
<span>.lg switch</span>
|
|
282
291
|
</label>
|
|
283
292
|
<label class="choice">
|
|
284
293
|
<input class="check" type="checkbox" id="indet-size" />
|
|
285
|
-
<span>Indeterminate <button class="btn
|
|
294
|
+
<span>Indeterminate <button class="btn link sm" type="button" onclick="document.getElementById('indet-size').indeterminate = !document.getElementById('indet-size').indeterminate">toggle</button></span>
|
|
286
295
|
</label>
|
|
287
296
|
</div>
|
|
288
297
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
<span>Small radio</span>
|
|
293
|
-
</label>
|
|
298
|
+
<!-- Typography is the knob that does resize them — control and label
|
|
299
|
+
together, so the alignment survives. -->
|
|
300
|
+
<div class="grid items-start" style="--control-font-size: var(--font-size-sm);">
|
|
294
301
|
<label class="choice">
|
|
295
|
-
<input class="
|
|
296
|
-
<span>
|
|
297
|
-
</label>
|
|
298
|
-
<label class="choice lg">
|
|
299
|
-
<input class="radio" type="radio" name="demo-radio-size" />
|
|
300
|
-
<span>Large radio</span>
|
|
301
|
-
</label>
|
|
302
|
-
</div>
|
|
303
|
-
|
|
304
|
-
<div class="grid-3 items-start">
|
|
305
|
-
<label class="choice sm">
|
|
306
|
-
<input class="switch" type="checkbox" role="switch" checked />
|
|
307
|
-
<span>Small switch</span>
|
|
302
|
+
<input class="check" type="checkbox" checked />
|
|
303
|
+
<span>Smaller type</span>
|
|
308
304
|
</label>
|
|
309
305
|
<label class="choice">
|
|
310
|
-
<input class="
|
|
311
|
-
<span>
|
|
306
|
+
<input class="radio" type="radio" name="demo-radio-type" checked />
|
|
307
|
+
<span>Smaller type</span>
|
|
312
308
|
</label>
|
|
313
|
-
<label class="choice
|
|
309
|
+
<label class="choice">
|
|
314
310
|
<input class="switch" type="checkbox" role="switch" checked />
|
|
315
|
-
<span>
|
|
311
|
+
<span>Smaller type</span>
|
|
316
312
|
</label>
|
|
317
313
|
</div>
|
|
318
314
|
</div>
|
|
319
315
|
</fieldset>
|
|
320
316
|
</form>
|
|
321
|
-
```
|
|
317
|
+
```
|
|
@@ -57,7 +57,7 @@ Scroll the page to see the actions stay reachable.
|
|
|
57
57
|
|
|
58
58
|
<fieldset class="field-group">
|
|
59
59
|
<legend class="field-label">Theme</legend>
|
|
60
|
-
<div class="stack">
|
|
60
|
+
<div class="stack sm">
|
|
61
61
|
<label class="choice">
|
|
62
62
|
<input class="radio" type="radio" name="theme" value="light" checked />
|
|
63
63
|
<span>Light</span>
|
|
@@ -141,7 +141,7 @@ Scroll the page to see the detached footer stay reachable.
|
|
|
141
141
|
|
|
142
142
|
<fieldset class="field-group">
|
|
143
143
|
<legend class="field-label">Theme</legend>
|
|
144
|
-
<div class="stack">
|
|
144
|
+
<div class="stack sm">
|
|
145
145
|
<label class="choice">
|
|
146
146
|
<input class="radio" type="radio" name="theme-detached" value="light" checked />
|
|
147
147
|
<span>Light</span>
|
|
@@ -184,4 +184,4 @@ Scroll the page to see the detached footer stay reachable.
|
|
|
184
184
|
}
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
-
A sticky footer can cover the last field on short pages. That is a page-layout concern, not a framework concern. Add bottom padding to the page or scroll container if needed.
|
|
187
|
+
A sticky footer can cover the last field on short pages. That is a page-layout concern, not a framework concern. Add bottom padding to the page or scroll container if needed.
|
|
@@ -21,11 +21,119 @@
|
|
|
21
21
|
onchange="this.setAttribute('aria-checked', this.checked)" />
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
Wrap a switch in `.choice` to pair it with a label. The switch stays
|
|
25
|
+
top-aligned with the first line of text, so labels that wrap onto two lines —
|
|
26
|
+
naturally or via an explicit line break — still sit cleanly.
|
|
27
|
+
|
|
28
|
+
```html demo
|
|
29
|
+
<label class="choice">
|
|
30
|
+
<input class="switch" type="checkbox" role="switch" checked />
|
|
31
|
+
<span>
|
|
32
|
+
Release alerts
|
|
33
|
+
<span class="field-help">Send status changes to the release channel.</span>
|
|
34
|
+
</span>
|
|
35
|
+
</label>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```html demo
|
|
39
|
+
<!-- Multi-line labels keep the switch aligned with the first line. -->
|
|
40
|
+
<label class="choice">
|
|
41
|
+
<input class="switch" type="checkbox" role="switch" />
|
|
42
|
+
<span>
|
|
43
|
+
Send a summary of account activity for the past month, including any
|
|
44
|
+
unusual sign-ins, to the address on file.
|
|
45
|
+
<span class="field-help">A long label that wraps onto a second line.</span>
|
|
46
|
+
</span>
|
|
47
|
+
</label>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```html demo
|
|
51
|
+
<!-- Explicit line break, top-aligned with the first line. -->
|
|
52
|
+
<label class="choice">
|
|
53
|
+
<input class="switch" type="checkbox" role="switch" />
|
|
54
|
+
<span>
|
|
55
|
+
Weekly summary with a<br />manual line break
|
|
56
|
+
<span class="field-help">A forced two-line label.</span>
|
|
57
|
+
</span>
|
|
58
|
+
</label>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Sizing and alignment
|
|
62
|
+
|
|
63
|
+
A switch is sized off the control typography, not field density. Its track
|
|
64
|
+
comes from `--choice-control-size` — the same token a checkbox and a radio use
|
|
65
|
+
— so the three sit on a line of text at matching weight. `.sm` and `.lg` change
|
|
66
|
+
`--control-size`, which is field height, and deliberately leave inline choices
|
|
67
|
+
alone.
|
|
68
|
+
|
|
69
|
+
The offset that centers each control on the first line of its label is derived
|
|
70
|
+
from that control's own height, so a checkbox and a taller switch land on the
|
|
71
|
+
same optical line. Change the type or the control size and they stay level:
|
|
72
|
+
|
|
73
|
+
```html demo
|
|
74
|
+
<!-- Same row, three heights: 18px checkbox, 18px radio, 20px switch track. -->
|
|
75
|
+
<div class="cluster">
|
|
76
|
+
<label class="choice">
|
|
77
|
+
<input class="check" type="checkbox" checked />
|
|
78
|
+
<span>Checkbox</span>
|
|
79
|
+
</label>
|
|
80
|
+
<label class="choice">
|
|
81
|
+
<input class="radio" type="radio" name="align-default" checked />
|
|
82
|
+
<span>Radio</span>
|
|
83
|
+
</label>
|
|
84
|
+
<label class="choice">
|
|
85
|
+
<input class="switch" type="checkbox" role="switch" checked />
|
|
86
|
+
<span>Switch</span>
|
|
87
|
+
</label>
|
|
88
|
+
</div>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```html demo
|
|
92
|
+
<!-- A looser line-height re-centers every control by the same rule. -->
|
|
93
|
+
<div class="cluster" style="line-height: 2.2;">
|
|
94
|
+
<label class="choice">
|
|
95
|
+
<input class="check" type="checkbox" checked />
|
|
96
|
+
<span>Checkbox</span>
|
|
97
|
+
</label>
|
|
98
|
+
<label class="choice">
|
|
99
|
+
<input class="radio" type="radio" name="align-tall" checked />
|
|
100
|
+
<span>Radio</span>
|
|
101
|
+
</label>
|
|
102
|
+
<label class="choice">
|
|
103
|
+
<input class="switch" type="checkbox" role="switch" checked />
|
|
104
|
+
<span>Switch</span>
|
|
105
|
+
</label>
|
|
106
|
+
</div>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```html demo
|
|
110
|
+
<!-- Scaling --choice-control-size grows the checkbox and the switch
|
|
111
|
+
track together, and the row stays aligned. -->
|
|
112
|
+
<div class="cluster" style="--choice-control-size: 1.5em;">
|
|
113
|
+
<label class="choice">
|
|
114
|
+
<input class="check" type="checkbox" checked />
|
|
115
|
+
<span>Checkbox</span>
|
|
116
|
+
</label>
|
|
117
|
+
<label class="choice">
|
|
118
|
+
<input class="radio" type="radio" name="align-big" checked />
|
|
119
|
+
<span>Radio</span>
|
|
120
|
+
</label>
|
|
121
|
+
<label class="choice">
|
|
122
|
+
<input class="switch" type="checkbox" role="switch" checked />
|
|
123
|
+
<span>Switch</span>
|
|
124
|
+
</label>
|
|
125
|
+
</div>
|
|
126
|
+
```
|
|
127
|
+
|
|
24
128
|
## CSS hooks
|
|
25
129
|
|
|
130
|
+
- `--choice-control-size` — shared size for inline choices; the switch track is
|
|
131
|
+
this plus `0.125em`, so scaling it scales the checkbox and the switch together.
|
|
26
132
|
- `--switch-width` — track width.
|
|
27
133
|
- `--switch-block-size` — track height.
|
|
28
134
|
- `--switch-knob-margin` — inset between knob and track.
|
|
29
135
|
|
|
30
|
-
Knob size and travel distance are derived from
|
|
31
|
-
than the derived values.
|
|
136
|
+
Knob size and travel distance are derived from the three `--switch-*` hooks; set
|
|
137
|
+
those rather than the derived values. The knob is concentric in its track: the
|
|
138
|
+
inset is measured inside the border on both axes, so it clears the rails by the
|
|
139
|
+
same distance it clears the ends.
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## Class reference
|
|
6
6
|
|
|
7
|
-
| Class
|
|
8
|
-
|
|
9
|
-
| `.field-error`
|
|
10
|
-
| `.field-help`
|
|
11
|
-
| `.field.danger`
|
|
12
|
-
| `.needs-validation` | Modifier
|
|
13
|
-
| `.was-validated`
|
|
14
|
-
| `.status-bar`
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---------------------|-------------|---------------------------------------------------------------------------------|
|
|
9
|
+
| `.field-error` | Composition | Canonical inline error message; shown while the field is invalid. |
|
|
10
|
+
| `.field-help` | Composition | Canonical helper text; carries supporting copy before and after validation. |
|
|
11
|
+
| `.field.danger` | Modifier | Manual invalid marking on the field wrapper. |
|
|
12
|
+
| `.needs-validation` | Modifier | Opt-in class for the validation enhancer and `:user-invalid` styling. |
|
|
13
|
+
| `.was-validated` | Modifier | Added to the form by the enhancer after the first submit attempt. |
|
|
14
|
+
| `.status-bar` | Component | Optional status element that shows `data-validation-message` on invalid submit. |
|
|
15
15
|
|
|
16
16
|
- `.field-error` is the canonical error message. It is wired to `aria-invalid="true"` via the input, so the visual border and the assistive-tech announcement move together.
|
|
17
17
|
- `.field-help` is the canonical helper text. It carries supporting copy before and after validation.
|
|
@@ -238,4 +238,4 @@ Invalid visuals converge across the three ways a field can be flagged:
|
|
|
238
238
|
`:user-invalid`. Each sets the danger border, and a checked or indeterminate
|
|
239
239
|
`.check`, `.radio`, or `.switch` also flips its fill to danger so border and
|
|
240
240
|
fill signal together. Choice cards surface the same invalid state on the card
|
|
241
|
-
border. The exact selector coverage is asserted by `tests/validation.test.js`.
|
|
241
|
+
border. The exact selector coverage is asserted by `tests/validation.test.js`.
|
|
@@ -85,4 +85,4 @@ instead of consuming the shared tokens.
|
|
|
85
85
|
|
|
86
86
|
When using a component, child elements follow the semantic pattern of that component. For example, `.avatar` accepts `<img>`, `<picture>`, text content, an empty `.badge` for status dots, and can be a `<button>` or `<a>`.
|
|
87
87
|
|
|
88
|
-
No child classes like `.avatar-img` are needed.
|
|
88
|
+
No child classes like `.avatar-img` are needed.
|
|
@@ -20,7 +20,7 @@ Set `--cluster-align`.
|
|
|
20
20
|
|
|
21
21
|
### Change spacing without changing control size
|
|
22
22
|
|
|
23
|
-
Set `--gap` locally on the layout primitive. The
|
|
23
|
+
Set `--gap` locally on the layout primitive. The extra utilities (`src/css/utilities/extra.css`) ship `.gap-sm` / `.gap-md` / `.gap-lg` for row/column containers.
|
|
24
24
|
|
|
25
25
|
→ Layout
|
|
26
26
|
|
|
@@ -56,7 +56,7 @@ Set `--form-actions-justify` (and `--form-actions-align`).
|
|
|
56
56
|
|
|
57
57
|
### Customize a switch's size
|
|
58
58
|
|
|
59
|
-
Change `--switch-width`, `--switch-block-size`, and `--switch-knob-margin`; knob size and travel are derived from them.
|
|
59
|
+
Change `--switch-width`, `--switch-block-size`, and `--switch-knob-margin`; knob size and travel are derived from them. To rescale the whole row of inline choices at once, set `--choice-control-size` instead — the checkbox, the radio, and the switch track all follow it. `.sm` / `.lg` are field density and leave inline choices alone.
|
|
60
60
|
|
|
61
61
|
→ Forms · Switch
|
|
62
62
|
|
|
@@ -64,6 +64,12 @@ Change `--switch-width`, `--switch-block-size`, and `--switch-knob-margin`; knob
|
|
|
64
64
|
|
|
65
65
|
Set `--disabled-opacity`. All disabled-prone components — buttons, tabs, menu items, badges, avatars, choice cards, native inputs, and range sliders — read it for their dimmed state.
|
|
66
66
|
|
|
67
|
+
### Keep bare native controls on-theme / accent-color
|
|
68
|
+
|
|
69
|
+
Native controls that no component class restyles — a bare checkbox, radio, range, or `<progress>` — follow the theme through `accent-color: var(--primary)`, declared on `:root` and every `[data-theme]` island so each island recomputes it from its own palette. Component classes (`.check`, `.radio`, `.range`) paint their own rendering and do not read it.
|
|
70
|
+
|
|
71
|
+
→ Forms · Overview · Foundations · Tokens (theme contract)
|
|
72
|
+
|
|
67
73
|
### Loading / busy overlay on a container
|
|
68
74
|
|
|
69
75
|
Use `aria-busy="true"` with a direct last-child `.spinner`; tint the overlay with `--busy-overlay-bg`.
|
|
@@ -97,3 +103,12 @@ surfaces — must use another palette. More specific component states or explici
|
|
|
97
103
|
surface variants (`.card.subtle`) still take precedence.
|
|
98
104
|
|
|
99
105
|
→ Components · Card · Foundations · Tokens (theme contract)
|
|
106
|
+
|
|
107
|
+
### Use or adapt a preset palette
|
|
108
|
+
|
|
109
|
+
`src/css/themes/` holds example palettes (`ocean`, `spruce`, `neon`, `brutalist`, …) as
|
|
110
|
+
reference material to copy into your own `[data-theme]` island — they are demo
|
|
111
|
+
assets, not package entrypoints. Each sets the intent/surface/text tokens and
|
|
112
|
+
lets the core derive everything else. In browsers with `color-mix()` support,
|
|
113
|
+
`--focus-ring` follows each island's `--focus` automatically; re-declare it only
|
|
114
|
+
for a deliberate visual override or a matching legacy fallback.
|