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.
- package/CHANGELOG.md +73 -0
- package/README.md +29 -5
- package/components.json +15 -17
- package/dist/actual.full.css +403 -227
- package/dist/actual.full.min.css +1 -1
- package/docs/brand/favicon.svg +5 -0
- package/docs/brand/lockup.svg +12 -0
- package/docs/brand/logo-dark.svg +9 -0
- package/docs/brand/logo-light.svg +9 -0
- package/docs/brand/logo.svg +11 -0
- package/docs/brand/mark.svg +11 -0
- package/docs/navigation.json +4 -2
- package/docs/pages/components/alert.md +2 -10
- package/docs/pages/components/badge.md +3 -9
- package/docs/pages/components/bleed.md +5 -4
- package/docs/pages/components/card.md +31 -2
- package/docs/pages/components/close.md +9 -3
- package/docs/pages/components/dialog.md +248 -31
- package/docs/pages/components/drawer.md +2 -2
- package/docs/pages/components/meter.md +2 -0
- package/docs/pages/components/navbar.md +8 -9
- package/docs/pages/components/table.md +3 -3
- package/docs/pages/enhancements/flyout.md +2 -2
- package/docs/pages/enhancements/scrollspy.md +1 -1
- package/docs/pages/enhancements/status-bar.md +2 -2
- package/docs/pages/examples/overview.md +3 -1
- package/docs/pages/forms/date-picker.md +90 -0
- package/docs/pages/forms/detached-actions.md +37 -30
- package/docs/pages/forms/form-actions.md +61 -28
- package/docs/pages/forms/input-policy.md +1 -1
- package/docs/pages/forms/overview.md +6 -5
- package/docs/pages/forms/sticky-actions.md +85 -83
- package/docs/pages/forms/validation.md +5 -5
- package/docs/pages/foundations/philosophy.md +5 -3
- package/docs/pages/foundations/theming.md +15 -4
- package/docs/pages/foundations/tokens.md +50 -33
- package/docs/pages/foundations/typography.md +4 -7
- package/docs/pages/guides/bootstrap.md +2 -2
- package/docs/pages/guides/design-tools.md +36 -0
- package/docs/pages/guides/integrating-actual-css.md +5 -1
- package/docs/pages/guides/introduction.md +3 -4
- package/docs/pages/guides/modular-import.md +3 -0
- package/docs/pages/guides/progressive-enhancement.md +2 -2
- package/docs/pages/guides/tailwind.md +70 -0
- package/docs/pages/guides/upgrading.md +74 -0
- package/docs/pages/layout/cluster.md +28 -2
- package/docs/pages/layout/overview.md +1 -1
- package/docs/pages/layout/stack.md +21 -16
- package/docs/pages/layout/topbar.md +1 -1
- package/docs/pages/patterns/navigation-list.md +16 -46
- package/docs/pages/patterns/overview.md +3 -4
- package/docs/pages/utilities/flex.md +30 -20
- package/docs/pages/utilities/sizing-wrapping.md +1 -1
- package/docs/pages/utilities/spacing.md +4 -3
- package/package.json +3 -2
- package/reserved-classes.json +3 -3
- package/skills/actual-css/references/enhancements.md +38 -0
- package/src/cli/actual-css.js +75 -6
- package/src/css/components/avatar.css +16 -9
- package/src/css/components/badge.css +1 -5
- package/src/css/components/bleed.css +5 -5
- package/src/css/components/button.css +17 -10
- package/src/css/components/card.css +18 -10
- package/src/css/components/chat.css +4 -5
- package/src/css/components/close.css +17 -6
- package/src/css/components/drawer.css +19 -3
- package/src/css/components/flyout.css +3 -0
- package/src/css/components/index.css +0 -1
- package/src/css/components/meter.css +5 -2
- package/src/css/components/modal.css +157 -69
- package/src/css/components/navbar.css +14 -25
- package/src/css/core/base.css +1 -1
- package/src/css/core/reset.css +2 -1
- package/src/css/core/theme.css +4 -0
- package/src/css/core/tokens.css +28 -10
- package/src/css/core/variants.css +41 -14
- package/src/css/forms/form-actions.css +15 -10
- package/src/css/forms/native.css +5 -1
- package/src/css/layout/cluster.css +11 -0
- package/src/css/layout/topbar.css +12 -6
- package/src/css/utilities/base.css +5 -0
- package/src/css/utilities/extra.css +3 -7
- package/src/tooling/color.js +65 -0
- package/src/tooling/design-components.js +286 -0
- package/src/tooling/design-export.js +69 -0
- package/src/tooling/design-tokens.js +474 -0
- package/src/tooling/penpot-plugin/manifest.json +7 -0
- package/src/tooling/penpot-plugin/plugin.js +272 -0
- package/src/tooling/penpot-plugin/ui.html +58 -0
- package/src/tooling/theme-contrast.js +209 -0
- package/docs/pages/patterns/actions.md +0 -52
- 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
|
|
52
|
-
|
|
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
|
|
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
|
|
42
|
+
## Choosing a rhythm
|
|
43
43
|
|
|
44
|
-
`--gap` is the primitive's channel
|
|
45
|
-
the
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
52
|
+
| `.stack tight` | 8px | A homogeneous series of controls |
|
|
53
53
|
| `.stack` | 12px | Normal flow between distinct elements |
|
|
54
|
-
| `.stack
|
|
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
|
-
`
|
|
68
|
+
`tight` — tighter than the default, but still spaced.
|
|
64
69
|
|
|
65
|
-
`.
|
|
66
|
-
Because the token is inherited,
|
|
67
|
-
of any nested stack, cluster, and grid. For a one-off gap
|
|
68
|
-
|
|
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
|
|
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
|
-
|
|
104
|
-
precisely so
|
|
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
|
|
4
|
-
|
|
5
|
-
|
|
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="
|
|
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
|
|
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="
|
|
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="
|
|
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
|
-
- `.
|
|
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
|
|
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
|
|
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
|
|
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
|
-
###
|
|
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
|
-
|
|
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="
|
|
26
|
-
<ul class="nav-list
|
|
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
|
|
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
|
|
10
|
-
|
|
|
11
|
-
| `.grow`
|
|
12
|
-
| `.items-start`
|
|
13
|
-
| `.items-center`
|
|
14
|
-
| `.items-end`
|
|
15
|
-
| `.
|
|
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`
|
|
22
|
-
| `.justify-content-center` | `justify-content: center`
|
|
23
|
-
| `.justify-content-end` | `justify-content: flex-end`
|
|
24
|
-
| `.justify-content-space-between` | `justify-content: space-between`
|
|
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
|
-
|
|
76
|
-
- `.flex-wrap` / `.flex-nowrap` (utilities/extra) set
|
|
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
|
|
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
|
|
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
|
|
52
|
-
|
|
53
|
-
|
|
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.
|
|
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.
|
|
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",
|
package/reserved-classes.json
CHANGED
|
@@ -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",
|