actual-css 0.11.0 → 0.12.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.
Files changed (92) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +29 -5
  3. package/components.json +15 -17
  4. package/dist/actual.full.css +403 -227
  5. package/dist/actual.full.min.css +1 -1
  6. package/docs/brand/favicon.svg +5 -0
  7. package/docs/brand/lockup.svg +12 -0
  8. package/docs/brand/logo-dark.svg +9 -0
  9. package/docs/brand/logo-light.svg +9 -0
  10. package/docs/brand/logo.svg +11 -0
  11. package/docs/brand/mark.svg +11 -0
  12. package/docs/navigation.json +4 -2
  13. package/docs/pages/components/alert.md +2 -10
  14. package/docs/pages/components/badge.md +3 -9
  15. package/docs/pages/components/bleed.md +5 -4
  16. package/docs/pages/components/card.md +31 -2
  17. package/docs/pages/components/close.md +9 -3
  18. package/docs/pages/components/dialog.md +248 -31
  19. package/docs/pages/components/drawer.md +2 -2
  20. package/docs/pages/components/meter.md +2 -0
  21. package/docs/pages/components/navbar.md +8 -9
  22. package/docs/pages/components/table.md +3 -3
  23. package/docs/pages/enhancements/flyout.md +2 -2
  24. package/docs/pages/enhancements/scrollspy.md +1 -1
  25. package/docs/pages/enhancements/status-bar.md +2 -2
  26. package/docs/pages/examples/overview.md +3 -1
  27. package/docs/pages/forms/date-picker.md +90 -0
  28. package/docs/pages/forms/detached-actions.md +37 -30
  29. package/docs/pages/forms/form-actions.md +61 -28
  30. package/docs/pages/forms/input-policy.md +1 -1
  31. package/docs/pages/forms/overview.md +6 -5
  32. package/docs/pages/forms/sticky-actions.md +85 -83
  33. package/docs/pages/forms/validation.md +5 -5
  34. package/docs/pages/foundations/philosophy.md +5 -3
  35. package/docs/pages/foundations/theming.md +15 -4
  36. package/docs/pages/foundations/tokens.md +50 -33
  37. package/docs/pages/foundations/typography.md +4 -7
  38. package/docs/pages/guides/bootstrap.md +2 -2
  39. package/docs/pages/guides/design-tools.md +36 -0
  40. package/docs/pages/guides/integrating-actual-css.md +5 -1
  41. package/docs/pages/guides/introduction.md +3 -4
  42. package/docs/pages/guides/modular-import.md +3 -0
  43. package/docs/pages/guides/progressive-enhancement.md +2 -2
  44. package/docs/pages/guides/tailwind.md +70 -0
  45. package/docs/pages/guides/upgrading.md +74 -0
  46. package/docs/pages/layout/cluster.md +28 -2
  47. package/docs/pages/layout/overview.md +1 -1
  48. package/docs/pages/layout/stack.md +21 -16
  49. package/docs/pages/layout/topbar.md +1 -1
  50. package/docs/pages/patterns/navigation-list.md +16 -46
  51. package/docs/pages/patterns/overview.md +3 -4
  52. package/docs/pages/utilities/flex.md +30 -20
  53. package/docs/pages/utilities/sizing-wrapping.md +1 -1
  54. package/docs/pages/utilities/spacing.md +4 -3
  55. package/package.json +3 -2
  56. package/reserved-classes.json +3 -3
  57. package/skills/actual-css/references/enhancements.md +38 -0
  58. package/src/cli/actual-css.js +75 -6
  59. package/src/css/components/avatar.css +16 -9
  60. package/src/css/components/badge.css +1 -5
  61. package/src/css/components/bleed.css +5 -5
  62. package/src/css/components/button.css +17 -10
  63. package/src/css/components/card.css +18 -10
  64. package/src/css/components/chat.css +4 -5
  65. package/src/css/components/close.css +17 -6
  66. package/src/css/components/drawer.css +19 -3
  67. package/src/css/components/flyout.css +3 -0
  68. package/src/css/components/index.css +0 -1
  69. package/src/css/components/meter.css +5 -2
  70. package/src/css/components/modal.css +157 -69
  71. package/src/css/components/navbar.css +14 -25
  72. package/src/css/core/base.css +1 -1
  73. package/src/css/core/reset.css +2 -1
  74. package/src/css/core/theme.css +4 -0
  75. package/src/css/core/tokens.css +28 -10
  76. package/src/css/core/variants.css +41 -14
  77. package/src/css/forms/form-actions.css +15 -10
  78. package/src/css/forms/native.css +5 -1
  79. package/src/css/layout/cluster.css +11 -0
  80. package/src/css/layout/topbar.css +12 -6
  81. package/src/css/utilities/base.css +5 -0
  82. package/src/css/utilities/extra.css +3 -7
  83. package/src/tooling/color.js +65 -0
  84. package/src/tooling/design-components.js +286 -0
  85. package/src/tooling/design-export.js +69 -0
  86. package/src/tooling/design-tokens.js +474 -0
  87. package/src/tooling/penpot-plugin/manifest.json +7 -0
  88. package/src/tooling/penpot-plugin/plugin.js +272 -0
  89. package/src/tooling/penpot-plugin/ui.html +58 -0
  90. package/src/tooling/theme-contrast.js +209 -0
  91. package/docs/pages/patterns/actions.md +0 -52
  92. package/src/css/components/actions.css +0 -27
@@ -380,6 +380,76 @@ Actual theme tokens should handle shared theme behavior. Local CSS remains appro
380
380
 
381
381
  This is particularly important when migrating a Tailwind application with a large custom color palette.
382
382
 
383
+ ### Map the Tailwind palette to theme roles
384
+
385
+ Tailwind's theme is a set of ramps: `--color-zinc-50` … `--color-zinc-950`,
386
+ one per hue. Actual's theme contract is a set of roles: `--surface`,
387
+ `--border`, `--text-muted`, `--primary`, `--focus`. Each element picks a
388
+ step in Tailwind; Actual picks once per role, in the theme, and every
389
+ component reads the role. Map one neutral family and one brand hue, then
390
+ stop: the rest of the ramp has no consumer.
391
+
392
+ A starting point for a zinc and blue application:
393
+
394
+ | Role | Light | Dark |
395
+ | ------------------ | ---------- | ---------- |
396
+ | `--surface` | `white` | `zinc-950` |
397
+ | `--surface-raised` | `white` | `zinc-900` |
398
+ | `--surface-subtle` | `zinc-100` | `zinc-800` |
399
+ | `--surface-solid` | `zinc-900` | `zinc-100` |
400
+ | `--border` | `zinc-200` | `zinc-700` |
401
+ | `--text` | `zinc-950` | `zinc-50` |
402
+ | `--text-muted` | `zinc-600` | `zinc-400` |
403
+ | `--text-subtle` | `zinc-500` | `zinc-500` |
404
+ | `--neutral` | `zinc-600` | `zinc-400` |
405
+ | `--primary` | `blue-600` | `blue-400` |
406
+ | `--focus` | `blue-500` | `blue-500` |
407
+
408
+ Each scheme is one `light-dark()` pair on the role, instead of a `dark:`
409
+ variant on every element:
410
+
411
+ ```css
412
+ [data-theme="app"] {
413
+ color-scheme: light dark;
414
+
415
+ --surface: light-dark(var(--color-white), var(--color-zinc-950));
416
+ --border: light-dark(var(--color-zinc-200), var(--color-zinc-700));
417
+ --primary: light-dark(var(--color-blue-600), var(--color-blue-400));
418
+ --primary-fg: light-dark(var(--color-white), var(--color-zinc-950));
419
+ --focus: var(--color-blue-500);
420
+ /* … the other roles of the table */
421
+ }
422
+ ```
423
+
424
+ Tailwind v4 emits only the theme variables your sources use; declare the
425
+ palette with `@theme static` while the theme reads them, and replace them with
426
+ their literal values before Tailwind leaves the build.
427
+
428
+ What the ramp does not decide for you:
429
+
430
+ - **Foreground pairs.** Tailwind has no `-fg` step. White on `blue-600` holds
431
+ 4.5:1, white on `blue-500` does not, so a dark-scheme primary lightened to
432
+ `blue-400` needs a dark `--primary-fg`. Every intent needs its pair:
433
+ `--warning-fg` on an amber is dark ink.
434
+ - **Focus.** `--focus` must hold 3:1 on `--surface` and `--surface-solid` in
435
+ both schemes, so it is a mid-tone, not the primary step. `blue-500` holds
436
+ on `white`, `zinc-900`, `zinc-950` and `zinc-100`: one value covers both
437
+ schemes.
438
+ - **Neutral temperature.** `slate`, `gray`, `zinc`, `neutral` and `stone` are
439
+ the same ramp at different temperatures; `neutral` is pure grey. Pick the
440
+ family that leans toward your primary, and take every neutral role from it.
441
+ - **No subtle intent steps.** Do not map `blue-50` / `blue-100` to tinted
442
+ surfaces: `.soft` mixes the intent into the local surface, so there is no
443
+ `--primary-subtle` to fill.
444
+ - **Shadow and hover ink.** Tailwind shadows are black; Actual derives
445
+ `--shadow` and `--shadow-popout` from one `--shadow-color`. Take it from the
446
+ neutral family's darkest step, and `--hover-overlay` as a few percent of
447
+ `--text`.
448
+
449
+ `bunx --bun actual-css contrast --theme FILE` measures the focus, soft and inverse
450
+ pairs in both schemes. Check the text tiers on `--surface-subtle` by hand:
451
+ `zinc-500` holds 4.5:1 on `white` but not on `zinc-100`.
452
+
383
453
  ## Forms
384
454
 
385
455
  Tailwind applications often construct form controls from utility combinations or use an additional forms plugin.
@@ -0,0 +1,74 @@
1
+ # Upgrading to 0.12
2
+
3
+ Each step below is a search for a removed class or hook and its replacement.
4
+ The [changelog](https://github.com/lekoala/actual-css/blob/master/CHANGELOG.md)
5
+ lists every change; this page keeps the ones that need an edit.
6
+
7
+ **Related terms:** migration, breaking changes, update, version.
8
+
9
+ ## Action rows
10
+
11
+ `.actions`, `.navbar-nav` and the layout of `.form-actions` are gone. A row of
12
+ actions is a `.cluster`; a vertical list is `stack list-reset`. Replace
13
+ `class="actions"` and `class="navbar-nav"` with `class="cluster"`, and
14
+ `class="form-actions"` with `class="cluster form-actions"`:
15
+
16
+ ```html
17
+ <menu class="cluster">…</menu>
18
+ <ul class="cluster">…</ul>
19
+ <div class="cluster form-actions">…</div>
20
+ <ul class="stack list-reset">…</ul>
21
+ ```
22
+
23
+ - The row takes the framework `--gap` (0.75rem). The former `.actions` used
24
+ 0.5rem: add `.tight` to keep it.
25
+ - The former `.navbar-nav` used `--space-10` (0.25rem), which no utility
26
+ reproduces. If the tighter navbar rhythm matters, set
27
+ `gap: var(--space-10)` on that row in application CSS.
28
+ - `.form-actions` has no top margin and no `--form-actions-margin-block-start`:
29
+ put `.stack` on the form. `--form-actions-justify` and `--form-actions-align`
30
+ still apply. In a modular build, import `layout/cluster` before
31
+ `forms/form-actions`.
32
+ - `.justify-content-*` aligns only its own element and no longer reaches a
33
+ nested `.cluster`. Put the utility on the row it should align.
34
+
35
+ ## Dialogs
36
+
37
+ - `.dialog-confirmation` is removed. Compose `.media` with `.dialog-icon`, then
38
+ a `<footer class="bleed background-subtle cluster justify-content-space-between">`;
39
+ the recipe is in [Dialog](../components/dialog.md).
40
+ - A `dialog.modal` body `<footer>` has no layout of its own: write
41
+ `<footer class="cluster justify-content-end">`.
42
+ - `--modal-header-bg` is removed: put a `.background-*` utility on the
43
+ `dialog.modal > header` band. Only that default fill has zero specificity;
44
+ the header's layout keeps its structural rule.
45
+ - The confirmation recipe uses the regular 1rem modal inset where the former
46
+ `.dialog-confirmation` used 1.5rem. Set `--modal-pad: var(--space-50)` on
47
+ the dialog to keep the roomier treatment.
48
+
49
+ ## Cards
50
+
51
+ The layout of a `.card` header or footer row is a zero-specificity default: any
52
+ author rule that targets the slot replaces it, not only a `.media`, `.cluster`,
53
+ `.form-actions` or `.justify-content-*` class. Check application CSS for bare
54
+ element rules such as `header { … }` or `footer { … }`, which now win over the
55
+ card's slot row.
56
+
57
+ ## Themes and density
58
+
59
+ - A theme sets `--control-pad-x-sm`, `--control-pad-x-md` and
60
+ `--control-pad-x-lg` instead of `--control-pad-x`. Used as a nested island,
61
+ it re-selects them in its own block; see
62
+ [Tokens](../foundations/tokens.md).
63
+ - `--font-width-dense` is removed, and `.compact` no longer condenses type: set
64
+ `font-stretch` on the element that should render condensed.
65
+
66
+ ## Rendering changes without an edit
67
+
68
+ These need no markup change; compare the affected screens.
69
+
70
+ - `.sm` controls have 13px of inline padding instead of 14px.
71
+ - `.compact` and `.spacious` controls get narrower or wider, not only shorter
72
+ or taller.
73
+ - `.nav-list` rows sit `--space-10` apart instead of `--space-20`.
74
+ - `.card.compact` lowers the gap between its children to `--space-20`.
@@ -17,6 +17,30 @@ between items always comes from `--gap`. Unlike `.stack`, which resets only the
17
17
  block axis, cluster resets margins on both axes — a wrapping cluster's `gap`
18
18
  controls inline spacing between items and block spacing between wrapped rows.
19
19
 
20
+ ## Action rows
21
+
22
+ Actions are content; the cluster owns the geometry. A semantic action list is a
23
+ `<menu>` (or `<ul>`) with `.cluster`:
24
+
25
+ ```html demo
26
+ <menu class="cluster">
27
+ <li><button class="btn primary" type="button">Save</button></li>
28
+ <li><button class="btn outline" type="button">Cancel</button></li>
29
+ </menu>
30
+ ```
31
+
32
+ There is no `.actions` class. A dense row is `cluster tight`; a vertical action
33
+ list is `stack list-reset`.
34
+
35
+ ## List chrome
36
+
37
+ `.cluster` neutralizes the native chrome of a `<ul>`, `<ol>` or `<menu>` it is
38
+ applied to. The element stays a list in the DOM and for assistive technology,
39
+ but a horizontal, wrapping group cannot carry markers and indentation
40
+ meaningfully, so they are removed. `.stack` makes no such change — an
41
+ `<ol class="stack">` keeps its numbers. Use `.list-reset` alone for a plain list
42
+ with no layout.
43
+
20
44
  ## CSS hooks
21
45
 
22
46
  - `--cluster-justify` — main-axis distribution (`justify-content`).
@@ -48,8 +72,10 @@ wraps to several lines — set `--cluster-align`.
48
72
  ```
49
73
 
50
74
  The optional utility layer ships `.justify-content-start`, `.justify-content-center`,
51
- `.justify-content-end` and `.justify-content-space-between`, which set
52
- `--cluster-justify` for you. See the utilities page.
75
+ `.justify-content-end` and `.justify-content-space-between`. They set
76
+ `justify-content` on that one row only; a nested `.cluster` keeps its own
77
+ alignment. `--cluster-justify` is inherited, so setting it on a region reaches
78
+ nested clusters too. See the utilities page.
53
79
 
54
80
  ## Controls inside a wrapping cluster
55
81
 
@@ -57,4 +57,4 @@ Prefer a parent `gap` for relationships between peers instead of encoding siblin
57
57
 
58
58
  Before adding a divider or other separating chrome, consider whether additional spacing already expresses the boundary clearly.
59
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 [Choosing a density](./stack.md#choosing-a-density) for the nesting and density mechanics.
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 [Choosing a rhythm](./stack.md#choosing-a-rhythm) for the nesting mechanics, and `.tight` / `.loose` for a gap-only change.
@@ -39,19 +39,24 @@ content, keep them in normal block flow instead:
39
39
  Use `.stack` for the vertical rhythm *between* related items inside one region,
40
40
  not as the wrapper that lays out independent full-width regions of a page.
41
41
 
42
- ## Choosing a density
42
+ ## Choosing a rhythm
43
43
 
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:
44
+ `--gap` is the primitive's channel. `.tight` and `.loose` set it and nothing
45
+ else; apply one on the stack to space one instance, or on an ancestor to reach
46
+ nested layouts. Pick the one that matches how tightly the children belong
47
+ together:
48
48
 
49
49
  | Markup | Gap | Use for |
50
50
  | ----------------- | ---- | ------------------------------------------ |
51
51
  | `.stack gap-none` | 0 | Lines forming one typographic unit |
52
- | `.stack compact` | 8px | A homogeneous series of controls |
52
+ | `.stack tight` | 8px | A homogeneous series of controls |
53
53
  | `.stack` | 12px | Normal flow between distinct elements |
54
- | `.stack spacious` | 24px | Sections, or blocks that read as separated |
54
+ | `.stack loose` | 24px | Sections, or blocks that read as separated |
55
+
56
+ **Size** changes a component's scale. **Density** (`.compact`, `.spacious`)
57
+ changes UI geometry and rhythm together: gap, padding, control size. **Rhythm**
58
+ (`.tight`, `.loose`) changes the gap only — closer or farther items, tighter
59
+ spacing without smaller buttons. Use one rhythm class per element.
55
60
 
56
61
  One typographic unit means a name and a job title, or a figure and its caption.
57
62
  A homogeneous series means a radio list, a checkbox list, or a compact vertical
@@ -60,13 +65,13 @@ menu.
60
65
  The distinction between the first two matters. `42` above `Open issues` is
61
66
  almost a single block of text, so it takes `gap-none`. Three `.choice` labels
62
67
  stay three separate controls that happen to form one group, so they take
63
- `compact` — tighter than the default, but still spaced.
68
+ `tight` — tighter than the default, but still spaced.
64
69
 
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).
70
+ `.tight` and `.loose` rebind `--gap` to `--space-20` and `--space-50`, the same
71
+ steps `.compact` and `.spacious` use. Because the token is inherited, they also
72
+ tighten the inner gap of any nested stack, cluster, and grid. For a one-off gap
73
+ that must *not* reach nested layouts, set the `gap` property directly on the
74
+ instance (the next section explains why).
70
75
 
71
76
  A stack that mixes kinds keeps the default: five `.field` wrappers and one lone
72
77
  `.choice` is a form that contains a checkbox, not a list of options, and
@@ -92,7 +97,7 @@ depth:
92
97
  ```
93
98
 
94
99
  Both give the region the same spacing; only the second stops there. This is what
95
- makes a nested `.stack compact` a real density choice — 12px down to 8px — rather
100
+ makes a nested `.stack tight` a real rhythm choice — 12px down to 8px — rather
96
101
  than a patch cancelling a rhythm inherited from three levels up.
97
102
 
98
103
  Setting `--gap` is still the right move on the element that *consumes* it: a
@@ -100,8 +105,8 @@ one-off `--gap` on a card body or an actions row tunes that primitive and
100
105
  nothing below it, because the setter is the consumer. The leak only appears when
101
106
  a container sets the token and its children read it.
102
107
 
103
- `.compact` and `.spacious` are the deliberate exception: they set `--gap`
104
- precisely so a density context reaches nested layouts.
108
+ The rhythm and density classes are the deliberate exception: they set `--gap`
109
+ precisely so the context reaches nested layouts.
105
110
 
106
111
  ## Grouping items tightly
107
112
 
@@ -4,7 +4,7 @@ Sticky, frosted top bar shell for app/dashboard layouts with a persistent sideba
4
4
 
5
5
  > **Module** — import `actual-css/css/layout/topbar` or `actual-css/css/layout`.
6
6
 
7
- Use `.topbar` for the structural shell of an app-shell header: sticky positioning, stacking, and a frosted background. Row content — search, breadcrumb, actions — stays local to the page.
7
+ Use `.topbar` for the structural shell of an app-shell header: sticky positioning, stacking, and a frosted background. Its children sit in a centered row by default; a layout primitive on the same element, such as `topbar cluster`, replaces that row. Row content — search, breadcrumb, actions — stays local to the page.
8
8
 
9
9
  ```html demo
10
10
  <header class="topbar">
@@ -1,14 +1,15 @@
1
1
  # Navigation List
2
2
 
3
- Use `.nav-list` for a semantic list of navigation links.
4
-
5
- It removes native list chrome but does not force a direction. Combine it with layout primitives depending on context.
3
+ Use `.nav-list` for a vertical list of navigation links: it removes native list
4
+ chrome, stacks the rows and stretches each `.nav-link` across the row. For a
5
+ horizontal row of links, use `.cluster` on the list, which removes the list
6
+ chrome too.
6
7
 
7
8
  ```html demo
8
9
  <div class="stack">
9
10
  <h2>Navigation</h2>
10
11
  <nav aria-label="Main navigation">
11
- <ul class="nav-list cluster">
12
+ <ul class="cluster">
12
13
  <li><a href="/docs">Docs</a></li>
13
14
  <li><a href="/components">Components</a></li>
14
15
  <li><a href="/examples">Examples</a></li>
@@ -16,7 +17,7 @@ It removes native list chrome but does not force a direction. Combine it with la
16
17
  </nav>
17
18
  <h2>Documentation</h2>
18
19
  <nav aria-label="Documentation">
19
- <ul class="nav-list stack">
20
+ <ul class="nav-list">
20
21
  <li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
21
22
  <li><a href="/docs/tokens">Tokens</a></li>
22
23
  <li><a href="/docs/layout">Layout</a></li>
@@ -26,14 +27,6 @@ It removes native list chrome but does not force a direction. Combine it with la
26
27
  </div>
27
28
  ```
28
29
 
29
- Use `.nav-list` for:
30
-
31
- - header navigation
32
- - side navigation
33
- - footer navigation
34
- - tab-like navigation lists
35
- - documentation navigation
36
-
37
30
  Do not reset every list inside `nav`.
38
31
 
39
32
  ```css
@@ -51,7 +44,7 @@ Prefer an explicit pattern class.
51
44
 
52
45
  ```html demo
53
46
  <nav aria-label="Footer">
54
- <ul class="nav-list cluster">
47
+ <ul class="cluster">
55
48
  <li><a href="/privacy">Privacy</a></li>
56
49
  <li><a href="/terms">Terms</a></li>
57
50
  <li><a href="/contact">Contact</a></li>
@@ -69,7 +62,7 @@ Header navigation is usually a composition of landmarks, layout primitives, and
69
62
  <a class="brand" href="/">Actual CSS</a>
70
63
 
71
64
  <nav aria-label="Main navigation">
72
- <ul class="nav-list cluster">
65
+ <ul class="cluster">
73
66
  <li><a href="/docs">Docs</a></li>
74
67
  <li><a href="/components">Components</a></li>
75
68
  <li><a href="/examples">Examples</a></li>
@@ -85,8 +78,7 @@ In this example:
85
78
  - `.center` constrains the content.
86
79
  - `.cluster` arranges the brand and navigation.
87
80
  - `nav` provides navigation semantics.
88
- - `.nav-list` normalizes the navigation list.
89
- - the inner `.cluster` arranges navigation items horizontally.
81
+ - the inner `.cluster` removes the list chrome and arranges the links horizontally.
90
82
 
91
83
  A project may add `.site-header` when it needs a visual shell.
92
84
 
@@ -106,7 +98,7 @@ A project may add `.site-header` when it needs a visual shell.
106
98
  <aside class="shell-sidebar-nav" aria-label="Primary">
107
99
  <a class="navbar-brand" href="#"><span class="avatar primary"><abbr>AC</abbr></span> Product</a>
108
100
  <nav aria-label="Primary">
109
- <ul class="nav-list stack">
101
+ <ul class="nav-list">
110
102
  <li><a class="nav-link" href="#" aria-current="page">Overview</a></li>
111
103
  <li><a class="nav-link" href="#">Settings</a></li>
112
104
  </ul>
@@ -167,7 +159,7 @@ Side navigation is usually a `.nav-list` composed with `.stack`.
167
159
  ```html demo
168
160
  <aside>
169
161
  <nav aria-label="Documentation">
170
- <ul class="nav-list stack">
162
+ <ul class="nav-list">
171
163
  <li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
172
164
  <li><a href="/docs/tokens">Tokens</a></li>
173
165
  <li><a href="/docs/layout">Layout</a></li>
@@ -182,7 +174,7 @@ A project may add `.side-nav` only when it needs specific visual behavior such a
182
174
  ```html demo
183
175
  <aside class="side-nav">
184
176
  <nav aria-label="Documentation">
185
- <ul class="nav-list stack">
177
+ <ul class="nav-list">
186
178
  <li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
187
179
  <li><a href="/docs/tokens">Tokens</a></li>
188
180
  <li><a href="/docs/layout">Layout</a></li>
@@ -206,30 +198,8 @@ A project may add `.side-nav` only when it needs specific visual behavior such a
206
198
  }
207
199
  ```
208
200
 
209
- ### Optional Navigation Link Styling
210
-
211
- `.nav-list` can stay purely structural. If the framework wants navigation links to have a default hit area and active state, this can be added as a lightweight visual pattern.
212
-
213
- ```css
214
- .nav-list a {
215
- display: flex;
216
- align-items: center;
217
- gap: var(--space-20);
218
- min-block-size: 2rem;
219
- padding-inline: var(--space-20);
220
- border-radius: var(--radius-sm);
221
- color: inherit;
222
- text-decoration: none;
223
- }
224
-
225
- .nav-list a:hover {
226
- background: var(--surface-subtle);
227
- }
228
-
229
- .nav-list a[aria-current="page"] {
230
- background: var(--surface-subtle);
231
- font-weight: 600;
232
- }
233
- ```
201
+ ### Link Styling
234
202
 
235
- Keep this separate from layout primitives. `.cluster` and `.stack` should not style links.
203
+ `.nav-link` gives a link its hit area, hover fill and `aria-current` state, in a
204
+ `.cluster` row or a `.nav-list` (see [Navbar](../components/navbar.md)). Set
205
+ `--gap` on a `.nav-list` to space its rows differently.
@@ -22,9 +22,8 @@ Use patterns when a semantic element needs a small amount of normalization befor
22
22
  Patterns often compose with layout primitives.
23
23
 
24
24
  ```html
25
- <menu class="actions cluster">...</menu>
26
- <ul class="nav-list cluster">...</ul>
27
- <ul class="nav-list stack">...</ul>
25
+ <menu class="cluster">...</menu>
26
+ <ul class="nav-list">...</ul>
28
27
  <section class="grid">...</section>
29
28
  ```
30
29
 
@@ -51,7 +50,7 @@ Avoid putting semantic resets into layout primitives.
51
50
  If list chrome should be removed, use an explicit pattern.
52
51
 
53
52
  ```html demo
54
- <ul class="nav-list stack">
53
+ <ul class="nav-list">
55
54
  <li><a href="/docs">Docs</a></li>
56
55
  <li><a href="/components">Components</a></li>
57
56
  </ul>
@@ -6,24 +6,25 @@ Small flex helpers for grow behavior and other one-line needs.
6
6
 
7
7
  Base utilities:
8
8
 
9
- | Class | Description |
10
- | --------------- | -------------------------------------------------------------- |
11
- | `.grow` | Makes an item take available flex space without overflowing. |
12
- | `.items-start` | Aligns children to the block-start edge; sets `--items-align`. |
13
- | `.items-center` | Centers children on the cross axis; sets `--items-align`. |
14
- | `.items-end` | Aligns children to the block-end edge; sets `--items-align`. |
15
- | `.dot` | Inline separator dot for metadata rows. |
9
+ | Class | Description |
10
+ | ----------------- | ------------------------------------------------------------------- |
11
+ | `.grow` | Makes an item take available flex space without overflowing. |
12
+ | `.items-start` | Aligns children to the block-start edge; sets `--items-align`. |
13
+ | `.items-center` | Centers children on the cross axis; sets `--items-align`. |
14
+ | `.items-end` | Aligns children to the block-end edge; sets `--items-align`. |
15
+ | `.items-baseline` | Aligns children on their first text baseline; sets `--items-align`. |
16
+ | `.dot` | Inline separator dot for metadata rows. |
16
17
 
17
18
  Extra utilities:
18
19
 
19
- | Class | Description |
20
- | -------------------------------- | --------------------------------------------------------- |
21
- | `.justify-content-start` | `justify-content: flex-start` and `--cluster-justify`. |
22
- | `.justify-content-center` | `justify-content: center` and `--cluster-justify`. |
23
- | `.justify-content-end` | `justify-content: flex-end` and `--cluster-justify`. |
24
- | `.justify-content-space-between` | `justify-content: space-between` and `--cluster-justify`. |
25
- | `.flex-wrap` | `flex-wrap: wrap` on any flex container. |
26
- | `.flex-nowrap` | `flex-wrap: nowrap` on any flex container. |
20
+ | Class | Description |
21
+ | -------------------------------- | ------------------------------------------------------- |
22
+ | `.justify-content-start` | `justify-content: flex-start` on the element itself. |
23
+ | `.justify-content-center` | `justify-content: center` on the element itself. |
24
+ | `.justify-content-end` | `justify-content: flex-end` on the element itself. |
25
+ | `.justify-content-space-between` | `justify-content: space-between` on the element itself. |
26
+ | `.flex-wrap` | `flex-wrap: wrap` on any flex container. |
27
+ | `.flex-nowrap` | `flex-wrap: nowrap` on any flex container. |
27
28
 
28
29
  ## Grow
29
30
 
@@ -66,14 +67,24 @@ Use `.items-start` on flex or grid layouts when children should keep their natur
66
67
 
67
68
  Use `.items-center` when a flex or grid layout should center its children on the cross axis. Use `.items-end` when children should align to the block-end edge.
68
69
 
70
+ Use `.items-baseline` when a row mixes text sizes — a price and its period, a name and a timestamp — so the words share one line instead of their boxes sharing a center.
71
+
72
+ ```html demo
73
+ <p class="cluster items-baseline">
74
+ <strong style="font-size: 2rem">$29</strong>
75
+ <span class="muted">/ month</span>
76
+ </p>
77
+ ```
78
+
69
79
  These helpers work by setting a custom property that participating components read,
70
80
  so they also apply inside a component's own grid anatomy rather than only on plain
71
81
  flex containers:
72
82
 
73
- - `.items-start` / `.items-center` / `.items-end` set `--items-align`, read by `.alert` and `.card`.
83
+ - `.items-start` / `.items-center` / `.items-end` / `.items-baseline` set `--items-align`, read by `.alert` and `.card`.
74
84
  - `.text-start` / `.text-center` / `.text-end` set `--text-align`, read by `.table` cells.
75
- - `.justify-content-*` (utilities/extra) set `--cluster-justify`, read by `.cluster`.
76
- - `.flex-wrap` / `.flex-nowrap` (utilities/extra) set `flex-wrap` directly on any flex container.
85
+
86
+ `.justify-content-*` and `.flex-wrap` / `.flex-nowrap` (utilities/extra) set the property
87
+ directly, so they never reach a nested `.cluster`.
77
88
 
78
89
  Set the property directly when you need a value the helpers do not ship.
79
90
 
@@ -107,6 +118,5 @@ Always mark it `aria-hidden="true"` — it is a visual separator, not content.
107
118
 
108
119
  ## CSS hooks
109
120
 
110
- - `--items-align` — cross-axis alignment, set by `.items-start` / `.items-center` / `.items-end`.
121
+ - `--items-align` — cross-axis alignment, set by the `.items-*` helpers.
111
122
  - `--text-align` — text alignment, set by `.text-start` / `.text-center` / `.text-end`.
112
- - `--cluster-justify` — main-axis distribution, set by the optional `.justify-content-*` helpers and read by `.cluster`.
@@ -29,7 +29,7 @@ one line (`.badge`). To stop a layout primitive from wrapping — for example to
29
29
  force a `.cluster` onto a single row — set `--cluster-wrap: nowrap`.
30
30
 
31
31
  ```html demo
32
- <div class="cluster compact" style="--cluster-wrap: nowrap;">
32
+ <div class="cluster tight" style="--cluster-wrap: nowrap;">
33
33
  <select class="select sm fit" aria-label="Segment">
34
34
  <option>All segments</option>
35
35
  </select>
@@ -48,9 +48,10 @@ Override the default gap from layout primitives (`.stack`, `.cluster`, `.grid`):
48
48
  - `.gap-none` → `gap: 0`
49
49
 
50
50
  `.gap-none` sets the element's own gap directly and does not change `--gap`
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.
51
+ for nested layouts. For a tighter or looser rhythm alone — closer items, without
52
+ smaller controls — use `.tight` / `.loose`; `.compact` / `.spacious` also change
53
+ padding and control size. Set the `gap` property on the instance when the change
54
+ must stop there.
54
55
 
55
56
  `--gap` defines the contextual rhythm; `.gap-context` applies that rhythm to a
56
57
  container that does not already consume `--gap`. The layout primitives
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "actual-css",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Plain CSS component framework with semantic classes, universal variants, small tokens, theme hooks, and progressive enhancements.",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.4.2",
@@ -10,7 +10,7 @@
10
10
  "type": "git",
11
11
  "url": "https://github.com/lekoala/actual-css.git"
12
12
  },
13
- "homepage": "https://github.com/lekoala/actual-css",
13
+ "homepage": "https://lekoala.github.io/actual-css/",
14
14
  "bugs": {
15
15
  "url": "https://github.com/lekoala/actual-css/issues"
16
16
  },
@@ -131,6 +131,7 @@
131
131
  "build:js": "bun scripts/build-js.js",
132
132
  "build:themes": "bun scripts/build-themes.js",
133
133
  "build:size": "bun scripts/build-size.js",
134
+ "export:design": "bun scripts/export-design.js",
134
135
  "check:enhance": "bun run scripts/check-enhance.js",
135
136
  "generate:reserved": "bun scripts/generate-reserved-classes.js",
136
137
  "check:reserved": "bun scripts/check-reserved.js",
@@ -1,6 +1,5 @@
1
1
  [
2
2
  "accordion",
3
- "actions",
4
3
  "admonition",
5
4
  "alert",
6
5
  "alert-body",
@@ -56,7 +55,6 @@
56
55
  "cursor-pointer",
57
56
  "danger",
58
57
  "data-list",
59
- "dialog-confirmation",
60
58
  "dialog-icon",
61
59
  "display-block",
62
60
  "display-flex",
@@ -110,6 +108,7 @@
110
108
  "intent-color",
111
109
  "is-open",
112
110
  "is-static",
111
+ "items-baseline",
113
112
  "items-center",
114
113
  "items-end",
115
114
  "items-start",
@@ -132,6 +131,7 @@
132
131
  "list-item-title",
133
132
  "list-item-trailing",
134
133
  "list-reset",
134
+ "loose",
135
135
  "margin-block-end-auto",
136
136
  "margin-block-start-auto",
137
137
  "margin-inline-auto",
@@ -159,7 +159,6 @@
159
159
  "nav-list",
160
160
  "navbar",
161
161
  "navbar-brand",
162
- "navbar-nav",
163
162
  "needs-validation",
164
163
  "neutral",
165
164
  "otp",
@@ -248,6 +247,7 @@
248
247
  "text-uppercase",
249
248
  "text-wrap",
250
249
  "textarea",
250
+ "tight",
251
251
  "tooltip",
252
252
  "topbar",
253
253
  "touch-target",