actual-css 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +214 -1
- package/README.md +13 -11
- package/components.json +668 -0
- package/dist/actual.css +166 -37
- package/dist/actual.full.css +1005 -550
- package/dist/actual.full.js +1 -1
- package/dist/actual.full.min.css +1 -1
- package/dist/actual.js +1 -1
- package/dist/actual.min.css +1 -1
- package/docs/design-notes/accessibility-decisions.md +33 -0
- package/docs/design-notes/browser-support.md +82 -25
- package/docs/design-notes/column-layout.md +3 -3
- package/docs/design-notes/css-anchor.md +75 -21
- package/docs/design-notes/enhancement-contract.md +14 -6
- package/docs/design-notes/grid.md +4 -4
- package/docs/design-notes/naming.md +6 -1
- package/docs/design-notes/platform-alignment.md +99 -2
- package/docs/design-notes/popover-manual-poc.md +328 -0
- package/docs/design-notes/surface-reparenting.md +131 -0
- package/docs/design-notes/tooltip-coordinate-space.md +132 -0
- package/docs/design-notes/widget-primitives.md +9 -6
- package/docs/pages/components/accordion.md +41 -2
- package/docs/pages/components/alert.md +80 -30
- package/docs/pages/components/app-navigation.md +6 -0
- package/docs/pages/components/avatar.md +6 -6
- package/docs/pages/components/badge.md +101 -16
- package/docs/pages/components/button.md +16 -8
- package/docs/pages/components/card.md +10 -10
- package/docs/pages/components/dialog.md +16 -6
- package/docs/pages/components/fab.md +4 -3
- package/docs/pages/components/list.md +42 -4
- package/docs/pages/components/navbar.md +17 -1
- package/docs/pages/components/pagination.md +2 -2
- package/docs/pages/components/steps.md +19 -0
- package/docs/pages/components/table.md +3 -2
- package/docs/pages/enhancements/flyout.md +144 -24
- package/docs/pages/enhancements/overview.md +25 -0
- package/docs/pages/enhancements/status-bar.md +20 -0
- package/docs/pages/enhancements/tabs.md +45 -37
- package/docs/pages/enhancements/tooltip.md +40 -2
- package/docs/pages/examples/overview.md +38 -5
- package/docs/pages/forms/choice-cards.md +6 -2
- package/docs/pages/forms/combobox.md +1 -1
- package/docs/pages/forms/floating-field.md +4 -3
- package/docs/pages/forms/joined-controls.md +22 -0
- package/docs/pages/forms/otp.md +2 -1
- package/docs/pages/forms/overview.md +1 -1
- package/docs/pages/forms/states-and-sizes.md +16 -18
- package/docs/pages/forms/sticky-actions.md +2 -2
- package/docs/pages/forms/switch.md +1 -1
- package/docs/pages/foundations/philosophy.md +67 -22
- package/docs/pages/foundations/theming.md +10 -2
- package/docs/pages/foundations/tokens.md +118 -21
- package/docs/pages/foundations/typography.md +35 -14
- package/docs/pages/guides/introduction.md +11 -9
- package/docs/pages/guides/progressive-enhancement.md +136 -49
- package/docs/pages/guides/tailwind.md +3 -2
- package/docs/pages/layout/media.md +1 -1
- package/docs/pages/layout/overview.md +11 -1
- package/docs/pages/layout/scroll-snap.md +3 -3
- package/docs/pages/layout/stack.md +17 -9
- package/docs/pages/patterns/icon-input.md +4 -2
- package/docs/pages/patterns/icon-slot.md +2 -0
- package/docs/pages/patterns/intent-nesting.md +1 -1
- package/docs/pages/utilities/overview.md +23 -2
- package/docs/pages/utilities/sizing-wrapping.md +1 -1
- package/docs/pages/utilities/spacing.md +10 -8
- package/llms.txt +2 -1
- package/package.json +19 -8
- package/{scripts/reserved-classes.json → reserved-classes.json} +4 -6
- package/src/css/components/accordion.css +42 -3
- package/src/css/components/alert.css +25 -13
- package/src/css/components/app-nav.css +18 -8
- package/src/css/components/avatar.css +13 -1
- package/src/css/components/badge.css +78 -12
- package/src/css/components/breadcrumb.css +2 -3
- package/src/css/components/button.css +9 -16
- package/src/css/components/card.css +9 -2
- package/src/css/components/chat.css +1 -0
- package/src/css/components/data-list.css +1 -1
- package/src/css/components/drawer.css +79 -25
- package/src/css/components/fab.css +0 -6
- package/src/css/components/flyout.css +46 -63
- package/src/css/components/index.css +0 -1
- package/src/css/components/indicator.css +21 -0
- package/src/css/components/join.css +7 -0
- package/src/css/components/key.css +10 -0
- package/src/css/components/list.css +40 -4
- package/src/css/components/menu.css +18 -11
- package/src/css/components/modal.css +48 -33
- package/src/css/components/navbar.css +37 -4
- package/src/css/components/pagination.css +1 -0
- package/src/css/components/spinner.css +6 -6
- package/src/css/components/status-bar.css +0 -5
- package/src/css/components/steps.css +45 -59
- package/src/css/components/tab.css +29 -9
- package/src/css/components/table.css +5 -5
- package/src/css/components/tooltip.css +45 -13
- package/src/css/core/base.css +23 -1
- package/src/css/core/intents.css +17 -6
- package/src/css/core/theme.css +27 -0
- package/src/css/core/tokens.css +35 -15
- package/src/css/core/variants.css +64 -15
- package/src/css/forms/choice-card.css +4 -4
- package/src/css/forms/choice.css +6 -3
- package/src/css/forms/control.css +2 -1
- package/src/css/forms/floating-field.css +3 -3
- package/src/css/forms/form.css +4 -3
- package/src/css/forms/input-icon.css +20 -14
- package/src/css/forms/native.css +6 -1
- package/src/css/forms/otp.css +9 -1
- package/src/css/forms/range.css +2 -0
- package/src/css/forms/select.css +29 -9
- package/src/css/forms/switch.css +19 -5
- package/src/css/layout/app-layout.css +1 -1
- package/src/css/layout/grid.css +50 -76
- package/src/css/layout/scroll-snap.css +11 -7
- package/src/css/layout/scroller.css +3 -4
- package/src/css/layout/stack.css +2 -2
- package/src/css/typography/fluid.css +4 -3
- package/src/css/typography/prose.css +6 -5
- package/src/css/utilities/base.css +2 -1
- package/src/css/utilities/extra.css +20 -17
- package/src/js/context-menu.js +27 -26
- package/src/js/dialog.js +2 -1
- package/src/js/dismiss.js +5 -0
- package/src/js/enhance.js +34 -2
- package/src/js/enhancement-loader.js +36 -43
- package/src/js/events.js +0 -3
- package/src/js/filter.js +0 -1
- package/src/js/floating-space.js +42 -0
- package/src/js/flyout.js +9 -44
- package/src/js/focus-group.js +7 -0
- package/src/js/focus.js +6 -0
- package/src/js/menu.js +10 -1
- package/src/js/selectors.js +5 -9
- package/src/js/status.js +44 -7
- package/src/js/surface.js +106 -132
- package/src/js/tab.js +6 -1
- package/src/js/tooltip.js +152 -53
- package/src/js/validation.js +1 -1
- package/src/css/components/surface.css +0 -49
- package/src/js/floating.js +0 -432
|
@@ -9,19 +9,52 @@ and `actual.full.js` from `dist/`, plus the theme palettes bundle from
|
|
|
9
9
|
|
|
10
10
|
## Templates
|
|
11
11
|
|
|
12
|
-
`demo/templates/` are standalone pages
|
|
12
|
+
`demo/templates/` are standalone pages. The first three explain the system; the
|
|
13
|
+
rest show it composed, isolated, or under stress.
|
|
14
|
+
|
|
15
|
+
### Start here
|
|
16
|
+
|
|
17
|
+
- [Visual guide](../../demo/templates/visual-guide.html) - seventeen illustrated figures on the spacing scale, the layout primitives, and density versus local size
|
|
18
|
+
- [Color guide](../../demo/templates/color-guide.html) - theming principles measured live on `ocean` and `sunset`, in light and dark, as `data-theme` islands
|
|
19
|
+
- [Kitchen sink](../../demo/templates/kitchen-sink.html) - one-screen test bed for themes, scopes, variants and interactions
|
|
20
|
+
|
|
21
|
+
### Page shapes
|
|
22
|
+
|
|
23
|
+
Whole pages, composed the way a real product would.
|
|
13
24
|
|
|
14
|
-
- [Kitchen sink](../../demo/templates/kitchen-sink.html) - every component and variant on one page
|
|
15
|
-
- [Keyboard controls](../../demo/templates/keyboard-controls.html) - hands-on keyboard support matrix and focus test bench
|
|
16
|
-
- [Surface contracts](../../demo/templates/surfaces.html) - .inverted, cascade precedence, and the intent boundary
|
|
17
25
|
- [Dashboard](../../demo/templates/dashboard.html) - data-heavy overview page
|
|
18
26
|
- [App](../../demo/templates/app.html) - application shell with sidebar
|
|
27
|
+
- [Workspaces](../../demo/templates/workspaces.html) - sectioned sidebar, master/detail list with native current state, and workspace cards
|
|
19
28
|
- [Marketing](../../demo/templates/marketing.html) - landing page with typography and fluid type
|
|
20
29
|
- [Blog](../../demo/templates/blog.html) - article page with prose
|
|
21
|
-
- [
|
|
30
|
+
- [Settings modal](../../demo/templates/settings-modal.html) - two-pane preferences dialog, with the local CSS it needs audited rule by rule
|
|
31
|
+
- [Workspace settings](../../demo/templates/settings-pricing.html) - plans with visible native choices, preferences and a local segmented tab treatment
|
|
32
|
+
- [Card compositions](../../demo/templates/card-compositions.html) - editorial, team, sign-in and horizontal cards composed from existing primitives
|
|
33
|
+
|
|
34
|
+
### Layout references
|
|
35
|
+
|
|
36
|
+
One mechanism at a time, with its contract and its pitfalls.
|
|
37
|
+
|
|
22
38
|
- [Layout reference](../../demo/templates/layouts.html) - canonical compositions built only with the layout primitives
|
|
39
|
+
- [Blocks](../../demo/templates/blocks.html) - layout building blocks
|
|
23
40
|
- [Grid density](../../demo/templates/grid.html) - the grid contracts on resizable stages, with the pitfalls called out
|
|
41
|
+
- [Column layout](../../demo/templates/column-layout.html) - the twelve-column canvas: spans, starts, and the narrow-container recomposition the framework leaves to the application
|
|
24
42
|
- [Density](../../demo/templates/density.html) - compact control density
|
|
43
|
+
|
|
44
|
+
### System benches
|
|
45
|
+
|
|
46
|
+
Contracts you cannot read off a static screenshot: state, motion, focus, and
|
|
47
|
+
extension points.
|
|
48
|
+
|
|
49
|
+
- [Surface contracts](../../demo/templates/surfaces.html) - `.inverted`, cascade precedence, and the intent boundary
|
|
50
|
+
- [Presence motion](../../demo/templates/motion.html) - status bar, tooltip, flyout, modal and drawer replayed side by side, with easing swaps and a reduced-motion simulation
|
|
51
|
+
- [Keyboard controls](../../demo/templates/keyboard-controls.html) - hands-on keyboard support matrix and focus test bench
|
|
52
|
+
- [Adaptive filter surface](../../demo/templates/adaptive-surface.html) - app-level flyout/drawer composition with one synchronized filter state
|
|
53
|
+
- [Select intents](../../demo/templates/select-intents.html) - extending the enhancer with a project's own `data-enhance` behavior, injected markup included, with no framework change
|
|
54
|
+
- [Popover transport probe](../../demo/templates/popover-transport.html) - self-scoring bench for the native popover transport go/no-go
|
|
55
|
+
|
|
56
|
+
### Third-party components on Actual tokens
|
|
57
|
+
|
|
25
58
|
- [Data grid](../../demo/templates/data-grid.html) - an external data grid component themed with Actual tokens (sort, filter, search, selection)
|
|
26
59
|
- [Combobox](../../demo/templates/combobox.html) - an external combobox themed with Actual tokens (search, tags, autocomplete)
|
|
27
60
|
|
|
@@ -88,7 +88,10 @@ Validation follows the shared pattern: `aria-invalid="true"` on the input (set m
|
|
|
88
88
|
</fieldset>
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
Sizes follow the shared `.sm` and `.lg`
|
|
91
|
+
Sizes follow the shared `.sm` and `.lg` typography scale; the check indicator
|
|
92
|
+
follows through its `em` sizing. Padding is density, so use a `.compact` or
|
|
93
|
+
`.spacious` context to change it. Intent classes (`.primary`, `.secondary`) are
|
|
94
|
+
supported on the `.choice-card` element.
|
|
92
95
|
|
|
93
96
|
## CSS hooks
|
|
94
97
|
|
|
@@ -100,7 +103,8 @@ Plain `.check` / `.radio` controls expose two hooks:
|
|
|
100
103
|
|
|
101
104
|
- `--choice-control-size` — the control's own size, in `em` off the surrounding
|
|
102
105
|
type. The switch track derives from it too, so a checkbox and a switch on the
|
|
103
|
-
same line stay proportionate. `.sm`
|
|
106
|
+
same line stay proportionate. A `.choice.sm` or `.choice.lg` scales it through
|
|
107
|
+
the surrounding typography.
|
|
104
108
|
- `--choice-control-offset` — top offset that aligns the control with the first
|
|
105
109
|
line of a multi-line label. Left unset, each control derives its own offset
|
|
106
110
|
from its height and the line box, which keeps a checkbox and a taller switch
|
|
@@ -75,7 +75,7 @@ contrast contracts apply to the combobox for free:
|
|
|
75
75
|
background: color-mix(in oklab, var(--surface) var(--soft-bg-mix), var(--primary));
|
|
76
76
|
color: color-mix(in oklab, var(--primary) var(--soft-fg-mix), var(--text));
|
|
77
77
|
font-size: var(--font-size-xs);
|
|
78
|
-
font-weight: var(--font-weight-
|
|
78
|
+
font-weight: var(--font-weight-semibold);
|
|
79
79
|
}
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -68,11 +68,12 @@ every state, so their label always sits at the top.
|
|
|
68
68
|
</div>
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
##
|
|
71
|
+
## Size and density
|
|
72
72
|
|
|
73
73
|
The reserved headroom responds to control density through `--control-size`:
|
|
74
|
-
`.sm` and `.lg` on the cell
|
|
75
|
-
|
|
74
|
+
`.sm` and `.lg` on the cell resize the control geometry and typography. A
|
|
75
|
+
`.compact` or `.spacious` ancestor changes geometry only, including the label
|
|
76
|
+
spacing with it; typography stays unchanged under density.
|
|
76
77
|
The floating label does add height — the headroom reserves a second vertical
|
|
77
78
|
line on top of the control's minimum size.
|
|
78
79
|
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
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.
|
|
15
15
|
|
|
16
|
+
`.join` reshapes corners and shared edges; it does not unify the segments' treatments, and the children keep whatever classes they carry. Give them one variant family so the group reads as a single unit, and change a segment's variant only to mark state — a solid button among outlines for the active segment of a segmented control. A group mixing `.btn`, `.btn outline` and `.btn soft` is valid markup that renders as three unrelated controls stuck together.
|
|
17
|
+
|
|
16
18
|
When composing source files manually, import `components/join.css` after the controls it groups. `.join` writes child border-radius longhands directly so joined corners win at equal specificity.
|
|
17
19
|
|
|
18
20
|
```html demo
|
|
@@ -33,6 +35,26 @@ the focus ring surrounds the complete joined field. Attached buttons keep their
|
|
|
33
35
|
own focus indicator when reached directly, so the actionable segment remains
|
|
34
36
|
identifiable.
|
|
35
37
|
|
|
38
|
+
## Linting `role="group"`
|
|
39
|
+
|
|
40
|
+
Biome's `a11y/useSemanticElements` reports the wrapper and offers `<fieldset>`
|
|
41
|
+
as the replacement. That is the only element it suggests, and it does not fit:
|
|
42
|
+
`<fieldset>` groups form controls under a `<legend>`, while ARIA's `group` is
|
|
43
|
+
any labelled set of related objects. Suppress it on the element:
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<!-- biome-ignore lint/a11y/useSemanticElements: ARIA group has no HTML
|
|
47
|
+
equivalent here; fieldset expects form controls under a legend. -->
|
|
48
|
+
<div class="join" role="group" aria-label="Date navigation">
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Unlike the menu rule in
|
|
52
|
+
[flyout](../enhancements/flyout.html#linting-rolemenu), do not switch this one
|
|
53
|
+
off globally: it correctly catches `<div role="navigation">`,
|
|
54
|
+
`<div role="button">` and `<div role="separator">`. And drop `role="group"`
|
|
55
|
+
rather than suppressing it when the wrapper has no label to give — an unnamed
|
|
56
|
+
group adds a boundary and nothing else.
|
|
57
|
+
|
|
36
58
|
## CSS hooks
|
|
37
59
|
|
|
38
60
|
- `--join-radius` — outer corner radius of the joined group. The per-corner
|
package/docs/pages/forms/otp.md
CHANGED
|
@@ -36,7 +36,8 @@ Add exactly one visual `span` per expected character. Their count must match
|
|
|
36
36
|
a numeric keyboard but does not enforce numeric input; validate the submitted
|
|
37
37
|
value as usual.
|
|
38
38
|
|
|
39
|
-
The component follows shared `.sm` and `.lg`
|
|
39
|
+
The component follows shared `.sm` and `.lg` size through `--control-size` and
|
|
40
|
+
`--control-font-size`.
|
|
40
41
|
Use `aria-invalid="true"` for explicit invalid state, or place it in the
|
|
41
42
|
standard `.needs-validation.was-validated` form flow.
|
|
42
43
|
|
|
@@ -98,7 +98,7 @@ A full form using the control classes, field wrappers, and form actions:
|
|
|
98
98
|
|
|
99
99
|
<fieldset class="field-group">
|
|
100
100
|
<legend class="field-label">Availability</legend>
|
|
101
|
-
<div class="stack
|
|
101
|
+
<div class="stack compact">
|
|
102
102
|
<label class="choice">
|
|
103
103
|
<input class="radio" type="radio" name="availability" value="available" checked />
|
|
104
104
|
<span>Available for work</span>
|
|
@@ -4,23 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
## Class reference
|
|
6
6
|
|
|
7
|
-
| Class | Kind | Description
|
|
8
|
-
| ----- | -------- |
|
|
9
|
-
| `.sm` | Modifier |
|
|
10
|
-
| `.lg` | Modifier |
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
| ----- | -------- | ---------------------------------------- |
|
|
9
|
+
| `.sm` | Modifier | Smaller control geometry and typography. |
|
|
10
|
+
| `.lg` | Modifier | Larger control geometry and typography. |
|
|
11
11
|
|
|
12
|
-
Each
|
|
12
|
+
Each maps `--control-size` and `--control-font-size` to the matching step.
|
|
13
13
|
|
|
14
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.
|
|
15
15
|
|
|
16
|
-
The `.sm` and `.lg` modifiers set the shared control tokens used by inputs,
|
|
16
|
+
The `.sm` and `.lg` modifiers set the shared control tokens used by inputs,
|
|
17
|
+
selects, textareas, buttons, and inline choices. Put the modifier on the control
|
|
18
|
+
itself, or on a `.field` wrapper when the whole field should share that size.
|
|
17
19
|
|
|
18
|
-
Inline choices — `.check`, `.radio`, `.switch` —
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
without its label would only break the alignment. Scale them by scaling their
|
|
23
|
-
type instead.
|
|
20
|
+
Inline choices — `.check`, `.radio`, `.switch` — sit on a line of text, so their
|
|
21
|
+
geometry follows the local control typography through `--choice-control-size`.
|
|
22
|
+
Apply `.sm` or `.lg` to the `.choice` wrapper so its label and control scale
|
|
23
|
+
together. Density contexts leave both unchanged.
|
|
24
24
|
|
|
25
25
|
```html demo
|
|
26
26
|
<form class="stack" novalidate>
|
|
@@ -276,12 +276,11 @@ type instead.
|
|
|
276
276
|
<button class="btn outline lg" type="button">Large</button>
|
|
277
277
|
</div>
|
|
278
278
|
|
|
279
|
-
<!--
|
|
280
|
-
identical even though the modifiers differ. -->
|
|
279
|
+
<!-- Size belongs on the choice wrapper so label and control move together. -->
|
|
281
280
|
<div class="grid items-start">
|
|
282
281
|
<label class="choice sm">
|
|
283
282
|
<input class="check" type="checkbox" checked />
|
|
284
|
-
<span
|
|
283
|
+
<span>Small checkbox</span>
|
|
285
284
|
</label>
|
|
286
285
|
<label class="choice">
|
|
287
286
|
<input class="radio" type="radio" name="demo-radio-size" checked />
|
|
@@ -289,7 +288,7 @@ type instead.
|
|
|
289
288
|
</label>
|
|
290
289
|
<label class="choice lg">
|
|
291
290
|
<input class="switch" type="checkbox" role="switch" checked />
|
|
292
|
-
<span
|
|
291
|
+
<span>Large switch</span>
|
|
293
292
|
</label>
|
|
294
293
|
<label class="choice">
|
|
295
294
|
<input class="check" type="checkbox" id="indet-size" />
|
|
@@ -297,8 +296,7 @@ type instead.
|
|
|
297
296
|
</label>
|
|
298
297
|
</div>
|
|
299
298
|
|
|
300
|
-
<!--
|
|
301
|
-
together, so the alignment survives. -->
|
|
299
|
+
<!-- The underlying typography hook remains available for custom scales. -->
|
|
302
300
|
<div class="grid items-start" style="--control-font-size: var(--font-size-sm);">
|
|
303
301
|
<label class="choice">
|
|
304
302
|
<input class="check" type="checkbox" checked />
|
|
@@ -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 compact">
|
|
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 compact">
|
|
145
145
|
<label class="choice">
|
|
146
146
|
<input class="radio" type="radio" name="theme-detached" value="light" checked />
|
|
147
147
|
<span>Light</span>
|
|
@@ -62,7 +62,7 @@ naturally or via an explicit line break — still sit cleanly.
|
|
|
62
62
|
|
|
63
63
|
A switch is sized off the control typography, not field density. Its track
|
|
64
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.
|
|
65
|
+
— so the three sit on a line of text at matching weight. Density contexts change
|
|
66
66
|
`--control-size`, which is field height, and deliberately leave inline choices
|
|
67
67
|
alone.
|
|
68
68
|
|
|
@@ -29,12 +29,15 @@ There is no `.btn-primary` or `.badge-success`. Intents are generic and reusable
|
|
|
29
29
|
|
|
30
30
|
Components fall back to their own default intent when no intent class is set. Buttons, badges, and alerts use the neutral palette (`--neutral` / `--neutral-fg`) by default.
|
|
31
31
|
|
|
32
|
-
Custom intents need no framework support — define `--intent` and `--intent-fg`
|
|
32
|
+
Custom intents need no framework support — define `--intent` and `--intent-fg`
|
|
33
|
+
(and `--intent-soft-fg` when the custom role needs its own soft foreground) on a
|
|
34
|
+
class:
|
|
33
35
|
|
|
34
36
|
```css
|
|
35
37
|
.tertiary {
|
|
36
38
|
--intent: var(--tertiary);
|
|
37
39
|
--intent-fg: var(--tertiary-fg);
|
|
40
|
+
--intent-soft-fg: var(--tertiary-soft-fg);
|
|
38
41
|
}
|
|
39
42
|
```
|
|
40
43
|
|
|
@@ -52,44 +55,86 @@ Custom intents need no framework support — define `--intent` and `--intent-fg`
|
|
|
52
55
|
`.ghost` and `.link` are button-only variants.
|
|
53
56
|
|
|
54
57
|
```html demo
|
|
55
|
-
<
|
|
56
|
-
<
|
|
57
|
-
<
|
|
58
|
+
<div class="stack">
|
|
59
|
+
<div class="cluster">
|
|
60
|
+
<button class="btn soft primary">Soft primary</button>
|
|
61
|
+
<span class="badge outline success">Outline success</span>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="alert solid warning">Solid warning</div>
|
|
64
|
+
</div>
|
|
58
65
|
```
|
|
59
66
|
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
`.sm` and `.lg`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
## Size and density
|
|
68
|
+
|
|
69
|
+
`.sm` and `.lg` mean one size role below or above a component's natural size.
|
|
70
|
+
Size names are shared roles, not shared measurements. Each participating
|
|
71
|
+
component family maps them to its own optical scale: badges use `xs / sm / md`,
|
|
72
|
+
while controls use `sm / md / lg`. Components without an explicit mapping do
|
|
73
|
+
not change.
|
|
74
|
+
|
|
75
|
+
A size role is applied to the component that participates in the scale and
|
|
76
|
+
never styles arbitrary descendants. It propagates through token inheritance,
|
|
77
|
+
though: components in the shared control scale set local `--control-size` and
|
|
78
|
+
`--control-font-size`, and descendants consume them by their own rules. That is
|
|
79
|
+
how `.field sm`, `.input-icon sm`, `.join sm`, and `.flyout sm` size the
|
|
80
|
+
controls inside them, while a bare `.sm` on a plain element does nothing.
|
|
81
|
+
|
|
82
|
+
`.compact` and `.spacious` establish inherited density tokens. Density arranges
|
|
83
|
+
how tightly UI sits — spacing and component geometry — while typography and
|
|
84
|
+
icon size stay unchanged. Participation is opt-in, and a component only joins
|
|
85
|
+
where density has an effect independent from its optical size: if the result is
|
|
86
|
+
merely that the component looks smaller or larger, that is size, not density.
|
|
87
|
+
|
|
88
|
+
Density participation takes three levels:
|
|
89
|
+
|
|
90
|
+
- **Geometry + rhythm** — controls and their wrappers (`.field`, `.join`,
|
|
91
|
+
`.flyout`, …). Height, padding, and gap respond; typography is untouched.
|
|
92
|
+
- **Rhythm only** — content rows and shells such as `.list`. Spacing tightens
|
|
93
|
+
(`--list-item-gap: var(--gap)`), but the structural size stays stable.
|
|
94
|
+
- **No density effect** — components whose geometry is intrinsic to their
|
|
95
|
+
content (`.badge`, `.avatar`, `.spinner`, `.rating`, `.key`, prose, inline
|
|
96
|
+
`.choice`/`.switch`). Their optical size belongs to `sm`/`lg` or local hooks.
|
|
67
97
|
|
|
68
98
|
As inherited contexts, one class tightens or loosens the whole subtree:
|
|
69
99
|
|
|
70
100
|
```html demo
|
|
71
|
-
<div class="
|
|
101
|
+
<div class="compact stack">
|
|
72
102
|
<button class="btn">Compact button</button>
|
|
73
103
|
<input class="input">
|
|
74
104
|
<span class="badge">Compact badge</span>
|
|
75
105
|
</div>
|
|
76
106
|
```
|
|
77
107
|
|
|
78
|
-
|
|
108
|
+
Application chrome can use the same scope:
|
|
79
109
|
|
|
80
110
|
```html demo
|
|
81
|
-
<
|
|
82
|
-
<
|
|
111
|
+
<header class="navbar compact">
|
|
112
|
+
<a class="navbar-brand" href="/">Workspace</a>
|
|
113
|
+
<nav class="cluster" aria-label="Workspace actions">
|
|
114
|
+
<button class="btn ghost">Search</button>
|
|
115
|
+
<button class="btn primary">Create</button>
|
|
116
|
+
</nav>
|
|
117
|
+
</header>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Component geometry remains local and wins over inherited density when both
|
|
121
|
+
affect the same dimension:
|
|
122
|
+
|
|
123
|
+
```html demo
|
|
124
|
+
<div class="compact">
|
|
125
|
+
<button class="btn lg">Large button in a compact context</button>
|
|
126
|
+
</div>
|
|
83
127
|
```
|
|
84
128
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
129
|
+
The density tokens are `--gap`, `--density-space`, and `--control-size`.
|
|
130
|
+
Components consume the dimensions that make sense for them and opt out of the
|
|
131
|
+
rest. The absolute `--space-*` scale is not rebound by density scopes.
|
|
132
|
+
Components with bespoke geometry (`.badge`, `.avatar`,
|
|
133
|
+
`.spinner`, `.rating`) own their local `.sm`/`.lg` mappings.
|
|
90
134
|
|
|
91
|
-
|
|
92
|
-
|
|
135
|
+
`.compact` also remains a meaningful local modifier for `.card` and `.table`.
|
|
136
|
+
On those components it tightens their own padding and establishes the compact
|
|
137
|
+
density context for descendants.
|
|
93
138
|
|
|
94
139
|
## Child semantics
|
|
95
140
|
|
|
@@ -20,7 +20,7 @@ Set `--cluster-align`.
|
|
|
20
20
|
|
|
21
21
|
### Change spacing without changing control size
|
|
22
22
|
|
|
23
|
-
Set `--gap`
|
|
23
|
+
Set `--gap` on the layout primitive to retune it and everything nested. To change only that element's rhythm without reaching nested primitives, set the `gap` property instead.
|
|
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. To rescale the whole row of inline choices at once, set `--choice-control-size`
|
|
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, use `.sm` / `.lg` on `.choice`, or set `--choice-control-size` directly — the checkbox, the radio, and the switch track all follow it. Density contexts leave inline choices alone.
|
|
60
60
|
|
|
61
61
|
→ Forms · Switch
|
|
62
62
|
|
|
@@ -70,6 +70,14 @@ Native controls that no component class restyles — a bare checkbox, radio, ran
|
|
|
70
70
|
|
|
71
71
|
→ Forms · Overview · Foundations · Tokens (theme contract)
|
|
72
72
|
|
|
73
|
+
### Store a theme name without applying it
|
|
74
|
+
|
|
75
|
+
`data-theme` is an active theme boundary on every element that carries it, not
|
|
76
|
+
a generic storage attribute. Use a different name such as `data-theme-value`,
|
|
77
|
+
or a form control's `value`, when the element should only hold a theme name.
|
|
78
|
+
Apply `data-theme` deliberately when that element and its subtree should paint
|
|
79
|
+
with the selected palette — a theme swatch is a useful example.
|
|
80
|
+
|
|
73
81
|
### Loading / busy overlay on a container
|
|
74
82
|
|
|
75
83
|
Use `aria-busy="true"` with a direct last-child `.spinner`; tint the overlay with `--busy-overlay-bg`.
|