actual-css 0.4.2 → 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 +66 -3
- package/README.md +2 -2
- package/dist/actual.css +54 -14
- package/dist/actual.full.css +744 -185
- 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/spacing-units.md +286 -0
- package/docs/design-notes/steps.md +748 -0
- package/docs/design-notes/widget-primitives.md +32 -15
- package/docs/navigation.json +2 -0
- package/docs/pages/components/alert.md +14 -9
- package/docs/pages/components/app-navigation.md +2 -0
- package/docs/pages/components/aura.md +102 -6
- package/docs/pages/components/avatar.md +9 -6
- package/docs/pages/components/badge.md +27 -9
- package/docs/pages/components/button.md +25 -18
- package/docs/pages/components/card.md +27 -7
- package/docs/pages/components/chat.md +1 -1
- package/docs/pages/components/data-list.md +72 -0
- package/docs/pages/components/dialog.md +12 -7
- package/docs/pages/components/drawer.md +3 -1
- package/docs/pages/components/fab.md +14 -10
- package/docs/pages/components/indicator.md +6 -6
- package/docs/pages/components/list.md +11 -2
- package/docs/pages/components/meter.md +56 -1
- package/docs/pages/components/navbar.md +1 -1
- package/docs/pages/components/pagination.md +1 -1
- package/docs/pages/components/progress.md +10 -0
- package/docs/pages/components/rating.md +4 -4
- package/docs/pages/components/skeleton.md +3 -1
- package/docs/pages/components/spinner.md +1 -1
- package/docs/pages/components/steps.md +379 -47
- package/docs/pages/components/table.md +6 -5
- package/docs/pages/enhancements/flyout.md +14 -10
- package/docs/pages/enhancements/overview.md +2 -2
- package/docs/pages/enhancements/scrollspy.md +1 -1
- package/docs/pages/enhancements/status-bar.md +10 -1
- package/docs/pages/enhancements/tabs.md +1 -1
- package/docs/pages/examples/overview.md +4 -1
- 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 +6 -4
- package/docs/pages/forms/labels.md +8 -5
- package/docs/pages/forms/overview.md +26 -19
- package/docs/pages/forms/password.md +3 -2
- package/docs/pages/forms/range.md +15 -2
- package/docs/pages/forms/states-and-sizes.md +7 -5
- package/docs/pages/forms/validation.md +15 -9
- package/docs/pages/foundations/philosophy.md +11 -1
- package/docs/pages/foundations/tokens.md +16 -9
- package/docs/pages/foundations/typography.md +11 -3
- package/docs/pages/guides/bootstrap.md +3 -3
- package/docs/pages/guides/introduction.md +2 -2
- 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/scroll-snap.md +2 -0
- package/docs/pages/layout/sidebar-layout.md +2 -0
- package/docs/pages/layout/stack.md +10 -6
- package/docs/pages/layout/topbar.md +2 -0
- package/docs/pages/patterns/structured-lists.md +7 -7
- package/docs/pages/utilities/accessibility.md +19 -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 +8 -1
- package/src/css/components/data-list.css +27 -0
- package/src/css/components/drawer.css +30 -11
- package/src/css/components/fab.css +44 -8
- package/src/css/components/flyout.css +17 -12
- package/src/css/components/index.css +1 -0
- package/src/css/components/list.css +3 -1
- package/src/css/components/meter.css +28 -1
- package/src/css/components/modal.css +28 -11
- package/src/css/components/progress.css +5 -0
- package/src/css/components/status-bar.css +31 -15
- package/src/css/components/steps.css +289 -55
- package/src/css/components/surface.css +5 -3
- package/src/css/components/tooltip.css +5 -8
- package/src/css/core/base.css +7 -1
- package/src/css/core/intents.css +6 -0
- package/src/css/core/tokens.css +24 -9
- package/src/css/core/variants.css +17 -4
- 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/forms/form.css +4 -4
- 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/css/typography/prose.css +2 -3
- package/src/css/utilities/base.css +16 -0
- package/src/js/password.js +1 -1
- package/src/js/selectors.js +1 -0
- package/src/js/status.js +88 -7
- package/src/js/surface.js +2 -11
- package/src/js/transition.js +20 -0
|
@@ -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">
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
> Use `.join` when controls need to be visually joined into a single unit.
|
|
4
4
|
|
|
5
|
+
**Related terms:** segmented control, button group, input group.
|
|
6
|
+
|
|
5
7
|
## Class reference
|
|
6
8
|
|
|
7
|
-
| Class | Kind | Description
|
|
8
|
-
|
|
9
|
-
| `.join` | Composition |
|
|
10
|
-
| `.join-addon` | Composition | Static prefix
|
|
9
|
+
| Class | Kind | Description |
|
|
10
|
+
| ------------- | ----------- | ------------------------------------------- |
|
|
11
|
+
| `.join` | Composition | Joins adjacent controls into a single unit. |
|
|
12
|
+
| `.join-addon` | Composition | Static prefix or suffix content. |
|
|
11
13
|
|
|
12
14
|
Add `.join` to the wrapper that groups the controls. Use `.join-addon` for static prefix/suffix content such as currency symbols, units, or protocol text. Action buttons inside the group should use `.btn`. The wrapper should still carry `role="group"` with a label for accessibility.
|
|
13
15
|
|
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## Class reference
|
|
6
6
|
|
|
7
|
-
| Class | Kind | Description
|
|
8
|
-
|
|
9
|
-
| `.field` | Composition | Field wrapper; canonical on `<label>` or `<div>`.
|
|
10
|
-
| `.field-label` | Composition | Label text, element-agnostic
|
|
11
|
-
| `.required-mark` | Composition | Visual required marker (`aria-hidden`)
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
| ---------------- | ----------- | ------------------------------------------------- |
|
|
9
|
+
| `.field` | Composition | Field wrapper; canonical on `<label>` or `<div>`. |
|
|
10
|
+
| `.field-label` | Composition | Label text, element-agnostic. |
|
|
11
|
+
| `.required-mark` | Composition | Visual required marker (`aria-hidden`). |
|
|
12
|
+
|
|
13
|
+
`.field-label` works on a `<span>`, on a detached `<label for>`, or on a
|
|
14
|
+
`<legend>`. `.required-mark` goes inside a label.
|
|
12
15
|
|
|
13
16
|
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
17
|
|
|
@@ -9,27 +9,34 @@
|
|
|
9
9
|
- Proper focus style that preserves keyboard navigation.
|
|
10
10
|
- `.field-group` and `.choice` provide layout without depending on parent scope.
|
|
11
11
|
- Customizable select is progressive enhancement only — the native select remains the baseline.
|
|
12
|
+
- Searchable selects, tags and autocomplete are a JavaScript widget concern; theme an external combobox with Actual tokens — see the [combobox template](../../demo/templates/combobox.html).
|
|
12
13
|
|
|
13
14
|
## Class reference
|
|
14
15
|
|
|
15
|
-
| Class | Kind | Description
|
|
16
|
-
|
|
17
|
-
| `.input` | Component | Text input
|
|
18
|
-
| `.textarea` | Component | Multi-line text control.
|
|
19
|
-
| `.select` | Component | Dropdown
|
|
20
|
-
| `.check` | Component | Styled checkbox.
|
|
21
|
-
| `.radio` | Component | Styled radio button.
|
|
22
|
-
| `.switch` | Component | Toggle switch on a
|
|
23
|
-
| `.range` | Component | Native range slider
|
|
24
|
-
| `.file` | Component | Native file input
|
|
25
|
-
| `.color` | Component | Native color picker in a control-sized box.
|
|
26
|
-
| `.field` | Composition | Field wrapper
|
|
27
|
-
| `.field-label` | Composition | Label text
|
|
28
|
-
| `.field-help` | Composition | Supporting helper text under a control.
|
|
29
|
-
| `.field-error` | Composition | Inline error message shown while
|
|
30
|
-
| `.field-group` | Composition |
|
|
31
|
-
| `.choice` | Composition | Choice-label layout
|
|
32
|
-
| `.form-actions` | Composition | Class-only flex row that closes a form
|
|
16
|
+
| Class | Kind | Description |
|
|
17
|
+
| --------------- | ----------- | --------------------------------------------- |
|
|
18
|
+
| `.input` | Component | Text input. |
|
|
19
|
+
| `.textarea` | Component | Multi-line text control. |
|
|
20
|
+
| `.select` | Component | Dropdown, native baseline with a CSS chevron. |
|
|
21
|
+
| `.check` | Component | Styled checkbox. |
|
|
22
|
+
| `.radio` | Component | Styled radio button. |
|
|
23
|
+
| `.switch` | Component | Toggle switch on a `role="switch"` checkbox. |
|
|
24
|
+
| `.range` | Component | Native range slider, theme-aware accent. |
|
|
25
|
+
| `.file` | Component | Native file input, themed picker button. |
|
|
26
|
+
| `.color` | Component | Native color picker in a control-sized box. |
|
|
27
|
+
| `.field` | Composition | Field wrapper, on `<label>` or `<div>`. |
|
|
28
|
+
| `.field-label` | Composition | Label text, element-agnostic. |
|
|
29
|
+
| `.field-help` | Composition | Supporting helper text under a control. |
|
|
30
|
+
| `.field-error` | Composition | Inline error message, shown while invalid. |
|
|
31
|
+
| `.field-group` | Composition | `<fieldset>` with a tunable legend gutter. |
|
|
32
|
+
| `.choice` | Composition | Choice-label layout around an inline control. |
|
|
33
|
+
| `.form-actions` | Composition | Class-only flex row that closes a form. |
|
|
34
|
+
|
|
35
|
+
`.input` shares the text-control recipe with `.textarea` and `.select`, and
|
|
36
|
+
`.select` also has an opt-in enhanced picker. `.field-label` works on a
|
|
37
|
+
`<span>`, a detached `<label>` or a `<legend>`. `.choice` wraps a `.check`,
|
|
38
|
+
`.radio` or `.switch`, and `.form-actions` works inside or outside the
|
|
39
|
+
`<form>`.
|
|
33
40
|
|
|
34
41
|
## Example form
|
|
35
42
|
|
|
@@ -164,7 +171,7 @@ A full form using the control classes, field wrappers, and form actions:
|
|
|
164
171
|
- `required` is the semantic source of truth. Add `<span class="required-mark" aria-hidden="true">*</span>` inside a label only when a visual required marker is wanted; the framework does not add one automatically.
|
|
165
172
|
- `.field` is the canonical field wrapper. It works on `<label>` and `<div>`.
|
|
166
173
|
- `.field-label` is element-agnostic. Use it on `<span>` inside a wrapped label, on `<label for="…">` in a detached layout, or on `<legend>` inside a fieldset.
|
|
167
|
-
- `.field-group` styles a `<fieldset class="field-group">` as a grouped field container. Its legend gutter is tunable with `--fieldset-legend-padding-inline` (`var(--space-10)`).
|
|
174
|
+
- `.field-group` styles a `<fieldset class="field-group">` as a grouped field container. Its legend gutter is tunable with `--fieldset-legend-padding-inline` (`var(--space-10)`). It carries no sibling margin: space consecutive groups with `.stack` on the form, so the rhythm follows the layout instead of the component.
|
|
168
175
|
- Use native `<optgroup>` and `disabled` options in `.select` controls when applicable; the customizable picker preserves both as a progressive enhancement.
|
|
169
176
|
- `.choice` is the choice-label API. Use `.check` or `.radio` on the nested control. The control goes first, the label group second, so multi-line labels align the control with the first line.
|
|
170
177
|
- For a switch, use `class="switch"` and `role="switch"`.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Password Toggle
|
|
2
2
|
|
|
3
3
|
> A password field reveals its value through a linked button. The markup is a
|
|
4
|
-
> plain command invoker; the behavior ships with the JS runtime
|
|
5
|
-
> (`actual-css/js`
|
|
4
|
+
> plain command invoker; the behavior ships with the full JS runtime
|
|
5
|
+
> (`actual-css/js/full`) and can also be imported independently
|
|
6
|
+
> (`actual-css/js/password`).
|
|
6
7
|
|
|
7
8
|
Point a `button` at the input with `commandfor` and
|
|
8
9
|
`command="--password-toggle"`. Use `.join` when the button should sit attached
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
# Range
|
|
2
2
|
|
|
3
|
-
> Native range
|
|
3
|
+
> Native range input with a lightweight theme-aware custom skin.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`.range` keeps the native range control and its interaction semantics, while
|
|
6
|
+
customizing the track, thumb, focus state, intents, and disabled state. The
|
|
7
|
+
focus ring targets the thumb — the surface the user actually manipulates —
|
|
8
|
+
rather than the CSS box.
|
|
9
|
+
|
|
10
|
+
**Related terms:** slider, range input, scrubber.
|
|
6
11
|
|
|
7
12
|
```html demo
|
|
8
13
|
<label class="field">
|
|
@@ -11,7 +16,15 @@ Core: native range, enhanced by `accent-color`. Optional richer skin may come la
|
|
|
11
16
|
</label>
|
|
12
17
|
```
|
|
13
18
|
|
|
19
|
+
Actual deliberately does not emulate filled tracks, tick marks, value labels,
|
|
20
|
+
or multi-thumb ranges. Those still require engine-specific pseudo-elements or a
|
|
21
|
+
value duplicated out of the HTML into CSS. Prefer the platform as richer range
|
|
22
|
+
styling becomes interoperable — see
|
|
23
|
+
[Enhanced range controls](https://github.com/lekoala/actual-css/blob/master/docs/design-notes/platform-alignment.md).
|
|
24
|
+
|
|
14
25
|
## CSS hooks
|
|
15
26
|
|
|
16
27
|
- `--range-thumb-size` — thumb diameter.
|
|
17
28
|
- `--range-track-height` — track thickness.
|
|
29
|
+
- `--range-thumb-bg` — thumb color. Defaults to the local intent, then `--primary`.
|
|
30
|
+
- `--range-track-bg` — track color.
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
## Class reference
|
|
6
6
|
|
|
7
|
-
| Class | Kind | Description
|
|
8
|
-
|
|
9
|
-
| `.sm` | Modifier | Compact control height and spacing rhythm
|
|
10
|
-
| `.lg` | Modifier | Large control height and spacing rhythm
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
| ----- | -------- | ------------------------------------------ |
|
|
9
|
+
| `.sm` | Modifier | Compact control height and spacing rhythm. |
|
|
10
|
+
| `.lg` | Modifier | Large control height and spacing rhythm. |
|
|
11
|
+
|
|
12
|
+
Each sets `--control-size` to `--control-size-sm` or `--control-size-lg`.
|
|
11
13
|
|
|
12
14
|
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
15
|
|
|
@@ -21,7 +23,7 @@ without its label would only break the alignment. Scale them by scaling their
|
|
|
21
23
|
type instead.
|
|
22
24
|
|
|
23
25
|
```html demo
|
|
24
|
-
<form novalidate>
|
|
26
|
+
<form class="stack" novalidate>
|
|
25
27
|
<fieldset class="field-group">
|
|
26
28
|
<legend class="field-label">Text control states</legend>
|
|
27
29
|
<div class="stack" style="--grid-min: 14rem;">
|
|
@@ -2,16 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
> Inline error feedback that respects assistive technology and form state.
|
|
4
4
|
|
|
5
|
+
**Related terms:** inline validation, field error.
|
|
6
|
+
|
|
5
7
|
## Class reference
|
|
6
8
|
|
|
7
|
-
| Class | Kind | Description
|
|
8
|
-
|
|
9
|
-
| `.field-error` | Composition | Canonical inline error message
|
|
10
|
-
| `.field-help` | Composition | Canonical helper text
|
|
11
|
-
| `.field.danger` | Modifier | Manual invalid marking on the
|
|
12
|
-
| `.needs-validation` | Modifier | Opt-in
|
|
13
|
-
| `.was-validated` | Modifier |
|
|
14
|
-
| `.status-bar` | Component | Optional status element
|
|
9
|
+
| Class | Kind | Description |
|
|
10
|
+
| ------------------- | ----------- | -------------------------------------------- |
|
|
11
|
+
| `.field-error` | Composition | Canonical inline error message. |
|
|
12
|
+
| `.field-help` | Composition | Canonical helper text. |
|
|
13
|
+
| `.field.danger` | Modifier | Manual invalid marking on the wrapper. |
|
|
14
|
+
| `.needs-validation` | Modifier | Opt-in for the enhancer and `:user-invalid`. |
|
|
15
|
+
| `.was-validated` | Modifier | Set by the enhancer after a submit attempt. |
|
|
16
|
+
| `.status-bar` | Component | Optional form-level status element. |
|
|
17
|
+
|
|
18
|
+
`.field-error` shows while the field is invalid; `.field-help` carries
|
|
19
|
+
supporting copy before and after validation. `.status-bar` shows
|
|
20
|
+
`data-validation-message` on an invalid submit.
|
|
15
21
|
|
|
16
22
|
- `.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
23
|
- `.field-help` is the canonical helper text. It carries supporting copy before and after validation.
|
|
@@ -47,7 +53,7 @@
|
|
|
47
53
|
|
|
48
54
|
Native validation first; the enhancer only adds state and focus behavior.
|
|
49
55
|
|
|
50
|
-
Actual CSS ships validation *styles*. Invalid fields are marked with `aria-invalid="true"` (or the manual `.field.danger` wrapper class). The default forms bundle imports `forms/validation.css`; custom builds may omit that file when validation styling is app-owned. A small enhancer (`actual-css/js/validation`), included in the
|
|
56
|
+
Actual CSS ships validation *styles*. Invalid fields are marked with `aria-invalid="true"` (or the manual `.field.danger` wrapper class). The default forms bundle imports `forms/validation.css`; custom builds may omit that file when validation styling is app-owned. A small enhancer (`actual-css/js/validation`), included in the full runtime (`actual-css/js/full`) and also importable on its own, prevents premature error display, marks invalid fields on blur and submit, focuses the first invalid field on submit, and supports a few custom rules. It is not a validation framework — server and AJAX validation stay in app code.
|
|
51
57
|
|
|
52
58
|
Opt in with the `.needs-validation` class. Importing the module registers the behavior; there is no init call.
|
|
53
59
|
|
|
@@ -10,9 +10,19 @@ Components are semantic boxes: `.btn`, `.badge`, `.alert`, `.card`, `.avatar`, e
|
|
|
10
10
|
|
|
11
11
|
`.primary`, `.secondary`, `.success`, `.warning`, `.danger` do not style elements directly. They only expose `--intent` and `--intent-fg`. Components and variants decide how to consume them.
|
|
12
12
|
|
|
13
|
+
Intent classes define the current `--intent` value; they do not form a
|
|
14
|
+
general-purpose color utility system. Use `.intent-color` when a simple element
|
|
15
|
+
should consume the current intent as its foreground color. It works with an
|
|
16
|
+
intent on the same element or inherited from an ancestor.
|
|
17
|
+
|
|
13
18
|
```html demo
|
|
14
19
|
<button class="btn primary">Primary</button>
|
|
15
20
|
<span class="badge success">Success</span>
|
|
21
|
+
<span class="success intent-color">Success text</span>
|
|
22
|
+
<span class="danger">
|
|
23
|
+
<i class="ti ti-alert-triangle intent-color" aria-hidden="true"></i>
|
|
24
|
+
Something needs attention
|
|
25
|
+
</span>
|
|
16
26
|
```
|
|
17
27
|
|
|
18
28
|
There is no `.btn-primary` or `.badge-success`. Intents are generic and reusable across any component that supports them.
|
|
@@ -35,7 +45,7 @@ Custom intents need no framework support — define `--intent` and `--intent-fg`
|
|
|
35
45
|
|
|
36
46
|
## Variants
|
|
37
47
|
|
|
38
|
-
`.solid`, `.soft`, `.outline` define the visual treatment by setting `--ui-bg`, `--ui-fg`, `--ui-border`. Components consume these tokens with sensible fallbacks. Interactive components also set a `--ui-hover-bg` recipe that their hover rule reads.
|
|
48
|
+
`.solid`, `.soft`, `.outline`, `.surface` define the visual treatment by setting `--ui-bg`, `--ui-fg`, `--ui-border`. Components consume these tokens with sensible fallbacks. Interactive components also set a `--ui-hover-bg` recipe that their hover rule reads.
|
|
39
49
|
|
|
40
50
|
`.btn` defaults to `.solid`; `.badge` and `.alert` default to `.soft`.
|
|
41
51
|
|
|
@@ -133,7 +133,7 @@ Spacing should be useful without becoming a design-token encyclopedia.
|
|
|
133
133
|
}
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
Official steps are named in tens so the scale stays extensible
|
|
136
|
+
Official steps are named in tens so the scale stays extensible. **Actual CSS will never define a `--space-*` token that is not a multiple of 10.** The intermediate names (`--space-15`, `--space-45`, …) are reserved for application-level interpolation: defining them is not writing into the framework namespace, it is using the half of the scale the framework has permanently given up.
|
|
137
137
|
|
|
138
138
|
Use `em` for spacing that should scale with the component text size, such as button gaps and inline padding. Use `rem` for global rhythm, layouts, and fixed density.
|
|
139
139
|
|
|
@@ -220,7 +220,7 @@ With `color-mix()` support the shadows derive from `--shadow-color` (a theme tok
|
|
|
220
220
|
|
|
221
221
|
### Motion
|
|
222
222
|
|
|
223
|
-
Motion
|
|
223
|
+
Motion durations keep transitions consistent and easy to disable.
|
|
224
224
|
|
|
225
225
|
```css
|
|
226
226
|
:root {
|
|
@@ -229,10 +229,13 @@ Motion tokens keep transitions consistent and easy to disable.
|
|
|
229
229
|
--duration-slow: 200ms; /* one-shot open/close */
|
|
230
230
|
--duration-spin: 0.75s; /* continuous spin (.spinner) */
|
|
231
231
|
--duration-shimmer: 1.2s; /* continuous shimmer (.skeleton, indeterminate .progress) */
|
|
232
|
-
--ease:
|
|
232
|
+
--ease-enter: cubic-bezier(0.2, 0, 0, 1);
|
|
233
|
+
--ease-exit: cubic-bezier(0.4, 0, 1, 1);
|
|
233
234
|
}
|
|
234
235
|
```
|
|
235
236
|
|
|
237
|
+
Ordinary interaction/state transitions have **no easing token**: they use the CSS default `ease` directly, and the dialog shake feedback plus the `actual-dialog` View Transition keep that default deliberately. The presence pair exists only for one-shot open/close where open and closed states own separate transition declarations (`.status-bar`/`.is-open`, `dialog.modal[open]`, `dialog.drawer[open]`): `--ease-enter` decelerates the appearance, `--ease-exit` accelerates the departure. The pair follows Material's standard rhythm; the emphasized-decelerate entrance is deliberately not offered because it only pays off at 250–400ms durations, beyond this vocabulary. Backdrops keep `ease` — a scrim only fades, it does not travel — but track their surface's duration. Toggles that share one transition list at `--duration-fast` (flyout, tooltip) also stay on `ease`: at 100ms the curve barely resolves and entry/exit cannot split on a single rule. These absences are deliberate, not gaps; a theme with a different motion character overrides `--ease-enter` / `--ease-exit`.
|
|
238
|
+
|
|
236
239
|
`reset.css` clamps raw animation and transition durations to `0.01ms`, resets their delays, and restores `html` scroll behavior under `prefers-reduced-motion: reduce`. Decorative loops effectively complete immediately without blanket-disabling animation support.
|
|
237
240
|
|
|
238
241
|
### Icons
|
|
@@ -244,6 +247,7 @@ Icons used by CSS-only controls are public tokens because users may need to repl
|
|
|
244
247
|
--icon-chevron: url("data:image/svg+xml,...");
|
|
245
248
|
--icon-check: url("data:image/svg+xml,...");
|
|
246
249
|
--icon-close: url("data:image/svg+xml,...");
|
|
250
|
+
--icon-plus: url("data:image/svg+xml,...");
|
|
247
251
|
}
|
|
248
252
|
```
|
|
249
253
|
|
|
@@ -272,12 +276,14 @@ Under `forced-colors: active`, `--backdrop-fill` maps to `Canvas`.
|
|
|
272
276
|
|
|
273
277
|
A small z-index scale orders non-dialog overlays. Native `<dialog>` elements (modal, drawer) render on the platform top-layer, which has no numeric z-index and always paints above the page — they never compete with this scale.
|
|
274
278
|
|
|
275
|
-
| Token | Value | Used by
|
|
276
|
-
|
|
277
|
-
| `--z-sticky` | 10 |
|
|
278
|
-
| `--z-menu` | 20 | Floating menus (`flyout`)
|
|
279
|
-
| `--z-tooltip` | 50 | Tooltips
|
|
280
|
-
| `--z-status` | 60 | `status-bar
|
|
279
|
+
| Token | Value | Used by |
|
|
280
|
+
| ------------- | ----- | ------------------------------- |
|
|
281
|
+
| `--z-sticky` | 10 | `form-actions.sticky`, `topbar` |
|
|
282
|
+
| `--z-menu` | 20 | Floating menus (`flyout`) |
|
|
283
|
+
| `--z-tooltip` | 50 | Tooltips |
|
|
284
|
+
| `--z-status` | 60 | `status-bar` |
|
|
285
|
+
|
|
286
|
+
`.surface-backdrop` sits just under the menus, at `calc(var(--z-menu) - 1)`.
|
|
281
287
|
|
|
282
288
|
Stacking-context traps: a flyout or tooltip that is a DOM descendant of a dialog, or of a container with `transform`, `filter`, `contain`, `isolation`, or `will-change`, is confined to that ancestor's stacking context. Its z-index token only orders it against siblings within that context. When a dialog's top-layer clips a descendant flyout, move the flyout markup outside the dialog or use a portal/popover to escape the stacking context.
|
|
283
289
|
|
|
@@ -294,6 +300,7 @@ The shared visual variants are:
|
|
|
294
300
|
- `.solid`: full background, paired foreground. This is the default for buttons.
|
|
295
301
|
- `.soft`: lightly tinted background, colored text. Good for alerts, badges, and secondary actions.
|
|
296
302
|
- `.outline`: transparent background, colored border and text.
|
|
303
|
+
- `.surface`: the page surface with the theme border, and the intent only in the text. The neutral chrome neither `.soft` (the intent-tinted treatment) nor `.outline` (no fill) can give.
|
|
297
304
|
|
|
298
305
|
Buttons also support two button-only variants:
|
|
299
306
|
|
|
@@ -66,7 +66,7 @@ documentation homepages) import it manually:
|
|
|
66
66
|
The module exposes three size tokens and three composed classes. It is deliberately not the foundation: body text, app UI, and the default prose scale stay static.
|
|
67
67
|
|
|
68
68
|
| Token | Class | Purpose |
|
|
69
|
-
|
|
69
|
+
| ----------------- | --------------- | ------------------------------------- |
|
|
70
70
|
| `--fluid-display` | `.text-display` | Hero / display sizes. |
|
|
71
71
|
| `--fluid-title` | `.text-title` | Section titles. |
|
|
72
72
|
| `--fluid-lead` | `.text-lead` | Intro paragraphs on display surfaces. |
|
|
@@ -77,7 +77,15 @@ There is also a non-fluid `.lead` utility in the core, for a simple readable int
|
|
|
77
77
|
|
|
78
78
|
Global links are intentionally neutral. Only `.prose` styles them as prose links, and only components style their own link-like elements (nav links, button-as-link, tabs, breadcrumbs, etc.). The reason is that underlining every `a` globally fights against button-like links, nav links, clickable cards, menu items, and tab triggers. Components that need link semantics should opt in with their own rule.
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
`--link` is the theme-level link ink. It is unset by default, so a bare `a` inherits its color and `.prose` links fall back to `--primary` — nothing changes until a theme opts in. Setting it is that opt-in, and it reaches both places at once:
|
|
81
|
+
|
|
82
|
+
```css
|
|
83
|
+
:root {
|
|
84
|
+
--link: var(--primary); /* bare links become link-colored, prose included */
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The `.prose` fallback to `--primary` breaks down for a theme whose primary is a light or fully saturated accent: it can carry a filled button, where it is the background under its own `--primary-fg`, but not inline body text, where it has to hold contrast against `--surface` on its own. `--link` is the override for exactly that case — hover included, with no rule to restate.
|
|
81
89
|
|
|
82
90
|
```css
|
|
83
91
|
[data-theme="vivid"] {
|
|
@@ -133,7 +141,7 @@ There is no `--line-height-normal`. It would be redundant with `--line-height`.
|
|
|
133
141
|
- `--prose-line-height` — body line height inside `.prose`.
|
|
134
142
|
- `--prose-heading-line-height` — heading line height inside `.prose`.
|
|
135
143
|
- `--prose-flow` — vertical rhythm between sibling blocks inside `.prose`.
|
|
136
|
-
- `--link` —
|
|
144
|
+
- `--link` — theme-level link ink, listed here because `.prose` is its main consumer. Unset, bare links inherit and prose links fall back to `--primary`.
|
|
137
145
|
|
|
138
146
|
## text-wrap
|
|
139
147
|
|
|
@@ -43,7 +43,7 @@ Remove the compatibility mechanism when Bootstrap is gone. The public Actual API
|
|
|
43
43
|
Many common Bootstrap components translate directly.
|
|
44
44
|
|
|
45
45
|
| Bootstrap | Actual CSS |
|
|
46
|
-
|
|
46
|
+
| -------------------------- | ----------------------- |
|
|
47
47
|
| `.btn .btn-primary` | `.btn .primary` |
|
|
48
48
|
| `.btn .btn-outline-danger` | `.btn .danger .outline` |
|
|
49
49
|
| `.btn .btn-sm` | `.btn .sm` |
|
|
@@ -101,7 +101,7 @@ Actual:
|
|
|
101
101
|
Common translations include:
|
|
102
102
|
|
|
103
103
|
| Bootstrap | Actual CSS |
|
|
104
|
-
|
|
104
|
+
| ----------------------------- | ------------------------------ |
|
|
105
105
|
| `.form-control` on an input | `.input` |
|
|
106
106
|
| `.form-control` on a textarea | `.textarea` |
|
|
107
107
|
| `.form-select` | `.select` |
|
|
@@ -213,7 +213,7 @@ Think in terms of the relationship between children rather than translating each
|
|
|
213
213
|
Typical choices are:
|
|
214
214
|
|
|
215
215
|
| Bootstrap pattern | Actual approach |
|
|
216
|
-
|
|
216
|
+
| ------------------------------------------ | ------------------------------------------ |
|
|
217
217
|
| flex row that may wrap | `.cluster` |
|
|
218
218
|
| vertical flex stack | `.stack` |
|
|
219
219
|
| exact structural columns | `.grid-2`, `.grid-3`, `.grid-4`, `.grid-6` |
|
|
@@ -75,7 +75,7 @@ Actual CSS uses a small unprefixed class grammar:
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
Intents are `.primary`, `.secondary`, `.success`, `.warning`, and `.danger`, and
|
|
78
|
-
work across components. Variants such as `.solid`, `.soft`, and `.
|
|
78
|
+
work across components. Variants such as `.solid`, `.soft`, `.outline`, and `.surface` are
|
|
79
79
|
shared by buttons, badges, alerts, and cards; `.inverted` is a shared surface
|
|
80
80
|
modifier that paints any block with the inverse surface. `.ghost` and `.link`
|
|
81
81
|
are button-only. Size variants `.sm` and `.lg` scale controls consistently.
|
|
@@ -140,7 +140,7 @@ internal design documents for contributors.
|
|
|
140
140
|
Actual CSS is built around progressive enhancement.
|
|
141
141
|
|
|
142
142
|
| Tier | Firefox | Safari | Chromium |
|
|
143
|
-
|
|
143
|
+
| ------------ | ------- | --------- | -------- |
|
|
144
144
|
| Degraded | 78+ | 14+ | 88+ |
|
|
145
145
|
| **Minimal** | **98+** | **15.4+** | **99+** |
|
|
146
146
|
| Intermediate | 121+ | 16+ | 106+ |
|
|
@@ -29,16 +29,27 @@ When an interactive state replaces the outline, it must preserve a visible focus
|
|
|
29
29
|
|
|
30
30
|
## Family manifests
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
Each family is one import. The contents are enumerations rather than table
|
|
33
|
+
cells, so they read as a list:
|
|
34
|
+
|
|
35
|
+
- **Core** — `actual-css/css`
|
|
36
|
+
reset, tokens, theme, base, intents, variants, focus, print
|
|
37
|
+
- **Typography** — `actual-css/css/typography`
|
|
38
|
+
prose, overline, fluid
|
|
39
|
+
- **Layout** — `actual-css/css/layout`
|
|
40
|
+
stack, cluster, center, frame, media, switcher, sidebar-layout, grid,
|
|
41
|
+
scroller, scroll-snap, topbar, container-query, app-shell
|
|
42
|
+
- **Forms** — `actual-css/css/forms`
|
|
43
|
+
native control baseline
|
|
44
|
+
- **Forms (complete)** — `actual-css/css/forms/all`
|
|
45
|
+
base plus input-icon, switch, range, choice-card, custom-select,
|
|
46
|
+
floating-field, otp
|
|
47
|
+
- **Components** — `actual-css/css/components`
|
|
48
|
+
buttons, surfaces, overlays, feedback, navigation, data and composed controls
|
|
49
|
+
- **Effects** — `actual-css/css/effects`
|
|
50
|
+
aura
|
|
51
|
+
- **Utilities** — `actual-css/css/utilities`
|
|
52
|
+
base and extra utilities
|
|
42
53
|
|
|
43
54
|
Individual modules can be imported through their domain path:
|
|
44
55
|
|