actual-css 0.9.1 → 0.10.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 +116 -0
- package/README.md +67 -45
- package/components.json +33 -13
- package/dist/actual.full.css +607 -502
- package/dist/actual.full.js +1 -1
- package/dist/actual.full.min.css +1 -1
- package/docs/design-notes/app-ui.md +1 -1
- package/docs/design-notes/column-layout.md +103 -520
- package/docs/design-notes/forced-colors.md +12 -1
- package/docs/design-notes/naming.md +1 -1
- package/docs/design-notes/surface-reparenting.md +8 -9
- package/docs/navigation.json +2 -0
- package/docs/pages/components/accordion.md +55 -1
- package/docs/pages/components/alert.md +9 -15
- package/docs/pages/components/badge.md +6 -7
- package/docs/pages/components/bleed.md +42 -0
- package/docs/pages/components/button.md +30 -4
- package/docs/pages/components/card.md +21 -86
- package/docs/pages/components/close.md +48 -0
- package/docs/pages/components/data-list.md +26 -1
- package/docs/pages/components/dialog.md +16 -16
- package/docs/pages/components/drawer.md +9 -9
- package/docs/pages/components/navbar.md +5 -5
- package/docs/pages/components/spinner.md +3 -3
- package/docs/pages/components/table.md +3 -2
- package/docs/pages/enhancements/overview.md +5 -0
- package/docs/pages/enhancements/tooltip.md +3 -1
- package/docs/pages/examples/overview.md +3 -1
- package/docs/pages/forms/choice-cards.md +39 -0
- package/docs/pages/forms/combobox.md +23 -11
- package/docs/pages/forms/input-policy.md +59 -0
- package/docs/pages/forms/joined-controls.md +2 -5
- package/docs/pages/forms/overview.md +6 -0
- package/docs/pages/forms/validation.md +37 -1
- package/docs/pages/foundations/theming.md +64 -18
- package/docs/pages/foundations/tokens.md +50 -13
- package/docs/pages/foundations/typography.md +10 -0
- package/docs/pages/guides/introduction.md +17 -24
- package/docs/pages/guides/modular-import.md +53 -6
- package/docs/pages/guides/progressive-enhancement.md +9 -5
- package/docs/pages/guides/tailwind.md +17 -5
- package/docs/pages/layout/column-layout.md +92 -54
- package/docs/pages/layout/media.md +1 -1
- package/docs/pages/layout/overview.md +1 -1
- package/docs/pages/utilities/overview.md +1 -1
- package/docs/pages/utilities/sizing-wrapping.md +5 -3
- package/llms.txt +24 -4
- package/package.json +7 -6
- package/reserved-classes.json +5 -30
- package/skills/actual-css/PROJECT.md.example +65 -0
- package/skills/actual-css/README.md +64 -0
- package/skills/actual-css/SKILL.md +234 -0
- package/skills/actual-css/references/accessibility.md +44 -0
- package/skills/actual-css/references/api-and-vocabulary.md +94 -0
- package/skills/actual-css/references/enhancements.md +59 -0
- package/skills/actual-css/references/forms.md +49 -0
- package/skills/actual-css/references/layout-and-theming.md +82 -0
- package/skills/actual-css/references/review-checklist.md +51 -0
- package/skills/actual-css/scripts/inspect-actual-css.mjs +171 -0
- package/src/css/components/accordion.css +44 -7
- package/src/css/components/alert.css +23 -43
- package/src/css/components/app-nav.css +9 -0
- package/src/css/components/badge.css +11 -39
- package/src/css/components/bleed.css +79 -0
- package/src/css/components/button.css +6 -17
- package/src/css/components/card.css +7 -40
- package/src/css/components/close.css +91 -0
- package/src/css/components/data-list.css +18 -0
- package/src/css/components/drawer.css +15 -56
- package/src/css/components/fab.css +10 -0
- package/src/css/components/flyout.css +1 -0
- package/src/css/components/index.css +2 -0
- package/src/css/components/join.css +36 -20
- package/src/css/components/menu.css +12 -0
- package/src/css/components/modal.css +10 -57
- package/src/css/components/navbar.css +27 -0
- package/src/css/core/base.css +2 -0
- package/src/css/core/focus.css +9 -3
- package/src/css/core/theme.css +25 -43
- package/src/css/core/tokens.css +3 -1
- package/src/css/core/variants.css +15 -36
- package/src/css/forms/choice-card.css +74 -4
- package/src/css/forms/choice.css +2 -3
- package/src/css/forms/control.css +15 -8
- package/src/css/forms/custom-select.css +4 -4
- package/src/css/forms/form.css +6 -0
- package/src/css/forms/native.css +4 -4
- package/src/css/forms/range.css +23 -8
- package/src/css/forms/switch.css +2 -3
- package/src/css/layout/app-layout.css +1 -1
- package/src/css/layout/column-layout.css +26 -111
- package/src/css/utilities/extra.css +7 -6
- package/src/js/dialog.js +95 -24
- package/src/js/enhance.js +7 -3
- package/src/js/escape.js +1 -0
- package/src/js/flyout.js +10 -1
- package/src/js/focus-group.js +2 -1
- package/src/js/keys.js +14 -0
- package/src/js/menu.js +2 -1
- package/src/js/status.js +19 -0
- package/src/js/surface.js +12 -8
- package/src/js/tab.js +2 -1
- package/src/js/tooltip.js +18 -1
- package/src/js/validation.js +36 -6
- package/dist/actual.css +0 -863
- package/dist/actual.js +0 -1
- package/dist/actual.min.css +0 -1
|
@@ -17,6 +17,24 @@ Component custom properties fall into three header categories in the source: **P
|
|
|
17
17
|
|
|
18
18
|
As a convention, component-prefixed properties owned by the component's base rule are usually author hooks. Properties owned by states/variants, derived from other hooks, or written by JavaScript are not. This convention is indicative, not algorithmic: runtime-written, derived, and state-relay properties stay internal even when their form resembles a hook.
|
|
19
19
|
|
|
20
|
+
### Where a token is declared
|
|
21
|
+
|
|
22
|
+
A hook is only defined inside the scope that declares it. Reading one outside that scope is not an error a browser reports: `var()` resolves to nothing, the whole declaration becomes invalid at computed-value time, and the property falls back to its initial value — `padding: var(--card-pad)` outside a card computes to `0`, silently.
|
|
23
|
+
|
|
24
|
+
| Scope | Declared on | Examples |
|
|
25
|
+
| --------- | --------------------------- | -------------------------------------- |
|
|
26
|
+
| Global | `:root`, every theme island | `--space-40`, `--radius`, `--primary` |
|
|
27
|
+
| Component | the component's base rule | `--card-pad`, `--drawer-size` |
|
|
28
|
+
| Relay | a variant, state, or script | `--ui-bg`, `--intent`, `--surface-pad` |
|
|
29
|
+
|
|
30
|
+
Global tokens are the ones to reach for in application CSS. Write a relay only to override what a variant sets on one element (Button · Variants); read one only where its owner documents it (`--bleed-pad`). When you do want a component token outside its component — matching a bare block to the card rhythm, say — give `var()` the default explicitly, so the declaration survives where the hook is absent:
|
|
31
|
+
|
|
32
|
+
```css
|
|
33
|
+
.panel {
|
|
34
|
+
padding: var(--card-pad, var(--space-40));
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
20
38
|
### Color
|
|
21
39
|
|
|
22
40
|
Intent tokens are used by `.primary`, `.secondary`, `.success`, `.warning`, `.danger`, and `.neutral`. They are curated color/foreground pairs. Actual CSS does not compute foregrounds automatically in the core theme contract.
|
|
@@ -62,17 +80,16 @@ The surface levels are: `surface` (canvas), `surface-raised` (cards, raised surf
|
|
|
62
80
|
|
|
63
81
|
Use `*-fg` pairs only for solid backgrounds where the component controls both foreground and background. Do not require a foreground token for every surface token.
|
|
64
82
|
|
|
65
|
-
Focus styling is outline-first.
|
|
83
|
+
Focus styling is outline-first. A global focus baseline applies `--focus-outline` and `--focus-outline-offset`: older browsers show it on `:focus`, while modern browsers limit it to `:focus-visible`. Components draw a solid `--focus-ring-width` line in `--focus`: inside the border box on text fields (`.input`, `.textarea`, `.select`), outside at `--focus-outline-offset` on actions (`.btn`, `.close`, choices, switches). The color never follows an intent or a local surface, so `--focus` must hold 3:1 against both `--surface` and `--surface-solid` — the page, fields and a solid band all rely on it. Under `forced-colors: active`, outlines map to the system focus color.
|
|
66
84
|
|
|
67
85
|
```css
|
|
68
86
|
:root {
|
|
69
|
-
--focus:
|
|
87
|
+
--focus: hsl(268 30% 55%);
|
|
70
88
|
|
|
71
89
|
--focus-outline-color: currentColor;
|
|
72
90
|
--focus-outline: calc(var(--border-width) * 2) solid var(--focus-outline-color);
|
|
73
91
|
--focus-outline-offset: 2px;
|
|
74
|
-
--focus-ring-width:
|
|
75
|
-
--focus-ring-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring);
|
|
92
|
+
--focus-ring-width: 2px;
|
|
76
93
|
}
|
|
77
94
|
```
|
|
78
95
|
|
|
@@ -211,6 +228,8 @@ Typography tokens cover the document baseline and common component needs.
|
|
|
211
228
|
:root {
|
|
212
229
|
--font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
213
230
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
231
|
+
--font-width: 100%;
|
|
232
|
+
--font-width-dense: 95%;
|
|
214
233
|
|
|
215
234
|
--line-height: 1.5;
|
|
216
235
|
--font-weight-normal: 400;
|
|
@@ -264,24 +283,41 @@ Disabled controls and disabled-prone components read `--disabled-opacity` for th
|
|
|
264
283
|
|
|
265
284
|
### Density
|
|
266
285
|
|
|
267
|
-
Density contexts swap shared spacing and geometry
|
|
286
|
+
Density contexts swap shared spacing and geometry, plus a slight typographic
|
|
287
|
+
width bonus:
|
|
268
288
|
|
|
269
289
|
```css
|
|
290
|
+
:root {
|
|
291
|
+
--font-width: 100%;
|
|
292
|
+
--font-width-dense: 95%;
|
|
293
|
+
}
|
|
294
|
+
|
|
270
295
|
.compact {
|
|
271
296
|
--gap: var(--space-20);
|
|
272
297
|
--density-space: var(--space-20);
|
|
273
298
|
--control-size: var(--control-size-sm);
|
|
299
|
+
font-stretch: var(--font-width-dense);
|
|
274
300
|
}
|
|
275
301
|
|
|
276
302
|
.spacious {
|
|
277
303
|
--gap: var(--space-50);
|
|
278
304
|
--density-space: var(--space-50);
|
|
279
305
|
--control-size: var(--control-size-lg);
|
|
306
|
+
font-stretch: var(--font-width);
|
|
280
307
|
}
|
|
281
308
|
```
|
|
282
309
|
|
|
283
|
-
Density
|
|
284
|
-
|
|
310
|
+
Density never changes font size or icon size — it may only use the denser font
|
|
311
|
+
width. `font-stretch` uses a variable `wdth` axis when available, or
|
|
312
|
+
participates in normal width-face matching for families that expose multiple
|
|
313
|
+
widths. Layout must never depend on the narrowing being available. Compact
|
|
314
|
+
density may slightly narrow variable typefaces when they support a width axis.
|
|
315
|
+
This is a density enhancement, not an overflow strategy: never condense a
|
|
316
|
+
component just because its label overflows at some viewport — that hides a
|
|
317
|
+
composition problem. A theme whose typeface has no useful width axis opts out
|
|
318
|
+
with `--font-width-dense: 100%`.
|
|
319
|
+
|
|
320
|
+
Participation is opt-in and selective: controls consume `--control-size`
|
|
285
321
|
for geometry; spacing helpers and rhythms consume `--density-space` and `--gap`;
|
|
286
322
|
components whose size is intrinsic (badge, avatar, spinner, rating, key, prose,
|
|
287
323
|
inline choice/switch) keep their own scales. A local component size overrides
|
|
@@ -426,9 +462,7 @@ Text controls (`.input`/`.textarea`/`.select`) expose the same lower-edge extens
|
|
|
426
462
|
|
|
427
463
|
Alerts expose the same idea on the leading edge instead of the lower one: `--alert-border-inline-start-color` and `--alert-border-inline-start-width` are unset by default and fall back to the regular `--ui-border`, so a theme can turn an alert into a callout with a colored flag on the inline-start side, matching the classic notice pattern, without a per-variant override.
|
|
428
464
|
|
|
429
|
-
A theme is not limited to the tokens above; it can restate any component-local token under a state selector to change the interaction recipe itself, not just the palette. The `
|
|
430
|
-
|
|
431
|
-
Buttons don't consume `--focus-outline` — button.css computes its own ring inline so the color can follow `--btn-focus-color` (intent-aware, unlike the plain `--focus`). It reuses the shared `--focus-ring-width` for the ring thickness and derives the color through `--btn-focus-ring-color` (a `color-mix()` of `--btn-focus-color` when supported, falling back to the shared `--focus-ring`).
|
|
465
|
+
A theme is not limited to the tokens above; it can restate any component-local token or rule under a state selector to change the interaction recipe itself, not just the palette. The `gradient` theme does this for field focus: it restores a `--focus` border plus an outer translucent halo in place of the core inset outline.
|
|
432
466
|
|
|
433
467
|
Rules:
|
|
434
468
|
|
|
@@ -445,9 +479,11 @@ Rules:
|
|
|
445
479
|
|
|
446
480
|
Themes override tokens, not selectors. The themes in `src/css/themes/` are repository-only demo examples, not included in the default stylesheet or the npm package; they exist to show valid ways to use this contract, such as `ocean`, `square`, `cyberpunk`, and `brutalist`.
|
|
447
481
|
|
|
448
|
-
A minimal recolor theme overrides the intent pairs, surfaces, text colors, border, focus, and
|
|
482
|
+
A minimal recolor theme overrides the intent pairs, surfaces, text colors, border, focus, hover overlay, and shadow color. Pick `--focus` as a mid-tone that holds 3:1 against both `--surface` and `--surface-solid` in every scheme the theme declares; a pastel dark-scheme primary usually fails on the light solid surface. `bun run report:theme-contrast` measures both pairs.
|
|
483
|
+
|
|
484
|
+
When overriding an intent color, review its paired `--*-fg` and `--*-soft-fg`. A theme that declares no hook falls back to the `--soft-fg-mix` derivation: one global percentage applied to every role, so it carries no contrast guarantee for a palette it was not tuned against. `bun run report:theme-contrast` prints the resting and hovered soft pair for every intent of every island, which is how a theme finds the roles that need a hook or a lower `--soft-fg-mix`.
|
|
449
485
|
|
|
450
|
-
|
|
486
|
+
The default palette's hooks apply to `:root` and to the `light`/`dark` boundaries only. Any other `data-theme` value resets them to the derivation, whether the attribute sits on `<html>` or on a nested island.
|
|
451
487
|
|
|
452
488
|
Shape, shadow, motion, typography, and soft-variant mix tokens are optional knobs. Override them only when the theme actually changes that part of the system.
|
|
453
489
|
|
|
@@ -488,6 +524,7 @@ A minimal recolor theme (illustrative, not a shipped theme):
|
|
|
488
524
|
--border: hsl(260 24% 84%);
|
|
489
525
|
--focus: var(--primary);
|
|
490
526
|
--hover-overlay: hsl(260 30% 10% / 0.04);
|
|
527
|
+
--shadow-color: hsl(260 30% 10%);
|
|
491
528
|
--soft-bg-mix: 84%;
|
|
492
529
|
--soft-border-mix: 58%;
|
|
493
530
|
|
|
@@ -497,7 +534,7 @@ A minimal recolor theme (illustrative, not a shipped theme):
|
|
|
497
534
|
}
|
|
498
535
|
```
|
|
499
536
|
|
|
500
|
-
Several tokens are theme-derived aliases that reference other tokens — `--state-selected`/`--state-selected-fg`/`--state-disabled`, `--indicator-ring`, `--shadow`/`--shadow-popout`, `--heading`, `--selection-bg`/`--selection-fg
|
|
537
|
+
Several tokens are theme-derived aliases that reference other tokens — `--state-selected`/`--state-selected-fg`/`--state-disabled`, `--indicator-ring`, `--shadow`/`--shadow-popout`, `--heading`, and `--selection-bg`/`--selection-fg`. They are declared on `:root, [data-theme]` so they recompute on every theme boundary: a custom property resolves its `var()` references at computed-value time on the element that declares it, so an alias declared only on `:root` would be inherited as an already-resolved value and would not follow a `[data-theme]` island's overridden tokens. A theme that wants a distinct alias (e.g. a `--selection-bg` of its own) overrides it explicitly afterwards, which wins by cascade order.
|
|
501
538
|
|
|
502
539
|
Without `data-theme`, the default theme advertises `color-scheme: light dark` and follows the user's OS preference in browsers that support `light-dark()`. Dark themes should set `color-scheme: dark`. Light themes should set `color-scheme: light`. Browsers without `light-dark()` receive the light fallback.
|
|
503
540
|
|
|
@@ -113,6 +113,16 @@ the document) and `--font-mono` (for `code` / `kbd` / `samp` / `pre`). There is
|
|
|
113
113
|
theme-level token in your own theme when a project actually needs one; the
|
|
114
114
|
baseline stays sans so app UI inherits predictably.
|
|
115
115
|
|
|
116
|
+
### Font width
|
|
117
|
+
|
|
118
|
+
Two public hooks carry the typographic side of density: `--font-width` (normal
|
|
119
|
+
width) and `--font-width-dense` (compact width). The document reads
|
|
120
|
+
`--font-width` through `font-stretch`; `.compact` applies
|
|
121
|
+
`--font-width-dense` and `.spacious` restores `--font-width`. A theme whose
|
|
122
|
+
typeface has no useful width axis sets `--font-width-dense: 100%`. Width is a
|
|
123
|
+
density token, not a responsive escape hatch — never condense text to fix an
|
|
124
|
+
overflowing label.
|
|
125
|
+
|
|
116
126
|
## Font weights
|
|
117
127
|
|
|
118
128
|
The framework exposes a small set of weights:
|
|
@@ -30,37 +30,29 @@ ARIA and native HTML, and per-widget configuration uses self-describing
|
|
|
30
30
|
npm install actual-css
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Import the full
|
|
33
|
+
Import what you use. The simplest start is the package's full entry, copied
|
|
34
|
+
into your project and pruned — see
|
|
35
|
+
[Start from the full entry](modular-import.md#start-from-the-full-entry):
|
|
34
36
|
|
|
35
37
|
```css
|
|
36
|
-
@import "actual-css/
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
`actual-css/full` ships every functional family. The bare `actual-css` entrypoint
|
|
40
|
-
is the minimal core (reset, tokens, theme, base, intents, variants, focus,
|
|
41
|
-
print).
|
|
42
|
-
|
|
43
|
-
Or compose only the pieces you use:
|
|
44
|
-
|
|
45
|
-
```css
|
|
46
|
-
@import "actual-css/css";
|
|
38
|
+
@import "actual-css/css"; /* core */
|
|
47
39
|
@import "actual-css/css/layout";
|
|
40
|
+
@import "actual-css/css/forms/all";
|
|
48
41
|
@import "actual-css/css/components/button";
|
|
49
42
|
@import "actual-css/css/components/card";
|
|
50
|
-
@import "actual-css/css/forms";
|
|
51
|
-
@import "actual-css/css/components/flyout";
|
|
52
43
|
@import "actual-css/css/utilities";
|
|
53
44
|
```
|
|
54
45
|
|
|
55
|
-
`actual-css/css` is the
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
[modular import guide](modular-import.md) for the full map.
|
|
46
|
+
`actual-css/css` is the core (reset, tokens, theme, base, intents, variants,
|
|
47
|
+
focus, print). Each family and module is its own import; the
|
|
48
|
+
[modular import guide](modular-import.md) has the full map.
|
|
59
49
|
|
|
60
|
-
|
|
50
|
+
For zero-config use — prototypes, CDN, or when bundle size is not worth
|
|
51
|
+
optimizing — the bare `actual-css` entrypoint and `actual-css/full` both resolve
|
|
52
|
+
to the complete compiled framework:
|
|
61
53
|
|
|
62
54
|
```html
|
|
63
|
-
<link rel="stylesheet" href="actual.full.min.css">
|
|
55
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/actual-css@0.10/dist/actual.full.min.css">
|
|
64
56
|
```
|
|
65
57
|
|
|
66
58
|
The package does not maintain separate partial bundles. Modular entrypoints map
|
|
@@ -76,11 +68,12 @@ Actual CSS uses a small unprefixed class grammar:
|
|
|
76
68
|
|
|
77
69
|
Intents are `.primary`, `.secondary`, `.success`, `.warning`, and `.danger`, and
|
|
78
70
|
work across components. Variants such as `.solid`, `.soft`, `.outline`, and `.surface` are
|
|
79
|
-
shared by buttons, badges, alerts, and cards;
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
shared by buttons, badges, alerts, and cards; a subtree that needs another
|
|
72
|
+
palette is a `data-theme` island, not a class. `.ghost` and `.link` are
|
|
73
|
+
button-only. Size variants `.sm` and `.lg` scale typography and
|
|
82
74
|
participating component geometry consistently. Density contexts `.compact` and
|
|
83
|
-
`.spacious` change geometry and spacing without changing
|
|
75
|
+
`.spacious` change geometry and spacing without changing font size or icons;
|
|
76
|
+
`.compact` may slightly narrow typefaces that support a width axis.
|
|
84
77
|
Undocumented `is-*` classes are runtime internals.
|
|
85
78
|
|
|
86
79
|
```html
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
# Modular imports
|
|
2
2
|
|
|
3
|
-
Actual CSS
|
|
3
|
+
Actual CSS has two kinds of entrypoint. Without `/css`, you get a compiled artifact ready to serve. With `/css`, you compose the sources.
|
|
4
4
|
|
|
5
5
|
## Entrypoints
|
|
6
6
|
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
```text
|
|
8
|
+
Composable source CSS (recommended)
|
|
9
|
+
actual-css/css core
|
|
10
|
+
actual-css/css/<family> one family, e.g. css/layout, css/forms/all
|
|
11
|
+
actual-css/css/<family>/* one module, e.g. css/components/button
|
|
12
|
+
actual-css/css/full every family, as source
|
|
13
|
+
|
|
14
|
+
Zero-config distribution
|
|
15
|
+
actual-css complete compiled framework
|
|
16
|
+
actual-css/full the same bundle, named explicitly
|
|
10
17
|
```
|
|
11
18
|
|
|
12
|
-
`actual-css` contains the shared baseline: reset, tokens, theme, document defaults, intents, universal variants, focus, and print.
|
|
19
|
+
`actual-css/css` contains the shared baseline: reset, tokens, theme, document defaults, intents, universal variants, focus, and print.
|
|
13
20
|
|
|
14
21
|
It contains no typography, layout, forms, components, effects, or utilities.
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
The full framework starts from the core and adds every family in cascade order:
|
|
17
24
|
|
|
18
25
|
```text
|
|
19
26
|
core → typography → layout → forms → components → effects → utilities
|
|
@@ -27,6 +34,46 @@ Components may enhance or replace that treatment in interactive states, but thei
|
|
|
27
34
|
|
|
28
35
|
When an interactive state replaces the outline, it must preserve a visible focus indicator in forced-colors, either with an outline-based fallback or by keeping the replacement out of forced-colors.
|
|
29
36
|
|
|
37
|
+
## Start from the full entry
|
|
38
|
+
|
|
39
|
+
Deleting is easier than adding, and it keeps the cascade order right. Copy the
|
|
40
|
+
package's full entry into your project, rewrite its relative imports to
|
|
41
|
+
package paths, then delete what you do not need:
|
|
42
|
+
|
|
43
|
+
- CSS: `src/css/actual.full.css`. Prefix each import with `actual-css/css/`
|
|
44
|
+
and drop `.css` and `/index`; `./actual.css` is `actual-css/css`. To go below
|
|
45
|
+
family level, replace a family line with the imports of its `index.css`,
|
|
46
|
+
rewritten the same way.
|
|
47
|
+
- JS: `src/js/full.js`. Prefix each import with `actual-css/js/` and drop
|
|
48
|
+
`.js`; `./index.js` is `actual-css/js`.
|
|
49
|
+
|
|
50
|
+
```css
|
|
51
|
+
/* app/index.css — actual.full.css, rewritten, components expanded and pruned */
|
|
52
|
+
@import "actual-css/css";
|
|
53
|
+
@import "actual-css/css/typography";
|
|
54
|
+
@import "actual-css/css/layout";
|
|
55
|
+
@import "actual-css/css/forms/all";
|
|
56
|
+
@import "actual-css/css/components/button";
|
|
57
|
+
@import "actual-css/css/components/close";
|
|
58
|
+
@import "actual-css/css/components/card";
|
|
59
|
+
@import "actual-css/css/components/modal";
|
|
60
|
+
@import "actual-css/css/utilities";
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
// app/index.js — full.js, rewritten and pruned
|
|
65
|
+
import "actual-css/js/flyout";
|
|
66
|
+
import "actual-css/js/dialog";
|
|
67
|
+
import "actual-css/js/dismiss";
|
|
68
|
+
import "actual-css/js/tooltip";
|
|
69
|
+
import "actual-css/js";
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
JS modules import what they depend on. CSS modules do not, and three are
|
|
73
|
+
shared: keep `components/close` with modal, drawer, alert, or a removable
|
|
74
|
+
badge; `components/bleed` with a `.bleed` child of card, drawer, or accordion;
|
|
75
|
+
`components/spinner` with `components/busy`.
|
|
76
|
+
|
|
30
77
|
## Family manifests
|
|
31
78
|
|
|
32
79
|
Each family is one import. The contents are enumerations rather than table
|
|
@@ -49,7 +49,10 @@ never tracked.
|
|
|
49
49
|
|
|
50
50
|
`enhance()` observes DOM insertions and removals, not attribute changes. If an
|
|
51
51
|
already-connected element receives a behavior attribute later, call the returned
|
|
52
|
-
`refresh(node)` handle
|
|
52
|
+
`refresh(node)` handle of your own `enhance()`, or `applyEnhancement()` for a
|
|
53
|
+
`data-enhance` token. The built-in `data-*` behaviors (`data-mask`,
|
|
54
|
+
`data-filter`, …) expose no handle: insert the element with the attribute
|
|
55
|
+
already set. Behavior attributes are setup-time contracts: removing
|
|
53
56
|
one does not disconnect an active behavior. If an application needs a live
|
|
54
57
|
enable/disable switch, keep that state inside its enhancer and clean it up when
|
|
55
58
|
the element leaves the DOM.
|
|
@@ -229,8 +232,8 @@ Three non-obvious requirements:
|
|
|
229
232
|
|
|
230
233
|
Lifecycle: `prepareSurface` → `openSurface` → `closeSurface` →
|
|
231
234
|
`disconnectSurface`. `retainSurface(panel)` reference-counts a surface shared by
|
|
232
|
-
several triggers and returns a release function; `isSurfaceOpen`
|
|
233
|
-
|
|
235
|
+
several triggers and returns a release function; `isSurfaceOpen` reads the
|
|
236
|
+
current state. The separate `escape` primitive adds
|
|
234
237
|
visible dismissable UI to the shared per-document Escape stack.
|
|
235
238
|
|
|
236
239
|
Actual-managed surfaces are mutually exclusive within a document. Opening a
|
|
@@ -785,8 +788,9 @@ document.addEventListener("actual:invalid", (event) => {
|
|
|
785
788
|
|
|
786
789
|
Custom rules go in `data-validation-rules` and resolve through
|
|
787
790
|
`FormValidator.registerRule`. Built-in rules are `same`, `number`, `digits`,
|
|
788
|
-
`alnum`, and `
|
|
789
|
-
errors flow back through
|
|
791
|
+
`alnum`, `starts-with`, `ends-with`, `date`, and `tel-prefix`. The library never
|
|
792
|
+
performs network validation; server errors flow back through
|
|
793
|
+
`FormValidator.setErrors(form, { name: message })` and
|
|
790
794
|
`FormValidator.clearFieldError(field)`.
|
|
791
795
|
|
|
792
796
|
```js
|
|
@@ -25,17 +25,29 @@ The layered import is the cleanest way to keep both stylesheets during the
|
|
|
25
25
|
migration:
|
|
26
26
|
|
|
27
27
|
```css
|
|
28
|
+
/* Tailwind v4 emits its own layers (theme, base, components, utilities),
|
|
29
|
+
so declare the order explicitly: Actual sits above Tailwind components
|
|
30
|
+
but below Tailwind utilities during the migration. */
|
|
31
|
+
@layer theme, base, components, actual, utilities;
|
|
32
|
+
|
|
28
33
|
@import "tailwind.css"; /* your compiled Tailwind output */
|
|
29
|
-
@layer actual;
|
|
30
34
|
@import "actual-css/full" layer(actual);
|
|
35
|
+
|
|
31
36
|
/* Unlayered project overrides stay on top */
|
|
32
37
|
@import "app.css";
|
|
33
38
|
```
|
|
34
39
|
|
|
35
|
-
The full import places every Actual rule in a single `actual` layer
|
|
36
|
-
|
|
37
|
-
runs
|
|
38
|
-
|
|
40
|
+
The full import places every Actual rule in a single `actual` layer. The
|
|
41
|
+
explicit `@layer` order is what keeps Tailwind utilities above Actual while
|
|
42
|
+
the migration runs — not the unlayered status of either output. See
|
|
43
|
+
[Cascade layer strategy](https://github.com/lekoala/actual-css/blob/master/docs/design-notes/cascade-layer.md)
|
|
44
|
+
for the limitations of the approach.
|
|
45
|
+
|
|
46
|
+
Layers do not scope custom properties: both frameworks define
|
|
47
|
+
`--font-sans`, `--font-mono`, `--font-weight-*`, and `--radius-sm` /
|
|
48
|
+
`--radius-lg`. With `actual` after `theme`, `font-sans` takes Actual's font
|
|
49
|
+
stack and `rounded-lg` resolves to Actual's `--radius-lg`. Expect these
|
|
50
|
+
token collisions on migrated screens until Tailwind is removed.
|
|
39
51
|
|
|
40
52
|
Do not assume that loading both complete stylesheets is automatically safe.
|
|
41
53
|
|