actual-css 0.7.0 → 0.9.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 +217 -0
- package/README.md +13 -11
- package/components.json +668 -0
- package/dist/actual.css +166 -37
- package/dist/actual.full.css +1087 -643
- 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 +62 -30
- 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 +53 -7
- package/docs/design-notes/popover-manual-poc.md +105 -25
- package/docs/design-notes/surface-reparenting.md +56 -47
- package/docs/design-notes/tooltip-coordinate-space.md +132 -0
- package/docs/design-notes/widget-primitives.md +7 -4
- package/docs/pages/components/accordion.md +41 -2
- package/docs/pages/components/alert.md +85 -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 +21 -6
- package/docs/pages/components/drawer.md +13 -0
- 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/skeleton.md +3 -1
- package/docs/pages/components/steps.md +19 -0
- package/docs/pages/components/table.md +3 -2
- package/docs/pages/enhancements/flyout.md +82 -38
- package/docs/pages/enhancements/overview.md +25 -0
- package/docs/pages/enhancements/status-bar.md +1 -1
- package/docs/pages/enhancements/tabs.md +45 -37
- package/docs/pages/enhancements/tooltip.md +36 -10
- package/docs/pages/examples/overview.md +38 -5
- package/docs/pages/forms/choice-cards.md +11 -6
- 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 +57 -26
- package/docs/pages/foundations/theming.md +2 -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 +115 -30
- 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 +159 -149
- 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 +101 -32
- package/src/css/components/fab.css +0 -6
- package/src/css/components/flyout.css +35 -98
- package/src/css/components/index.css +0 -1
- package/src/css/components/indicator.css +21 -0
- package/src/css/components/key.css +10 -0
- package/src/css/components/list.css +40 -4
- package/src/css/components/menu.css +2 -1
- 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/skeleton.css +15 -4
- 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 +13 -5
- package/src/css/components/tooltip.css +36 -40
- 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 +76 -29
- 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 +28 -8
- 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 +6 -5
- package/src/js/surface.js +97 -139
- package/src/js/tab.js +6 -1
- package/src/js/tooltip.js +150 -51
- package/src/js/validation.js +1 -1
- package/src/css/components/surface.css +0 -49
|
@@ -38,7 +38,7 @@ It applies everywhere — cards, dialogs, heroes, app shells — not only in pro
|
|
|
38
38
|
|
|
39
39
|
It does not own visual hierarchy. No global `font-size` on headings, no global `font-weight` on headings, no global margins on headings, no global `text-decoration` on links. These choices would shape app UI in ways the framework cannot predict.
|
|
40
40
|
|
|
41
|
-
The mildly opinionated defaults at the baseline are few: line-height on headings (tight, so multi-line headings stay readable), `text-wrap: balance` on headings where supported, the `hr` rule, the `::selection` rule, the `code` / `kbd` / `samp` / `pre` font family, `small` font size, and a global link underline offset that prose and components reuse. Everything else stays neutral so components and `.prose` can take over without fighting the baseline.
|
|
41
|
+
The mildly opinionated defaults at the baseline are few: line-height on headings (tight, so multi-line headings stay readable), `text-wrap: balance` on headings where supported, the `hr` rule, the `::selection` rule, the `code` / `kbd` / `samp` / `pre` font family, `pre` overflow containment, `small` font size, and a global link underline offset that prose and components reuse. Everything else stays neutral so components and `.prose` can take over without fighting the baseline.
|
|
42
42
|
|
|
43
43
|
Global links inherit color. The visual affordance of a link is the responsibility of `.prose` (for authored content) or of a component (for nav links, button-like links, tabs, breadcrumbs, etc.). Underlining every `a` globally would collide with all of those.
|
|
44
44
|
|
|
@@ -54,10 +54,11 @@ The reason for that boundary: a dialog title, a card heading, or a sidebar secti
|
|
|
54
54
|
|
|
55
55
|
### Fluid module
|
|
56
56
|
|
|
57
|
-
`src/css/typography/fluid.css`
|
|
58
|
-
`actual
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
`src/css/typography/fluid.css` ships with the typography family
|
|
58
|
+
(`actual-css/css/typography`) and `actual-css/full`, but not with the minimal
|
|
59
|
+
core. A core-only entry point that needs display, title, and lead sizes that
|
|
60
|
+
scale with the viewport (landing pages, marketing pages, hero sections,
|
|
61
|
+
documentation homepages) imports it explicitly:
|
|
61
62
|
|
|
62
63
|
```css
|
|
63
64
|
@import "actual-css/css/typography/fluid";
|
|
@@ -116,14 +117,14 @@ baseline stays sans so app UI inherits predictably.
|
|
|
116
117
|
|
|
117
118
|
The framework exposes a small set of weights:
|
|
118
119
|
|
|
119
|
-
- `--font-weight` (400) — body default
|
|
120
|
-
- `--font-weight-medium` (500) — slightly heavier than body, for nav links
|
|
121
|
-
- `--font-weight-
|
|
122
|
-
- `--font-weight-bold` (700) — the strongest weight exposed, used by the navbar brand
|
|
120
|
+
- `--font-weight-normal` (400) — body default
|
|
121
|
+
- `--font-weight-medium` (500) — slightly heavier than body, for nav links and accordion summaries
|
|
122
|
+
- `--font-weight-semibold` (600) — emphasis, prose headings, badges, tabs, table headers
|
|
123
|
+
- `--font-weight-bold` (700) — the strongest weight exposed, used by the navbar brand
|
|
123
124
|
|
|
124
125
|
No `--font-weight-light`. Light weights depend on the typeface, are rarely a good default, and add surface area without a recurring need.
|
|
125
126
|
|
|
126
|
-
These weights are also the values used by components. Components
|
|
127
|
+
These weights are also the values used by components. Components reference the tokens instead of literal weights, so theme authors can re-map the scale in one place.
|
|
127
128
|
|
|
128
129
|
## Line heights
|
|
129
130
|
|
|
@@ -159,7 +160,7 @@ Headings are split between the global baseline and `.prose`.
|
|
|
159
160
|
|
|
160
161
|
Globally, headings get a tight line-height, a color from `--heading` (or inherited), and progressive `text-wrap: balance`. They do not get a `font-size`, a `font-weight`, or margins. The reason is that a card heading, a dialog title, or a sidebar section should not be auto-magically enlarged by selector.
|
|
161
162
|
|
|
162
|
-
Inside `.prose`, headings get a `font-weight` from `--font-weight-
|
|
163
|
+
Inside `.prose`, headings get a `font-weight` from `--font-weight-semibold`, a tighter line-height from `--prose-heading-line-height`, margin rhythm, and keep the global `text-wrap: balance`. Their color follows the contextual `--heading` alias, so prose also composes correctly with a contextual surface. The `h1` to `h4` font sizes are scoped to `.prose`, remain low-specificity, and are not exposed as a public scale.
|
|
163
164
|
|
|
164
165
|
The `hgroup` element gets only structural styling: a grid layout, a gap, and a reset of internal margins. No font-size, no color, no weight. Its visual identity is the responsibility of the headings and paragraphs it contains.
|
|
165
166
|
|
|
@@ -175,7 +176,27 @@ Three logical alignment utilities exist (`.text-start`, `.text-center`, `.text-e
|
|
|
175
176
|
|
|
176
177
|
`small` gets a smaller font size globally (`0.875em`) because it is a semantic element, not a utility. There is no `.small` class competing with the element.
|
|
177
178
|
|
|
178
|
-
`code`, `kbd`, `samp`, and `pre` get the mono font family globally.
|
|
179
|
+
`code`, `kbd`, `samp`, and `pre` get the mono font family globally. `pre` also gets `overflow-x: auto`, because one unbreakable line widens the whole page and nothing in the markup warns you. That is containment, not decoration: background, padding, and radius are still left to `.prose` or to a code-block component.
|
|
180
|
+
|
|
181
|
+
For a standalone snippet outside authored content, `.prose` is the ready-made box — opt out of the reading measure so the code can use the full width:
|
|
182
|
+
|
|
183
|
+
```html
|
|
184
|
+
<div class="prose" style="--prose-measure: none">
|
|
185
|
+
<pre><code>bun add actual-css</code></pre>
|
|
186
|
+
</div>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`hr` resets the UA's `margin-inline: auto`. In document flow that changes nothing — auto inline margins on an auto-width block resolve to zero — but as a flex or grid item they replace the cross-axis stretch, which made an `<hr>` inside a `.stack` compute to zero width and disappear. `.stack` deliberately leaves the inline axis free (self-centering children keep working), so the reset belongs to the element.
|
|
190
|
+
|
|
191
|
+
Its block margin is tunable with `--hr-space`. The `--space-60` default suits a rule closing a page section; a rule separating two rows inside a panel wants far less.
|
|
192
|
+
|
|
193
|
+
```css
|
|
194
|
+
.settings-panel hr {
|
|
195
|
+
--hr-space: var(--space-10);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The hook applies to an `hr` in document flow. Inside `.stack` or `.prose` the parent owns the distance between siblings and overrides the element's own margin — express the rhythm there instead, with `--gap` or `--prose-flow`.
|
|
179
200
|
|
|
180
201
|
## Tables
|
|
181
202
|
|
|
@@ -198,14 +219,14 @@ To enable fluid display type on a marketing or documentation surface, import the
|
|
|
198
219
|
|
|
199
220
|
The module does not change anything in the core: it adds three size tokens and three classes. Body text, app UI, and the default prose scale are not affected.
|
|
200
221
|
|
|
201
|
-
Projects that
|
|
222
|
+
Projects on `actual-css/css/typography` or `actual-css/full` already have the module. A minimal-core project that does not need fluid display type does nothing — the module is not in the core.
|
|
202
223
|
|
|
203
224
|
## What not to reintroduce
|
|
204
225
|
|
|
205
226
|
These are decisions that the framework has already made. Re-introducing them silently would regress the system.
|
|
206
227
|
|
|
207
228
|
- Do not add `font-size` on global `h1` to `h6`. Headings inherit size from context (component or `.prose`).
|
|
208
|
-
- Do not add `font-weight` on global `h1` to `h6`.
|
|
229
|
+
- Do not add `font-weight` on global `h1` to `h6`. Heavier weights are scoped to `.prose` and to components that need them.
|
|
209
230
|
- Do not add global `text-decoration: underline` on `a`. Links get their visual affordance from `.prose` or from their component.
|
|
210
231
|
- Do not add `transition: all`. Transitions target specific properties.
|
|
211
232
|
- Do not add a `--font-weight-light`. It is rarely a good default and depends on the typeface.
|
|
@@ -78,7 +78,9 @@ Intents are `.primary`, `.secondary`, `.success`, `.warning`, and `.danger`, and
|
|
|
78
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
|
-
are button-only. Size variants `.sm` and `.lg` scale
|
|
81
|
+
are button-only. Size variants `.sm` and `.lg` scale typography and
|
|
82
|
+
participating component geometry consistently. Density contexts `.compact` and
|
|
83
|
+
`.spacious` change geometry and spacing without changing typography or icons.
|
|
82
84
|
Undocumented `is-*` classes are runtime internals.
|
|
83
85
|
|
|
84
86
|
```html
|
|
@@ -139,16 +141,16 @@ internal design documents for contributors.
|
|
|
139
141
|
|
|
140
142
|
Actual CSS is built around progressive enhancement.
|
|
141
143
|
|
|
142
|
-
| Tier
|
|
143
|
-
|
|
|
144
|
-
| Degraded
|
|
145
|
-
| **Minimal**
|
|
146
|
-
|
|
|
147
|
-
| Recommended | 129+ | 17.5+ | 123+ |
|
|
144
|
+
| Tier | Firefox | Safari | Chromium |
|
|
145
|
+
| ----------- | -------- | ------- | -------- |
|
|
146
|
+
| Degraded | 78+ | 14+ | 88+ |
|
|
147
|
+
| **Minimal** | **125+** | **17+** | **116+** |
|
|
148
|
+
| Recommended | 129+ | 17.5+ | 123+ |
|
|
148
149
|
|
|
149
150
|
**Degraded** — semantic HTML and core CSS remain usable. JavaScript
|
|
150
151
|
enhancements are outside the supported contract.
|
|
151
152
|
|
|
152
153
|
**Minimal** — full Actual support, including the JavaScript runtime. The
|
|
153
|
-
runtime assumes modern browser APIs
|
|
154
|
-
|
|
154
|
+
runtime assumes modern browser APIs — including the native manual Popover
|
|
155
|
+
transport used by interactive surfaces — and ships no legacy compatibility
|
|
156
|
+
layers or polyfills.
|
|
@@ -17,14 +17,16 @@ unsupported — it is not tested, documented as supported, or preserved when the
|
|
|
17
17
|
runtime evolves. The runtime assumes the modern platform primitives available
|
|
18
18
|
across Minimal and ships no compatibility layer or polyfill.
|
|
19
19
|
|
|
20
|
-
| Tier
|
|
21
|
-
|
|
|
22
|
-
| Degraded
|
|
23
|
-
| **Minimal**
|
|
24
|
-
|
|
|
25
|
-
| Recommended | 129+ | 17.5+ | 123+ |
|
|
20
|
+
| Tier | Firefox | Safari | Chromium |
|
|
21
|
+
| ----------- | -------- | ------- | -------- |
|
|
22
|
+
| Degraded | 78+ | 14+ | 88+ |
|
|
23
|
+
| **Minimal** | **125+** | **17+** | **116+** |
|
|
24
|
+
| Recommended | 129+ | 17.5+ | 123+ |
|
|
26
25
|
|
|
27
|
-
The
|
|
26
|
+
The floor is set by the native manual Popover transport (`popover="manual"`,
|
|
27
|
+
`showPopover()`, `hidePopover()`), which interactive surfaces use to promote a
|
|
28
|
+
panel to the top layer without moving it in the DOM. The tier definitions live
|
|
29
|
+
in the browser-support design note.
|
|
28
30
|
|
|
29
31
|
## Overview
|
|
30
32
|
|
|
@@ -109,7 +111,7 @@ The JS is designed to run on its own, without Actual's stylesheet.
|
|
|
109
111
|
presentation class needed. Self-describing attributes (`data-mask`,
|
|
110
112
|
`data-tooltip`, `data-context-menu`) stay framework-neutral by construction.
|
|
111
113
|
- **`selectors.js`** lists the state classes the runtime *writes* (`is-open`,
|
|
112
|
-
`was-validated`,
|
|
114
|
+
`was-validated`, …). Edit this file (or alias it in a bundler) to
|
|
113
115
|
match a different CSS framework's state vocabulary. It is a read-side-only
|
|
114
116
|
adapter — it does not bridge CSS class names to JS initialization.
|
|
115
117
|
- **One documented exception:** validation reads `.field-error` (or its alias
|
|
@@ -157,17 +159,30 @@ const stop = autoUpdate(trigger, float, () => {
|
|
|
157
159
|
|
|
158
160
|
Options passed to `reposition()`:
|
|
159
161
|
|
|
160
|
-
| Option
|
|
161
|
-
|
|
|
162
|
-
| `placement`
|
|
163
|
-
| `distance`
|
|
164
|
-
| `flip`
|
|
165
|
-
| `shift`
|
|
166
|
-
| `shiftPadding`
|
|
167
|
-
| `scope`
|
|
162
|
+
| Option | Default | Contract |
|
|
163
|
+
| ----------------- | ---------------- | -------------------------------------------- |
|
|
164
|
+
| `placement` | `"bottom-start"` | Preferred side and alignment |
|
|
165
|
+
| `distance` | `0` | Gap from the reference element |
|
|
166
|
+
| `flip` | `true` | Flip when the preferred side is out of view |
|
|
167
|
+
| `shift` | `true` | Shift along the cross axis to stay in bounds |
|
|
168
|
+
| `shiftPadding` | `4` | Minimum space kept from the boundary |
|
|
169
|
+
| `scope` | viewport | Boundary element for overflow decisions |
|
|
170
|
+
| `coordinateSpace` | `"viewport"` | Space the written `left`/`top` use |
|
|
168
171
|
|
|
169
172
|
`placement` takes a `-start` or `-end` alignment suffix.
|
|
170
173
|
|
|
174
|
+
Measurement is always in viewport coordinates; `coordinateSpace` only changes
|
|
175
|
+
what is written. `"viewport"` expects `position: fixed`; `"document"` adds the
|
|
176
|
+
page scroll and expects `position: absolute` against the initial containing
|
|
177
|
+
block, which the top layer supplies to an open popover. The browser then
|
|
178
|
+
scrolls the element with the page rather than `autoUpdate()` correcting it a
|
|
179
|
+
frame later — right for a reference that scrolls with the page, wrong for a
|
|
180
|
+
fixed or sticky one. `tooltip.js` and element-anchored surfaces choose this
|
|
181
|
+
coupled coordinate/position mode once per opening. A point-positioned surface
|
|
182
|
+
always uses fixed viewport coordinates because `x` and `y` are client
|
|
183
|
+
coordinates. Scrolling a nested container still needs the next `autoUpdate()`
|
|
184
|
+
frame; document coordinates remove correction only for page scrolling.
|
|
185
|
+
|
|
171
186
|
`@lekoala/floating` is the standalone positioning dependency used by the
|
|
172
187
|
runtime. `autoUpdate(reference, float, callback)` batches scroll, resize, and
|
|
173
188
|
element-resize callbacks per document and returns a stop handle; it observes
|
|
@@ -185,23 +200,32 @@ must be able to position a listbox under an input — that is the test.
|
|
|
185
200
|
or account for:
|
|
186
201
|
|
|
187
202
|
```css
|
|
188
|
-
.my-panel
|
|
189
|
-
.my-panel[
|
|
190
|
-
|
|
203
|
+
.my-panel { position: absolute; }
|
|
204
|
+
.my-panel[popover] { inset: auto; margin: 0; }
|
|
205
|
+
.my-panel[popover]:not(:popover-open) { display: none; }
|
|
206
|
+
/* surface.js sets a coupled fixed/viewport or absolute/document mode —
|
|
191
207
|
do not override with !important */
|
|
192
|
-
/*
|
|
193
|
-
—
|
|
208
|
+
/* no z-index: an open panel is promoted to the top layer, where
|
|
209
|
+
numbers do not apply — see Layering in foundations/tokens */
|
|
210
|
+
/* .is-open is written by surface.js — style or ignore it */
|
|
194
211
|
/* --surface-anchor-width is set while an open surface is positioned */
|
|
195
212
|
/* data-actual-surface is written by surface.js for teardown
|
|
196
213
|
— never select on it */
|
|
197
214
|
```
|
|
198
215
|
|
|
199
|
-
|
|
216
|
+
Three non-obvious requirements:
|
|
200
217
|
|
|
201
|
-
1. `
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
218
|
+
1. `surface.js` writes `popover="manual"` and removes `hidden`: the panel is
|
|
219
|
+
promoted to the top layer where it stands, never reparented, and the closed
|
|
220
|
+
state belongs to the platform. `.is-open` is the state the runtime writes
|
|
221
|
+
and the only one to key styles on.
|
|
222
|
+
2. A panel that declares its own `display` must restore `display: none` for the
|
|
223
|
+
closed popover. An author declaration outranks the UA origin whatever the
|
|
224
|
+
specificity, so a bare `display: grid` leaves a closed panel painted at its
|
|
225
|
+
static position.
|
|
226
|
+
3. The open state switches to the coupled position and coordinate mode chosen
|
|
227
|
+
from its anchor, with measured inline coordinates. The UA's own `inset` /
|
|
228
|
+
`margin` must be cleared.
|
|
205
229
|
|
|
206
230
|
Lifecycle: `prepareSurface` → `openSurface` → `closeSurface` →
|
|
207
231
|
`disconnectSurface`. `retainSurface(panel)` reference-counts a surface shared by
|
|
@@ -209,6 +233,11 @@ several triggers and returns a release function; `isSurfaceOpen` and
|
|
|
209
233
|
`getSurfaceAutoClose` read current state. The separate `escape` primitive adds
|
|
210
234
|
visible dismissable UI to the shared per-document Escape stack.
|
|
211
235
|
|
|
236
|
+
Actual-managed surfaces are mutually exclusive within a document. Opening a
|
|
237
|
+
surface closes any other open Actual surface, including one containing its
|
|
238
|
+
trigger. Nested surfaces are not currently supported: a panel opened from
|
|
239
|
+
inside another panel replaces it rather than stacking on it.
|
|
240
|
+
|
|
212
241
|
`openSurface(menu, opts)` dispatches a cancelable `actual:surface-open` event —
|
|
213
242
|
widgets can veto or decorate opens, and context menus inject their own
|
|
214
243
|
`source`/`restoreFocusTo` through it.
|
|
@@ -224,14 +253,11 @@ widgets can veto or decorate opens, and context menus inject their own
|
|
|
224
253
|
| `shift` | `true` | Shift to stay within the boundary |
|
|
225
254
|
| `shiftPadding` | `4` | Minimum space kept from the boundary |
|
|
226
255
|
| `scope` | viewport | Boundary element |
|
|
227
|
-
| `mobile` | `"auto"` | Sheet behavior |
|
|
228
|
-
| `breakpoint` | `768` | Max viewport width for an automatic sheet |
|
|
229
256
|
| `autoClose` | `"outside"` | Which clicks close the surface |
|
|
230
257
|
| `dismissOnScroll` | `false` | Close on a scroll the user just started |
|
|
231
258
|
| `restoreFocusTo` | `trigger` | Element focused on close |
|
|
232
259
|
|
|
233
260
|
`x`, `y` replace the anchor entirely, which is what a context menu needs.
|
|
234
|
-
`mobile` takes `"auto"`, `"sheet"`, `"none"` or `"anchored"`.
|
|
235
261
|
|
|
236
262
|
`autoClose` takes `"true"` to close on inside and outside clicks, `"inside"` or
|
|
237
263
|
`"outside"` to limit it to one side, and `"false"` to disable automatic click
|
|
@@ -391,6 +417,63 @@ on the same root throws, and `disconnect()` releases the name so it can be
|
|
|
391
417
|
registered again. A custom root passed as the third argument must be disposed
|
|
392
418
|
by its owner; the default `document.documentElement` root is not affected.
|
|
393
419
|
|
|
420
|
+
### Applying behaviors from application selectors
|
|
421
|
+
|
|
422
|
+
Prefer declarative `data-enhance` in HTML. When server-rendered markup or
|
|
423
|
+
application conventions make JavaScript more convenient, use
|
|
424
|
+
`applyEnhancement(name, selector, root?)`:
|
|
425
|
+
|
|
426
|
+
```js
|
|
427
|
+
import "actual-css/js/tab";
|
|
428
|
+
import "actual-css/js/flyout";
|
|
429
|
+
import "actual-css/js/validation";
|
|
430
|
+
import { applyEnhancement } from "actual-css/js/enhance";
|
|
431
|
+
|
|
432
|
+
const bindings = {
|
|
433
|
+
tabs: ".tabs",
|
|
434
|
+
flyout: ".menu-trigger",
|
|
435
|
+
validation: "form.needs-validation",
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
for (const [name, selector] of Object.entries(bindings)) {
|
|
439
|
+
applyEnhancement(name, selector);
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Run this after the target markup exists, for example in a module script.
|
|
444
|
+
Select the element that owns the behavior, not necessarily the element carrying
|
|
445
|
+
the component class. For example, `flyout` applies to **triggers**, not `.flyout`
|
|
446
|
+
panels. Those triggers need `aria-controls` pointing to their panels. Tooltips use
|
|
447
|
+
`data-tooltip` directly and do not need a named enhancement.
|
|
448
|
+
|
|
449
|
+
`selector` is a CSS selector. `root` defaults to `document.documentElement` and
|
|
450
|
+
uses `querySelectorAll()` semantics: only descendants match, never the scope
|
|
451
|
+
itself. Pass a container to limit the application:
|
|
452
|
+
|
|
453
|
+
```js
|
|
454
|
+
applyEnhancement("tabs", ".tabs", container);
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Each registration on the scope or its ancestors refreshes the scope once.
|
|
458
|
+
Shadow roots need their own registrations; document registrations do not cross
|
|
459
|
+
into them.
|
|
460
|
+
|
|
461
|
+
The function returns an array of matched elements, preserves existing
|
|
462
|
+
tokens, and can be called repeatedly without initializing an active behavior
|
|
463
|
+
twice. Invalid names or selectors throw. Without a DOM it returns an
|
|
464
|
+
empty array. It does not import modules: applying a token before its module is
|
|
465
|
+
registered lets that registration's initial scan discover it later.
|
|
466
|
+
|
|
467
|
+
`applyEnhancement()` is a one-time convenience for adding an enhancement token
|
|
468
|
+
to elements selected by the application. It does not create a persistent
|
|
469
|
+
selector-to-enhancement binding. For injected markup, author `data-enhance`
|
|
470
|
+
directly or call the function with a scope containing the new elements.
|
|
471
|
+
Detached elements receive the token and initialize when inserted into a
|
|
472
|
+
registered root. Removing the token does not disconnect an active behavior.
|
|
473
|
+
|
|
474
|
+
`data-enhance` remains the portable behavior contract. Class mappings belong to
|
|
475
|
+
the application; Actual does not infer behavior from presentation classes.
|
|
476
|
+
|
|
394
477
|
### Enhancement manifests
|
|
395
478
|
|
|
396
479
|
The enhancement-loader lets a server (or static HTML) declare document-wide
|
|
@@ -676,7 +759,9 @@ field, and dispatches a bubbling `actual:invalid` event with
|
|
|
676
759
|
<input class="input" name="email" type="email" required
|
|
677
760
|
aria-describedby="email-error" />
|
|
678
761
|
<span class="field-error" id="email-error">Enter a valid email.</span>
|
|
679
|
-
<
|
|
762
|
+
<div class="form-actions">
|
|
763
|
+
<button class="btn primary" type="submit">Submit</button>
|
|
764
|
+
</div>
|
|
680
765
|
</form>
|
|
681
766
|
|
|
682
767
|
<div class="status-bar" data-status role="status" aria-live="polite" aria-atomic="true"></div>
|
|
@@ -163,7 +163,7 @@ Tailwind allows almost every utility to be changed independently at a breakpoint
|
|
|
163
163
|
There is intentionally no equivalent Actual syntax such as:
|
|
164
164
|
|
|
165
165
|
```text
|
|
166
|
-
md:cluster xl:
|
|
166
|
+
md:cluster xl:spacious
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
First ask what the layout is supposed to do.
|
|
@@ -213,7 +213,8 @@ Actual does not prohibit media queries. It simply does not encode every media qu
|
|
|
213
213
|
| `max-w-*` for readable text | `.measure` where appropriate |
|
|
214
214
|
| common visual component bundle | Actual component |
|
|
215
215
|
| component colors | intents such as `.primary`, `.danger`, `.success` |
|
|
216
|
-
|
|
|
216
|
+
| `gap-*` on one container | `gap: var(--space-*)` |
|
|
217
|
+
| rebind rhythm for nested primitives | `--gap` on the layout context |
|
|
217
218
|
| small common corrections | Actual utilities |
|
|
218
219
|
| breakpoint-prefixed utilities | intrinsic layout, container query, or project CSS |
|
|
219
220
|
| arbitrary values | custom property or project CSS |
|
|
@@ -25,4 +25,4 @@ Add `.items-center` to align the leading element with short trailing content. Fo
|
|
|
25
25
|
</div>
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
The media object is the underlying pattern of `.blog-author`, `.blog-comment`, and similar compositions in templates. Components can adopt it instead of repeating the grid rule.
|
|
28
|
+
The media object is the underlying pattern of `.blog-author`, `.blog-comment`, and similar compositions in templates. Components can adopt it instead of repeating the grid rule. The [Workspaces example](../examples/overview.md) shows the card pattern: `card > header` with `.media` plus `hgroup`, and row actions in the header — never a third `.media` child.
|
|
@@ -47,4 +47,14 @@ Most layout primitives read `--gap` and allow local overrides.
|
|
|
47
47
|
|
|
48
48
|
Prefer a local custom property over adding many one-off utility classes. Use inline styles only for demos, prototypes, or truly dynamic values.
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
Set `--gap` locally to retune the primitive and its nested layouts. To change only one element's rhythm without reaching nested primitives, set the `gap` property instead.
|
|
51
|
+
|
|
52
|
+
## Spacing expresses relationships
|
|
53
|
+
|
|
54
|
+
**Components own their internal rhythm; layout owns the relationships between components.**
|
|
55
|
+
|
|
56
|
+
Prefer a parent `gap` for relationships between peers instead of encoding sibling margins into a component. Smaller gaps imply a stronger relationship; progressively larger gaps distinguish groups and sections.
|
|
57
|
+
|
|
58
|
+
Before adding a divider or other separating chrome, consider whether additional spacing already expresses the boundary clearly.
|
|
59
|
+
|
|
60
|
+
Density changes the amount of space available, not the relationships that space communicates. When a composition contains local, group, and section rhythms, preserve their relative hierarchy with nested or local `--gap` values rather than relying on one inherited gap at every level. See [Stack](./stack.md) for the nesting and density mechanics.
|
|
@@ -24,10 +24,10 @@ Use `.scroll-snap` for a niche row of items that should scroll horizontally, suc
|
|
|
24
24
|
|
|
25
25
|
The baseline is flex layout plus `overflow-x: auto`, so older browsers still get a usable horizontal scroll area. Browsers with scroll snap support add `scroll-snap-type` and item alignment.
|
|
26
26
|
|
|
27
|
-
Items snap to the inline start edge by default. Use `data-snap="center"` for visual rails where centered cards are the better fit.
|
|
27
|
+
Items snap to the inline start edge by default, with `proximity` snapping so a short rail never fights the pointer. Use `data-snap-align="center"` for visual rails where centered cards are the better fit, and `data-snap="mandatory"` only when every stop must land.
|
|
28
28
|
|
|
29
29
|
```html demo
|
|
30
|
-
<div class="scroll-snap" data-snap="center" style="--scroll-snap-item-size: min(85%, 18rem)">
|
|
30
|
+
<div class="scroll-snap" data-snap-align="center" style="--scroll-snap-item-size: min(85%, 18rem)">
|
|
31
31
|
<article class="card">One</article>
|
|
32
32
|
<article class="card">Two</article>
|
|
33
33
|
<article class="card">Three</article>
|
|
@@ -42,7 +42,7 @@ Items snap to the inline start edge by default. Use `data-snap="center"` for vis
|
|
|
42
42
|
- `--scroll-snap-gap` — space between items.
|
|
43
43
|
- `--scroll-snap-padding` — inline scroll padding, so a snapped item does not sit
|
|
44
44
|
flush against the container edge. Not declared; falls back to `--scroll-snap-gap`.
|
|
45
|
-
- `--scroll-snap-align` — item snap alignment. Prefer `data-snap="center"`
|
|
45
|
+
- `--scroll-snap-align` — item snap alignment. Prefer `data-snap-align="center"`
|
|
46
46
|
over setting this directly.
|
|
47
47
|
|
|
48
48
|
Keep scrollbars visible by default. If a product deliberately hides them, make that choice explicit with `data-scrollbar="hidden"`.
|
|
@@ -41,15 +41,17 @@ not as the wrapper that lays out independent full-width regions of a page.
|
|
|
41
41
|
|
|
42
42
|
## Choosing a density
|
|
43
43
|
|
|
44
|
-
`--gap` is the primitive's channel, and the density variants set it at
|
|
45
|
-
of use.
|
|
44
|
+
`--gap` is the primitive's channel, and the density context variants set it at
|
|
45
|
+
the point of use. Apply the density class on the stack itself to size one
|
|
46
|
+
instance, or on an ancestor to reach nested layouts. Pick the one that matches
|
|
47
|
+
how tightly the children belong together:
|
|
46
48
|
|
|
47
49
|
| Markup | Gap | Use for |
|
|
48
50
|
| ----------------- | ---- | ------------------------------------------ |
|
|
49
51
|
| `.stack gap-none` | 0 | Lines forming one typographic unit |
|
|
50
|
-
| `.stack
|
|
52
|
+
| `.stack compact` | 8px | A homogeneous series of controls |
|
|
51
53
|
| `.stack` | 12px | Normal flow between distinct elements |
|
|
52
|
-
| `.stack
|
|
54
|
+
| `.stack spacious` | 24px | Sections, or blocks that read as separated |
|
|
53
55
|
|
|
54
56
|
One typographic unit means a name and a job title, or a figure and its caption.
|
|
55
57
|
A homogeneous series means a radio list, a checkbox list, or a compact vertical
|
|
@@ -57,8 +59,14 @@ menu.
|
|
|
57
59
|
|
|
58
60
|
The distinction between the first two matters. `42` above `Open issues` is
|
|
59
61
|
almost a single block of text, so it takes `gap-none`. Three `.choice` labels
|
|
60
|
-
stay three separate controls that happen to form one group, so they take
|
|
61
|
-
tighter than the default, but still spaced.
|
|
62
|
+
stay three separate controls that happen to form one group, so they take
|
|
63
|
+
`compact` — tighter than the default, but still spaced.
|
|
64
|
+
|
|
65
|
+
`.compact` and `.spacious` rebind `--gap` to `--space-20` and `--space-50`.
|
|
66
|
+
Because the token is inherited, the same two classes also tighten the inner gap
|
|
67
|
+
of any nested stack, cluster, and grid. For a one-off gap that must *not* follow
|
|
68
|
+
density, set the `gap` property directly on the instance (the next section
|
|
69
|
+
explains why).
|
|
62
70
|
|
|
63
71
|
A stack that mixes kinds keeps the default: five `.field` wrappers and one lone
|
|
64
72
|
`.choice` is a form that contains a checkbox, not a list of options, and
|
|
@@ -84,7 +92,7 @@ depth:
|
|
|
84
92
|
```
|
|
85
93
|
|
|
86
94
|
Both give the region the same spacing; only the second stops there. This is what
|
|
87
|
-
makes a nested `.stack
|
|
95
|
+
makes a nested `.stack compact` a real density choice — 12px down to 8px — rather
|
|
88
96
|
than a patch cancelling a rhythm inherited from three levels up.
|
|
89
97
|
|
|
90
98
|
Setting `--gap` is still the right move on the element that *consumes* it: a
|
|
@@ -92,8 +100,8 @@ one-off `--gap` on a card body or an actions row tunes that primitive and
|
|
|
92
100
|
nothing below it, because the setter is the consumer. The leak only appears when
|
|
93
101
|
a container sets the token and its children read it.
|
|
94
102
|
|
|
95
|
-
`.
|
|
96
|
-
density context reaches nested layouts.
|
|
103
|
+
`.compact` and `.spacious` are the deliberate exception: they set `--gap`
|
|
104
|
+
precisely so a density context reaches nested layouts.
|
|
97
105
|
|
|
98
106
|
## Grouping items tightly
|
|
99
107
|
|
|
@@ -11,13 +11,15 @@ Use `.input-icon` for a search or filter input with a leading icon.
|
|
|
11
11
|
|
|
12
12
|
It positions the wrapper's first child absolutely inside a relative container and grows the input's start padding to clear it. `pointer-events: none` on the icon keeps clicks passing through to the input underneath. It is icon-library agnostic — an `<i>` webfont icon, an inline `<svg>`, or a `<span>` all work as the wrapper's first child.
|
|
13
13
|
|
|
14
|
-
The icon
|
|
14
|
+
The icon follows local typography through `--input-icon-size`. Apply a size to
|
|
15
|
+
the wrapper so icon, input type, and control geometry scale together. A density
|
|
16
|
+
context changes only the geometry.
|
|
15
17
|
|
|
16
18
|
```html demo
|
|
17
19
|
<div class="stack">
|
|
18
20
|
<label class="input-icon sm">
|
|
19
21
|
<i class="ti ti-search" aria-hidden="true"></i>
|
|
20
|
-
<input class="input
|
|
22
|
+
<input class="input" type="search" aria-label="Search">
|
|
21
23
|
</label>
|
|
22
24
|
</div>
|
|
23
25
|
```
|
|
@@ -14,6 +14,8 @@ centers its glyph, and clips overflow:
|
|
|
14
14
|
- `overflow: hidden`;
|
|
15
15
|
- a child `svg` constrained to the box.
|
|
16
16
|
|
|
17
|
+
Icons inherit first: an icon that supports nearby content uses `currentColor`; it takes its own color only when it conveys an independent state or intent.
|
|
18
|
+
|
|
17
19
|
## The contract
|
|
18
20
|
|
|
19
21
|
```css
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
# Intent Nesting
|
|
2
2
|
|
|
3
|
-
Intent on an ancestor must not tint nested components, and a local intent inside an intent-carrying ancestor must win. Both directions are verified in `tests/css-audit.test.js` and the kitchen-sink demo template. Intent classes
|
|
3
|
+
Intent on an ancestor must not tint nested components, and a local intent inside an intent-carrying ancestor must win. Both directions are verified in `tests/css-audit.test.js`, `tests/browser/intent-boundary.test.js`, `tests/browser/soft-boundary.test.js` and the kitchen-sink demo template. Intent classes expose `--intent`, `--intent-fg`, and the soft-foreground relay `--intent-soft-fg`; each consuming component opens a local intent boundary in a `:where()` block that resets exactly the tokens it consumes to initial. Parent intents do not leak into nested components, and a local intent class still wins because it has higher specificity than `:where()`.
|
|
@@ -19,7 +19,7 @@ not about opting in. Importing `actual-css/css/utilities` — or
|
|
|
19
19
|
| **Extra** | `actual-css/css/utilities/extra` | Explicit property/value names |
|
|
20
20
|
|
|
21
21
|
Base is the curated set, and it is where a short name is allowed: `.px`, `.py`,
|
|
22
|
-
`.mbs`, `.gap-none`. Extra spells out the property and the value — `.gap-
|
|
22
|
+
`.mbs`, `.gap-none`. Extra spells out the property and the value — `.row-gap-context`,
|
|
23
23
|
`.overflow-x-auto`, `.justify-content-center` — and never gives a base utility
|
|
24
24
|
a second spelling.
|
|
25
25
|
|
|
@@ -33,8 +33,29 @@ list the two layers as separate tables. Every other utility page is base only.
|
|
|
33
33
|
|
|
34
34
|
> Utilities deliberately excluded to keep the surface small and intentional.
|
|
35
35
|
|
|
36
|
-
- No display scale such as `.block`, `.flex`, `.grid` — use layout primitives.
|
|
36
|
+
- No display scale such as `.block`, `.flex`, `.grid` — use layout primitives. The extra layer does ship explicit `.display-flex` / `.display-grid` escape hatches; see Display escape hatches below.
|
|
37
37
|
- No color scales such as `.text-primary` or `.bg-success` — intent colors belong to components and state.
|
|
38
38
|
- No breakpoint utility variants — use container queries or layout primitives.
|
|
39
39
|
- No utility variants for hover, focus, dark mode, or arbitrary selectors — use component states.
|
|
40
40
|
- No full spacing scale with every step and direction — the 17 spacing helpers across the core and extra utilities cover the most common escape hatches.
|
|
41
|
+
|
|
42
|
+
## Display escape hatches
|
|
43
|
+
|
|
44
|
+
A one-off display correction is the exception to the display Non-Goal. The extra
|
|
45
|
+
layer spells the property and the value, so these are opt-in corrections, not the
|
|
46
|
+
short atomic scale the Non-Goal bans.
|
|
47
|
+
|
|
48
|
+
| Class | Description |
|
|
49
|
+
| ----------------------- | ------------------------ |
|
|
50
|
+
| `.display-block` | `display: block`. |
|
|
51
|
+
| `.display-inline` | `display: inline`. |
|
|
52
|
+
| `.display-inline-block` | `display: inline-block`. |
|
|
53
|
+
| `.display-flex` | `display: flex`. |
|
|
54
|
+
| `.display-inline-flex` | `display: inline-flex`. |
|
|
55
|
+
| `.display-grid` | `display: grid`. |
|
|
56
|
+
| `.display-none` | `display: none`. |
|
|
57
|
+
| `.visibility-hidden` | `visibility: hidden`. |
|
|
58
|
+
|
|
59
|
+
Prefer `.stack`, `.cluster`, `.grid`, and the other layout primitives first.
|
|
60
|
+
Reach for a display helper when existing component or third-party markup needs a
|
|
61
|
+
one-line correction and no primitive expresses it.
|
|
@@ -27,7 +27,7 @@ layout primitive from wrapping — for example to force a `.cluster` onto a sing
|
|
|
27
27
|
row — set `--cluster-wrap: nowrap`.
|
|
28
28
|
|
|
29
29
|
```html demo
|
|
30
|
-
<div class="cluster
|
|
30
|
+
<div class="cluster compact" style="--cluster-wrap: nowrap;">
|
|
31
31
|
<select class="select sm fit" aria-label="Segment">
|
|
32
32
|
<option>All segments</option>
|
|
33
33
|
</select>
|
|
@@ -18,9 +18,6 @@ Extra utilities:
|
|
|
18
18
|
|
|
19
19
|
| Class | Description |
|
|
20
20
|
| --------------------------- | --------------------------------------------- |
|
|
21
|
-
| `.gap-sm` | `gap: var(--space-20)` — denser row rhythm. |
|
|
22
|
-
| `.gap-md` | `gap: var(--space-40)` — default row rhythm. |
|
|
23
|
-
| `.gap-lg` | `gap: var(--space-50)` — roomier row rhythm. |
|
|
24
21
|
| `.padding-context` | All-side padding at the current density step. |
|
|
25
22
|
| `.gap-context` | `gap: var(--gap)`. |
|
|
26
23
|
| `.row-gap-context` | `row-gap: var(--gap)`. |
|
|
@@ -32,8 +29,8 @@ Extra utilities:
|
|
|
32
29
|
| `.margin-block-end-auto` | Pushes content toward the block start. |
|
|
33
30
|
|
|
34
31
|
Spacing helpers follow the density context. The default step is
|
|
35
|
-
`--space-40` (1rem); the `.
|
|
36
|
-
and the `.
|
|
32
|
+
`--space-40` (1rem); the `.compact` context tightens it to `--space-20` (0.5rem)
|
|
33
|
+
and the `.spacious` context loosens it to `--space-50` (1.5rem). All helpers read
|
|
37
34
|
`--density-space` and map to logical properties (`padding-block`,
|
|
38
35
|
`margin-block-end`, etc.) for writing-direction safety.
|
|
39
36
|
|
|
@@ -51,8 +48,13 @@ Override the default gap from layout primitives (`.stack`, `.cluster`, `.grid`):
|
|
|
51
48
|
- `.gap-none` → `gap: 0`
|
|
52
49
|
|
|
53
50
|
`.gap-none` sets the element's own gap directly and does not change `--gap`
|
|
54
|
-
for nested layouts. For a denser or roomier rhythm, use the `.
|
|
55
|
-
density contexts or
|
|
51
|
+
for nested layouts. For a denser or roomier rhythm, use the `.compact` /
|
|
52
|
+
`.spacious` density contexts, or set the `gap` property on the instance when the
|
|
53
|
+
change must stop there.
|
|
54
|
+
|
|
55
|
+
`--gap` defines the contextual rhythm; `.gap-context` applies that rhythm to a
|
|
56
|
+
container that does not already consume `--gap`. The layout primitives
|
|
57
|
+
(`.stack`, `.cluster`, `.grid`, …) read it on their own.
|
|
56
58
|
|
|
57
59
|
## Padding
|
|
58
60
|
|
|
@@ -82,5 +84,5 @@ No `mbs-none` / `mbe-none` — use `margin: 0` via `.list-reset` for lists, or a
|
|
|
82
84
|
|
|
83
85
|
## CSS hooks
|
|
84
86
|
|
|
85
|
-
- `--density-space` — the step every padding and margin helper reads; `.
|
|
87
|
+
- `--density-space` — the step every padding and margin helper reads; `.compact` sets it to `--space-20`, default to `--space-40`, `.spacious` to `--space-50`.
|
|
86
88
|
- `--gap` — base gap of layout primitives; read by the optional `.gap-context`, `.row-gap-context`, and `.column-gap-context` helpers.
|
package/llms.txt
CHANGED
|
@@ -14,9 +14,10 @@ Actual CSS uses a small public grammar: `.component [intent] [variant] [size] [m
|
|
|
14
14
|
|
|
15
15
|
- `actual-css` — the minimal core: tokens, theme contract, reset, base elements, and universal variants. Components and layout primitives are NOT included.
|
|
16
16
|
- `actual-css/full` — the complete framework: core plus every component, form, layout, typography, effect, and utility family.
|
|
17
|
-
- `actual-css/js` — the enhancement
|
|
17
|
+
- `actual-css/js` — the enhancement-loader entry only: it watches `data-enhance-modules` manifest blocks and imports the declared enhancers on demand.
|
|
18
18
|
- `actual-css/js/full` — the complete runtime with all built-in enhancers pre-registered.
|
|
19
19
|
- `actual-css/reserved-classes.json` — machine-readable list of the framework-owned class namespace. Use it to check whether a class belongs to Actual CSS and to validate claimed framework classes; application-specific classes are expected to exist outside this manifest.
|
|
20
|
+
- `actual-css/components.json` — machine-readable component index, derived from the sources (CSS headers, selectors, package exports, `src/js`) by `scripts/build-catalog.js` and verified by `check:catalog`. Gives each component its import paths, owned classes, hooks, states, and registered enhancement tokens — enough to know what exists and where to read more, not a replacement for `docs/pages/components/*.md`.
|
|
20
21
|
- Individual families and modules are importable separately (`actual-css/css/components`, `actual-css/css/layout/grid`, `actual-css/js/dialog`, …); see [README](README.md) and [Modular imports](docs/pages/guides/modular-import.md).
|
|
21
22
|
|
|
22
23
|
Forms are the one family with two aggregate entrypoints:
|