actual-css 0.2.0 → 0.3.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 +38 -1
- package/README.md +24 -9
- package/dist/actual-themes.min.css +1 -0
- package/dist/actual.css +1244 -915
- package/dist/actual.js +1 -3
- package/dist/actual.min.css +1 -1
- package/dist/optional.css +1048 -0
- package/dist/optional.min.css +1 -0
- package/docs/design-notes/browser-support.md +94 -14
- package/docs/design-notes/cascade-layer.md +1 -1
- package/docs/design-notes/enhancement-contract.md +11 -14
- package/docs/design-notes/forced-colors.md +105 -0
- package/docs/design-notes/naming.md +2 -1
- package/docs/design-notes/platform-alignment.md +492 -0
- package/docs/design-notes/references.md +8 -0
- package/docs/design-notes/widget-primitives.md +37 -1
- package/docs/navigation.json +135 -0
- package/docs/pages/components/accordion.md +80 -0
- package/docs/pages/components/alert.md +203 -0
- package/docs/pages/components/aura.md +35 -0
- package/docs/pages/components/avatar.md +95 -0
- package/docs/pages/components/badge.md +102 -0
- package/docs/pages/components/breadcrumb.md +19 -0
- package/docs/pages/components/button.md +205 -0
- package/docs/pages/components/card.md +183 -0
- package/docs/pages/components/chat.md +50 -0
- package/docs/pages/components/dialog.md +367 -0
- package/docs/pages/components/drawer.md +113 -0
- package/docs/pages/components/fab.md +118 -0
- package/docs/pages/components/key.md +33 -0
- package/docs/pages/components/meter.md +23 -0
- package/docs/pages/components/navbar.md +92 -0
- package/docs/pages/components/pagination.md +55 -0
- package/docs/pages/components/progress.md +29 -0
- package/docs/pages/components/skeleton.md +38 -0
- package/docs/pages/components/spinner.md +93 -0
- package/docs/pages/components/table.md +102 -0
- package/docs/pages/enhancements/flyout.md +391 -0
- package/docs/pages/enhancements/overview.md +36 -0
- package/docs/pages/enhancements/scrollspy.md +71 -0
- package/docs/pages/enhancements/status-bar.md +72 -0
- package/docs/pages/enhancements/tabs.md +80 -0
- package/docs/pages/enhancements/tooltip.md +130 -0
- package/docs/pages/examples/overview.md +41 -0
- package/docs/pages/forms/choice-cards.md +102 -0
- package/docs/pages/forms/controls.md +32 -0
- package/docs/pages/forms/detached-actions.md +59 -0
- package/docs/pages/forms/floating-field.md +88 -0
- package/docs/pages/forms/form-actions.md +56 -0
- package/docs/pages/forms/input-policy.md +91 -0
- package/docs/pages/forms/joined-controls.md +37 -0
- package/docs/pages/forms/labels.md +42 -0
- package/docs/pages/forms/otp.md +50 -0
- package/docs/pages/forms/overview.md +188 -0
- package/docs/pages/forms/password.md +40 -0
- package/docs/pages/forms/range.md +17 -0
- package/docs/pages/forms/states-and-sizes.md +321 -0
- package/docs/pages/forms/sticky-actions.md +187 -0
- package/docs/pages/forms/switch.md +31 -0
- package/docs/pages/forms/validation.md +241 -0
- package/docs/{mental-model.md → pages/foundations/philosophy.md} +33 -18
- package/docs/pages/foundations/theming.md +92 -0
- package/docs/pages/foundations/tokens.md +421 -0
- package/docs/{typography.md → pages/foundations/typography.md} +27 -9
- package/docs/pages/guides/bootstrap.md +438 -0
- package/docs/pages/guides/introduction.md +157 -0
- package/docs/pages/guides/optional-components.md +33 -0
- package/docs/pages/guides/progressive-enhancement.md +686 -0
- package/docs/pages/guides/tailwind.md +455 -0
- package/docs/pages/layout/app-shell.md +25 -0
- package/docs/pages/layout/center.md +29 -0
- package/docs/pages/layout/cluster.md +57 -0
- package/docs/pages/layout/frame.md +30 -0
- package/docs/pages/layout/grid.md +142 -0
- package/docs/pages/layout/list.md +41 -0
- package/docs/pages/layout/media.md +21 -0
- package/docs/pages/layout/overview.md +37 -0
- package/docs/pages/layout/scroll-snap.md +54 -0
- package/docs/pages/layout/sidebar-layout.md +27 -0
- package/docs/pages/layout/stack.md +18 -0
- package/docs/pages/layout/switcher.md +36 -0
- package/docs/pages/layout/topbar.md +23 -0
- package/docs/pages/patterns/actions.md +52 -0
- package/docs/pages/patterns/code-block.md +36 -0
- package/docs/pages/patterns/exclusive-accordion.md +16 -0
- package/docs/pages/patterns/hierarchical-nav.md +26 -0
- package/docs/pages/patterns/icon-input.md +25 -0
- package/docs/pages/patterns/intent-nesting.md +3 -0
- package/docs/pages/patterns/navigation-list.md +235 -0
- package/docs/pages/patterns/overview.md +58 -0
- package/docs/pages/patterns/structured-lists.md +47 -0
- package/docs/pages/utilities/accessibility.md +34 -0
- package/docs/pages/utilities/flex.md +105 -0
- package/docs/pages/utilities/links.md +18 -0
- package/docs/pages/utilities/list.md +31 -0
- package/docs/pages/utilities/overflow.md +43 -0
- package/docs/pages/utilities/overview.md +18 -0
- package/docs/pages/utilities/shape.md +25 -0
- package/docs/pages/utilities/sizing-wrapping.md +115 -0
- package/docs/pages/utilities/spacing.md +79 -0
- package/docs/pages/utilities/text.md +43 -0
- package/llms.txt +4 -4
- package/package.json +20 -12
- package/src/css/actual.css +12 -1
- package/src/css/base.css +3 -5
- package/src/css/components/accordion.css +18 -30
- package/src/css/components/actions.css +4 -1
- package/src/css/components/alert.css +126 -99
- package/src/css/components/avatar.css +16 -10
- package/src/css/components/badge.css +55 -35
- package/src/css/components/breadcrumb.css +7 -15
- package/src/css/components/busy.css +6 -0
- package/src/css/components/button.css +78 -32
- package/src/css/components/card.css +17 -37
- package/src/css/components/drawer.css +30 -13
- package/src/css/components/flyout.css +39 -109
- package/src/css/components/index.css +1 -0
- package/src/css/components/join.css +14 -2
- package/src/css/components/key.css +2 -0
- package/src/css/components/menu.css +125 -0
- package/src/css/components/meter.css +0 -23
- package/src/css/components/modal.css +162 -7
- package/src/css/components/navbar.css +17 -18
- package/src/css/components/overline.css +0 -7
- package/src/css/components/pagination.css +1 -1
- package/src/css/components/progress.css +8 -26
- package/src/css/components/skeleton.css +7 -0
- package/src/css/components/spinner.css +6 -7
- package/src/css/components/status-bar.css +15 -24
- package/src/css/components/surface.css +2 -8
- package/src/css/components/tab.css +19 -48
- package/src/css/components/table.css +7 -5
- package/src/css/components/tooltip.css +14 -7
- package/src/css/focus.css +14 -38
- package/src/css/forms/choice-card.css +13 -14
- package/src/css/forms/choice.css +21 -27
- package/src/css/forms/control.css +16 -17
- package/src/css/forms/custom-select.css +9 -11
- package/src/css/forms/form-actions.css +14 -3
- package/src/css/forms/form.css +7 -4
- package/src/css/forms/index.css +4 -4
- package/src/css/forms/input-icon.css +30 -12
- package/src/css/forms/native.css +50 -11
- package/src/css/forms/range.css +17 -9
- package/src/css/forms/select.css +8 -8
- package/src/css/forms/switch.css +14 -12
- package/src/css/forms/validation.css +32 -5
- package/src/css/grid.css +19 -18
- package/src/css/intents.css +2 -2
- package/src/css/layout.css +29 -1
- package/src/css/optional/aura.css +93 -0
- package/src/css/optional/chat.css +105 -0
- package/src/css/optional/fab.css +104 -0
- package/src/css/optional/floating-field.css +87 -0
- package/src/css/optional/index.css +5 -0
- package/src/css/optional/layout-extra.css +7 -4
- package/src/css/optional/otp.css +115 -0
- package/src/css/optional/scroll-snap.css +6 -0
- package/src/css/optional/scroller.css +13 -7
- package/src/css/optional/typography-fluid.css +5 -0
- package/src/css/optional/utilities-extra.css +17 -2
- package/src/css/prose.css +18 -8
- package/src/css/reset.css +0 -10
- package/src/css/theme.css +21 -5
- package/src/css/themes/cyberpunk.css +1 -1
- package/src/css/themes/dim.css +3 -3
- package/src/css/themes/edge.css +8 -10
- package/src/css/themes/index.css +3 -3
- package/src/css/themes/{dark.css → indigo.css} +5 -4
- package/src/css/themes/neon.css +5 -5
- package/src/css/themes/square.css +0 -3
- package/src/css/tokens.css +74 -20
- package/src/css/utilities.css +8 -10
- package/src/css/variants.css +37 -65
- package/src/js/command.js +1 -3
- package/src/js/context-menu.js +67 -35
- package/src/js/dialog.js +68 -79
- package/src/js/dismiss.js +15 -0
- package/src/js/enhance.js +54 -23
- package/src/js/enhancement-loader.js +301 -0
- package/src/js/events.js +3 -0
- package/src/js/filter.js +3 -3
- package/src/js/floating.js +101 -131
- package/src/js/flyout.js +104 -87
- package/src/js/focus-group.js +116 -0
- package/src/js/focus.js +6 -1
- package/src/js/index.js +4 -2
- package/src/js/input.js +1 -1
- package/src/js/keys.js +27 -0
- package/src/js/mask.js +7 -6
- package/src/js/menu.js +87 -34
- package/src/js/parse-config.js +47 -0
- package/src/js/password.js +9 -1
- package/src/js/scrollspy.js +12 -4
- package/src/js/selectors.js +0 -7
- package/src/js/status.js +3 -1
- package/src/js/surface.js +185 -136
- package/src/js/tab.js +36 -53
- package/src/js/tooltip.js +53 -31
- package/src/js/validation.js +34 -8
- package/dist/actual.js.map +0 -31
- package/docs/README.md +0 -28
- package/docs/components.md +0 -860
- package/docs/design-notes/previous-work.md +0 -5
- package/docs/forms.md +0 -1265
- package/docs/javascript.md +0 -496
- package/docs/layout.md +0 -480
- package/docs/patterns.md +0 -504
- package/docs/reserved.md +0 -7
- package/docs/tokens.md +0 -455
- package/docs/ui.md +0 -929
- package/docs/utilities.md +0 -384
- package/src/css/dialog-fallback.css +0 -56
- package/src/js/dialog-fallback.js +0 -163
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Navigation List
|
|
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.
|
|
6
|
+
|
|
7
|
+
```html demo
|
|
8
|
+
<div class="stack">
|
|
9
|
+
<h2>Navigation</h2>
|
|
10
|
+
<nav aria-label="Main navigation">
|
|
11
|
+
<ul class="nav-list cluster">
|
|
12
|
+
<li><a href="/docs">Docs</a></li>
|
|
13
|
+
<li><a href="/components">Components</a></li>
|
|
14
|
+
<li><a href="/examples">Examples</a></li>
|
|
15
|
+
</ul>
|
|
16
|
+
</nav>
|
|
17
|
+
<h2>Documentation</h2>
|
|
18
|
+
<nav aria-label="Documentation">
|
|
19
|
+
<ul class="nav-list stack">
|
|
20
|
+
<li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
|
|
21
|
+
<li><a href="/docs/tokens">Tokens</a></li>
|
|
22
|
+
<li><a href="/docs/layout">Layout</a></li>
|
|
23
|
+
<li><a href="/docs/components">Components</a></li>
|
|
24
|
+
</ul>
|
|
25
|
+
</nav>
|
|
26
|
+
</div>
|
|
27
|
+
```
|
|
28
|
+
|
|
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
|
+
Do not reset every list inside `nav`.
|
|
38
|
+
|
|
39
|
+
```css
|
|
40
|
+
/* Avoid */
|
|
41
|
+
nav ul {
|
|
42
|
+
margin: 0;
|
|
43
|
+
padding: 0;
|
|
44
|
+
list-style: none;
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This is too broad and removes native list behavior from every navigation context, including nested documentation trees or rich content.
|
|
49
|
+
|
|
50
|
+
Prefer an explicit pattern class.
|
|
51
|
+
|
|
52
|
+
```html demo
|
|
53
|
+
<nav aria-label="Footer">
|
|
54
|
+
<ul class="nav-list cluster">
|
|
55
|
+
<li><a href="/privacy">Privacy</a></li>
|
|
56
|
+
<li><a href="/terms">Terms</a></li>
|
|
57
|
+
<li><a href="/contact">Contact</a></li>
|
|
58
|
+
</ul>
|
|
59
|
+
</nav>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Header Navigation
|
|
63
|
+
|
|
64
|
+
Header navigation is usually a composition of landmarks, layout primitives, and patterns.
|
|
65
|
+
|
|
66
|
+
```html demo
|
|
67
|
+
<header class="site-header">
|
|
68
|
+
<div class="center cluster" style="--cluster-justify: space-between">
|
|
69
|
+
<a class="brand" href="/">Actual CSS</a>
|
|
70
|
+
|
|
71
|
+
<nav aria-label="Main navigation">
|
|
72
|
+
<ul class="nav-list cluster">
|
|
73
|
+
<li><a href="/docs">Docs</a></li>
|
|
74
|
+
<li><a href="/components">Components</a></li>
|
|
75
|
+
<li><a href="/examples">Examples</a></li>
|
|
76
|
+
</ul>
|
|
77
|
+
</nav>
|
|
78
|
+
</div>
|
|
79
|
+
</header>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
In this example:
|
|
83
|
+
|
|
84
|
+
- `header` provides the document landmark.
|
|
85
|
+
- `.center` constrains the content.
|
|
86
|
+
- `.cluster` arranges the brand and navigation.
|
|
87
|
+
- `nav` provides navigation semantics.
|
|
88
|
+
- `.nav-list` normalizes the navigation list.
|
|
89
|
+
- the inner `.cluster` arranges navigation items horizontally.
|
|
90
|
+
|
|
91
|
+
A project may add `.site-header` when it needs a visual shell.
|
|
92
|
+
|
|
93
|
+
```css
|
|
94
|
+
.site-header {
|
|
95
|
+
border-block-end: 1px solid var(--border);
|
|
96
|
+
background: var(--surface);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### App Shell With Sidebar
|
|
101
|
+
|
|
102
|
+
`.app-shell` (see Layout App Shell) covers the simple case: a single column stacked `header`/`main`/`footer`. A persistent-sidebar app — a dashboard, an admin panel — needs a second, distinct shape: a two-column grid where the sidebar collapses below a breakpoint. These are not the same primitive solving the same problem two ways; `.app-shell` has no sidebar at all.
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<div class="shell-sidebar">
|
|
106
|
+
<aside class="shell-sidebar-nav" aria-label="Primary">
|
|
107
|
+
<a class="navbar-brand" href="#"><span class="avatar primary"><abbr>AC</abbr></span> Product</a>
|
|
108
|
+
<nav aria-label="Primary">
|
|
109
|
+
<ul class="nav-list stack">
|
|
110
|
+
<li><a class="nav-link" href="#" aria-current="page">Overview</a></li>
|
|
111
|
+
<li><a class="nav-link" href="#">Settings</a></li>
|
|
112
|
+
</ul>
|
|
113
|
+
</nav>
|
|
114
|
+
</aside>
|
|
115
|
+
|
|
116
|
+
<div class="shell-sidebar-main">
|
|
117
|
+
<header class="topbar">...</header>
|
|
118
|
+
<main class="center">...</main>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```css
|
|
124
|
+
.shell-sidebar {
|
|
125
|
+
display: grid;
|
|
126
|
+
grid-template-columns: 1fr;
|
|
127
|
+
min-block-size: var(--viewport-block);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.shell-sidebar-nav {
|
|
131
|
+
display: none;
|
|
132
|
+
flex-direction: column;
|
|
133
|
+
gap: var(--gap);
|
|
134
|
+
inline-size: var(--shell-sidebar-size, 16rem);
|
|
135
|
+
padding: var(--space-40);
|
|
136
|
+
border-inline-end: var(--border-width) solid var(--border);
|
|
137
|
+
background: var(--surface-raised);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.shell-sidebar-main {
|
|
141
|
+
min-inline-size: 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@media (min-width: 64rem) {
|
|
145
|
+
.shell-sidebar {
|
|
146
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.shell-sidebar-nav {
|
|
150
|
+
display: flex;
|
|
151
|
+
position: sticky;
|
|
152
|
+
inset-block-start: 0;
|
|
153
|
+
block-size: var(--viewport-block);
|
|
154
|
+
overflow-y: auto;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The sidebar width is the one tunable a project reaches for often, so it is exposed as `--shell-sidebar-size` rather than hard-coded — override it locally (`style="--shell-sidebar-size: 18rem"` or in a project stylesheet) instead of forking the rule. The breakpoint stays a literal `64rem` in the media query: custom properties cannot be substituted into a media condition, so a project that genuinely needs a different one copies the rule rather than fighting the token.
|
|
160
|
+
|
|
161
|
+
Below the breakpoint, mirror the sidebar into a `.drawer` (see Components Drawer) for mobile access — the two are separate elements, not a responsive transform of one.
|
|
162
|
+
|
|
163
|
+
### Side Navigation
|
|
164
|
+
|
|
165
|
+
Side navigation is usually a `.nav-list` composed with `.stack`.
|
|
166
|
+
|
|
167
|
+
```html demo
|
|
168
|
+
<aside>
|
|
169
|
+
<nav aria-label="Documentation">
|
|
170
|
+
<ul class="nav-list stack">
|
|
171
|
+
<li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
|
|
172
|
+
<li><a href="/docs/tokens">Tokens</a></li>
|
|
173
|
+
<li><a href="/docs/layout">Layout</a></li>
|
|
174
|
+
<li><a href="/docs/components">Components</a></li>
|
|
175
|
+
</ul>
|
|
176
|
+
</nav>
|
|
177
|
+
</aside>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
A project may add `.side-nav` only when it needs specific visual behavior such as indentation, sticky positioning, section labels, or active states.
|
|
181
|
+
|
|
182
|
+
```html demo
|
|
183
|
+
<aside class="side-nav">
|
|
184
|
+
<nav aria-label="Documentation">
|
|
185
|
+
<ul class="nav-list stack">
|
|
186
|
+
<li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
|
|
187
|
+
<li><a href="/docs/tokens">Tokens</a></li>
|
|
188
|
+
<li><a href="/docs/layout">Layout</a></li>
|
|
189
|
+
</ul>
|
|
190
|
+
</nav>
|
|
191
|
+
</aside>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
```css
|
|
195
|
+
.side-nav {
|
|
196
|
+
font-size: var(--font-size-sm);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.side-nav a {
|
|
200
|
+
color: inherit;
|
|
201
|
+
text-decoration: none;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.side-nav a[aria-current="page"] {
|
|
205
|
+
font-weight: 600;
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
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
|
+
```
|
|
234
|
+
|
|
235
|
+
Keep this separate from layout primitives. `.cluster` and `.stack` should not style links.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Patterns
|
|
2
|
+
|
|
3
|
+
> Small structural helpers for recurring semantic HTML shapes, between layout primitives and full components.
|
|
4
|
+
|
|
5
|
+
Patterns are small structural helpers for recurring semantic HTML shapes. They sit between layout primitives and full components.
|
|
6
|
+
|
|
7
|
+
They do not define page layout like `.stack`, `.cluster`, or `.grid`, and they do not provide a strong visual identity like `.alert`, `.card`, or `.btn`.
|
|
8
|
+
|
|
9
|
+
Use patterns when a semantic element needs a small amount of normalization before being composed with layout primitives or components.
|
|
10
|
+
|
|
11
|
+
## Principles
|
|
12
|
+
|
|
13
|
+
- Layout primitives control spatial behavior.
|
|
14
|
+
- Patterns normalize recurring semantic structures.
|
|
15
|
+
- Components provide visual identity, states, and interaction styling.
|
|
16
|
+
- Prefer composition over one-off component CSS.
|
|
17
|
+
- Avoid broad element selectors such as `nav ul` or `.alert menu`.
|
|
18
|
+
- A pattern should be useful in more than one component or context.
|
|
19
|
+
|
|
20
|
+
## Relationship With Layout
|
|
21
|
+
|
|
22
|
+
Patterns often compose with layout primitives.
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<menu class="actions cluster">...</menu>
|
|
26
|
+
<ul class="nav-list cluster">...</ul>
|
|
27
|
+
<ul class="nav-list stack">...</ul>
|
|
28
|
+
<section class="grid">...</section>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Avoid putting semantic resets into layout primitives.
|
|
32
|
+
|
|
33
|
+
```css
|
|
34
|
+
/* Avoid */
|
|
35
|
+
.stack {
|
|
36
|
+
padding: 0;
|
|
37
|
+
list-style: none;
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`.stack` should remain useful for real content lists where markers are expected.
|
|
42
|
+
|
|
43
|
+
```html demo
|
|
44
|
+
<ul class="stack">
|
|
45
|
+
<li>First important point</li>
|
|
46
|
+
<li>Second important point</li>
|
|
47
|
+
<li>Third important point</li>
|
|
48
|
+
</ul>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If list chrome should be removed, use an explicit pattern.
|
|
52
|
+
|
|
53
|
+
```html demo
|
|
54
|
+
<ul class="nav-list stack">
|
|
55
|
+
<li><a href="/docs">Docs</a></li>
|
|
56
|
+
<li><a href="/components">Components</a></li>
|
|
57
|
+
</ul>
|
|
58
|
+
```
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Structured Lists
|
|
2
|
+
|
|
3
|
+
Use native lists plus layout primitives for rich content rows. Reset list chrome only when markers are not part of the content.
|
|
4
|
+
|
|
5
|
+
```html demo
|
|
6
|
+
<figure class="stack">
|
|
7
|
+
<figcaption><strong>Most played songs this week</strong></figcaption>
|
|
8
|
+
|
|
9
|
+
<ul class="list-reset stack gap-none">
|
|
10
|
+
<li class="media items-center py" style="border-block-end: var(--border-width) solid var(--border)">
|
|
11
|
+
<div class="avatar">
|
|
12
|
+
<img src="https://i.pravatar.cc/48?img=5" alt="Dio Lupa" />
|
|
13
|
+
</div>
|
|
14
|
+
<div class="cluster">
|
|
15
|
+
<div class="stack grow" style="--gap: var(--space-10)">
|
|
16
|
+
<strong>Dio Lupa</strong>
|
|
17
|
+
<span class="muted">Remaining Reason</span>
|
|
18
|
+
</div>
|
|
19
|
+
<span class="muted">3:45</span>
|
|
20
|
+
<button class="btn ghost" type="button" aria-label="Play">
|
|
21
|
+
<i class="ti ti-player-play" aria-hidden="true"></i>
|
|
22
|
+
</button>
|
|
23
|
+
</div>
|
|
24
|
+
</li>
|
|
25
|
+
|
|
26
|
+
<li class="media items-center py" style="border-block-end: var(--border-width) solid var(--border)">
|
|
27
|
+
<div class="avatar">
|
|
28
|
+
<img src="https://i.pravatar.cc/48?img=10" alt="Astral Planes" />
|
|
29
|
+
</div>
|
|
30
|
+
<div class="cluster">
|
|
31
|
+
<div class="stack grow" style="--gap: var(--space-10)">
|
|
32
|
+
<strong>Astral Planes</strong>
|
|
33
|
+
<span class="muted">Neon Drift</span>
|
|
34
|
+
</div>
|
|
35
|
+
<span class="muted">4:12</span>
|
|
36
|
+
<button class="btn ghost" type="button" aria-label="Play">
|
|
37
|
+
<i class="ti ti-player-play" aria-hidden="true"></i>
|
|
38
|
+
</button>
|
|
39
|
+
</div>
|
|
40
|
+
</li>
|
|
41
|
+
</ul>
|
|
42
|
+
</figure>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Use `.actions` for action controls and `.nav-list` for navigation links. For structured content items, compose `.list-reset`, `.stack`, `.cluster`, `.media`, and components directly.
|
|
46
|
+
|
|
47
|
+
`.media` is a two-slot object: it lays out exactly two children — the leading element and one content column. Trailing metadata and actions belong inside the content column (nest a `.cluster` and put `.grow` on the flexible part), never as extra row children: additional children silently wrap onto a second grid row.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Accessibility
|
|
2
|
+
|
|
3
|
+
Text hidden visually but still available to assistive technology.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.sr-only` | Utility | Visually hides text while keeping it in the accessibility tree. |
|
|
10
|
+
|
|
11
|
+
## Screen reader only
|
|
12
|
+
|
|
13
|
+
Use `.sr-only` for text that should be available to assistive technology but visually hidden.
|
|
14
|
+
|
|
15
|
+
```html demo
|
|
16
|
+
<button class="btn ghost" type="button">
|
|
17
|
+
<i class="ti ti-menu-2" aria-hidden="true"></i>
|
|
18
|
+
<span class="sr-only">Open navigation</span>
|
|
19
|
+
</button>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
.sr-only {
|
|
24
|
+
position: absolute;
|
|
25
|
+
inline-size: 1px;
|
|
26
|
+
block-size: 1px;
|
|
27
|
+
padding: 0;
|
|
28
|
+
margin: -1px;
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
clip: rect(0, 0, 0, 0);
|
|
31
|
+
white-space: nowrap;
|
|
32
|
+
border: 0;
|
|
33
|
+
}
|
|
34
|
+
```
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Flex Helpers
|
|
2
|
+
|
|
3
|
+
Small flex helpers for grow behavior and other one-line needs.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.grow` | Utility | Makes an item take available flex space without overflowing. |
|
|
10
|
+
| `.items-start` | Utility | Aligns children to the block-start edge; sets `--items-align`. |
|
|
11
|
+
| `.items-center` | Utility | Centers children on the cross axis; sets `--items-align`. |
|
|
12
|
+
| `.items-end` | Utility | Aligns children to the block-end edge; sets `--items-align`. |
|
|
13
|
+
| `.dot` | Utility | Inline separator dot for metadata rows. |
|
|
14
|
+
| `.justify-content-start` | Utility | `justify-content: flex-start` and `--cluster-justify`. Optional layer. |
|
|
15
|
+
| `.justify-content-center` | Utility | `justify-content: center` and `--cluster-justify`. Optional layer. |
|
|
16
|
+
| `.justify-content-end` | Utility | `justify-content: flex-end` and `--cluster-justify`. Optional layer. |
|
|
17
|
+
| `.justify-content-space-between` | Utility | `justify-content: space-between` and `--cluster-justify`. Optional layer. |
|
|
18
|
+
| `.flex-wrap` | Utility | `flex-wrap: wrap` on any flex container. Optional layer. |
|
|
19
|
+
| `.flex-nowrap` | Utility | `flex-wrap: nowrap` on any flex container. Optional layer. |
|
|
20
|
+
|
|
21
|
+
## Grow
|
|
22
|
+
|
|
23
|
+
Use `.grow` when one item in a flex layout should take available space without overflowing.
|
|
24
|
+
|
|
25
|
+
```html demo
|
|
26
|
+
<header class="cluster">
|
|
27
|
+
<strong>Actual CSS</strong>
|
|
28
|
+
<nav class="grow" aria-label="Main navigation">
|
|
29
|
+
<a href="#">Docs</a>
|
|
30
|
+
<a href="#">Components</a>
|
|
31
|
+
</nav>
|
|
32
|
+
<button class="btn ghost" type="button">Menu</button>
|
|
33
|
+
</header>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```css
|
|
37
|
+
.grow {
|
|
38
|
+
flex: 1 1 auto;
|
|
39
|
+
min-inline-size: 0;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Item alignment
|
|
44
|
+
|
|
45
|
+
Use `.items-start` on flex or grid layouts when children should keep their natural height and align to the block-start edge. This is especially useful for form fields in a grid, where the default grid stretch would make short fields as tall as taller neighbors.
|
|
46
|
+
|
|
47
|
+
```html demo
|
|
48
|
+
<div class="grid items-start">
|
|
49
|
+
<label class="field">
|
|
50
|
+
<span class="field-label">Name</span>
|
|
51
|
+
<input class="input" type="text" />
|
|
52
|
+
</label>
|
|
53
|
+
<label class="field">
|
|
54
|
+
<span class="field-label">Notes</span>
|
|
55
|
+
<textarea class="textarea"></textarea>
|
|
56
|
+
</label>
|
|
57
|
+
</div>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
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.
|
|
61
|
+
|
|
62
|
+
These helpers work by setting a custom property that participating components read,
|
|
63
|
+
so they also apply inside a component's own grid anatomy rather than only on plain
|
|
64
|
+
flex containers:
|
|
65
|
+
|
|
66
|
+
- `.items-start` / `.items-center` / `.items-end` set `--items-align`, read by `.alert` and `.card`.
|
|
67
|
+
- `.text-start` / `.text-center` / `.text-end` set `--text-align`, read by `.table` cells.
|
|
68
|
+
- `.justify-content-*` (optional layer) set `--cluster-justify`, read by `.cluster`.
|
|
69
|
+
- `.flex-wrap` / `.flex-nowrap` (optional layer) set `flex-wrap` directly on any flex container.
|
|
70
|
+
|
|
71
|
+
Set the property directly when you need a value the helpers do not ship.
|
|
72
|
+
|
|
73
|
+
## Metadata separator
|
|
74
|
+
|
|
75
|
+
> A small inline dot for separating facts in a metadata row.
|
|
76
|
+
|
|
77
|
+
Use `.dot` between short facts in a byline, timestamp row, or breadcrumb-like list of details — anywhere a plain `·` character would otherwise be typed as text (which screen readers announce awkwardly).
|
|
78
|
+
|
|
79
|
+
```html demo
|
|
80
|
+
<p class="cluster" style="--cluster-justify: flex-start;">
|
|
81
|
+
<span>Ada Meridian</span>
|
|
82
|
+
<span class="dot" aria-hidden="true"></span>
|
|
83
|
+
<time datetime="2026-06-12">June 12, 2026</time>
|
|
84
|
+
<span class="dot" aria-hidden="true"></span>
|
|
85
|
+
<span>8 min read</span>
|
|
86
|
+
</p>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```css
|
|
90
|
+
.dot {
|
|
91
|
+
flex: none;
|
|
92
|
+
inline-size: 0.25rem;
|
|
93
|
+
block-size: 0.25rem;
|
|
94
|
+
border-radius: var(--radius-full);
|
|
95
|
+
background: var(--text-subtle);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Always mark it `aria-hidden="true"` — it is a visual separator, not content.
|
|
100
|
+
|
|
101
|
+
## CSS hooks
|
|
102
|
+
|
|
103
|
+
- `--items-align` — cross-axis alignment, set by `.items-start` / `.items-center` / `.items-end`.
|
|
104
|
+
- `--text-align` — text alignment, set by `.text-start` / `.text-center` / `.text-end`.
|
|
105
|
+
- `--cluster-justify` — main-axis distribution, set by the optional `.justify-content-*` helpers and read by `.cluster`.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Link Variants
|
|
2
|
+
|
|
3
|
+
Link styling for chrome that is conceptually a link but should not look like prose.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.link-plain` | Utility | Removes the underline and inherits the surrounding color. |
|
|
10
|
+
| `.link-muted` | Utility | Muted link that shifts to the full text color on hover. |
|
|
11
|
+
|
|
12
|
+
## Plain
|
|
13
|
+
|
|
14
|
+
`.link-plain` removes the link's underline and inherits the surrounding color. Use for chrome that is conceptually a link (a card title, a table row action, a tag, a breadcrumb segment) but should not look like prose.
|
|
15
|
+
|
|
16
|
+
## Muted
|
|
17
|
+
|
|
18
|
+
`.link-muted` is a `.link-plain` that starts in the muted text color and shifts to the full text color on hover. Use for navigation lists, table of contents, and other secondary navigation surfaces.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# List Helpers
|
|
2
|
+
|
|
3
|
+
Utilities for list chrome reset, readable measure, and editorial kicker labels.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.list-reset` | Utility | Removes native list margin, padding, and markers. |
|
|
10
|
+
| `.measure` | Utility | Caps a block at a readable width via `--prose-measure`. |
|
|
11
|
+
| `.overline` | Component | Small editorial kicker label: muted, uppercase, letterspaced. |
|
|
12
|
+
|
|
13
|
+
## List reset
|
|
14
|
+
|
|
15
|
+
`.list-reset` removes the native list chrome (margin, padding, markers) from any list. It is the generic version of `.nav-list` — use `.nav-list` when the list is a navigation list for semantic intent, and `.list-reset` for everything else (tag clouds, footer columns, related items, comment threads, embedded controls).
|
|
16
|
+
|
|
17
|
+
## Measure
|
|
18
|
+
|
|
19
|
+
`.measure` caps a block at a readable width using `--prose-measure`. It does not center — combine with `.center` for the common centered reading column, or with `margin-inline: auto` for a one-off centered block.
|
|
20
|
+
|
|
21
|
+
Use it for any content that needs a comfortable measure: prose articles, TOC lists, form fields, callouts. Avoid using it for full-bleed surfaces.
|
|
22
|
+
|
|
23
|
+
## Editorial labels
|
|
24
|
+
|
|
25
|
+
`.overline` is a small editorial label: muted color, smaller size, uppercase, slight letter-spacing. It does not impose a shape by itself. Add `.pill` for a bordered rounded chip, and combine with an intent class (`.primary`, `.success`, etc.) to tint the chip's text, border, and background.
|
|
26
|
+
|
|
27
|
+
The overline exists because categories, kicker labels, and section markers recur across editorial surfaces, and `.badge` is the wrong shape for them. `.badge` is a status indicator; `.overline` is metadata.
|
|
28
|
+
|
|
29
|
+
## CSS hooks
|
|
30
|
+
|
|
31
|
+
- `--prose-measure` — the readable measure `.measure` caps at; defaults to `70ch`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Overflow
|
|
2
|
+
|
|
3
|
+
Explicit overflow handling for content that may exceed its container.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.overflow-auto` | Utility | Enables scrolling when content exceeds the container. |
|
|
10
|
+
| `.overflow-hidden` | Utility | Clips overflowing content. Optional layer. |
|
|
11
|
+
| `.overflow-clip` | Utility | Clips overflowing content without a scroll container. Optional layer. |
|
|
12
|
+
| `.overflow-x-auto` | Utility | Horizontal scrolling only. Optional layer. |
|
|
13
|
+
| `.overflow-y-auto` | Utility | Vertical scrolling only. Optional layer. |
|
|
14
|
+
|
|
15
|
+
Use `.overflow-auto` when content may overflow its container, especially tables and code-like regions.
|
|
16
|
+
|
|
17
|
+
```html demo
|
|
18
|
+
<div class="overflow-auto">
|
|
19
|
+
<table class="table">
|
|
20
|
+
<caption>Team members</caption>
|
|
21
|
+
<thead>
|
|
22
|
+
<tr>
|
|
23
|
+
<th>Name</th>
|
|
24
|
+
<th>Role</th>
|
|
25
|
+
</tr>
|
|
26
|
+
</thead>
|
|
27
|
+
<tbody>
|
|
28
|
+
<tr>
|
|
29
|
+
<td>Alice Johnson</td>
|
|
30
|
+
<td>Admin</td>
|
|
31
|
+
</tr>
|
|
32
|
+
</tbody>
|
|
33
|
+
</table>
|
|
34
|
+
</div>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```css
|
|
38
|
+
.overflow-auto {
|
|
39
|
+
overflow: auto;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The optional layer extends the same concern with axis-specific and clipping variants. For quiet, custom scrollbar chrome instead of the native OS scrollbar, pair `.overflow-auto` with `.scroller` on the Sizing And Wrapping page.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Utilities
|
|
2
|
+
|
|
3
|
+
Utilities are a small escape hatch for common single-purpose needs. They should support composition, not become the primary way to build UI.
|
|
4
|
+
|
|
5
|
+
- Prefer semantic HTML, components, and layout primitives first.
|
|
6
|
+
- Add utilities only when the rule is broadly useful and unlikely to become a component.
|
|
7
|
+
- Keep utility names stable, boring, and few.
|
|
8
|
+
- Utilities should use logical properties where relevant.
|
|
9
|
+
|
|
10
|
+
## Non-Goals
|
|
11
|
+
|
|
12
|
+
> Utilities deliberately excluded to keep the surface small and intentional.
|
|
13
|
+
|
|
14
|
+
- No display scale such as `.block`, `.flex`, `.grid` — use layout primitives.
|
|
15
|
+
- No color scales such as `.text-primary` or `.bg-success` — intent colors belong to components and state.
|
|
16
|
+
- No breakpoint utility variants — use container queries or layout primitives.
|
|
17
|
+
- No utility variants for hover, focus, dark mode, or arbitrary selectors — use component states.
|
|
18
|
+
- No full spacing scale with every step and direction — the 17 spacing helpers across the core and optional layers cover the most common escape hatches.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Shape Helpers
|
|
2
|
+
|
|
3
|
+
Rare shape utilities for cases that must be perfectly round or square.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.circle` | Utility | Forces a perfectly round shape via `--radius-full`. |
|
|
10
|
+
|
|
11
|
+
Shape utilities should be rare because shape is mostly theme-level.
|
|
12
|
+
|
|
13
|
+
Use `.circle` only when an element must be perfectly round.
|
|
14
|
+
|
|
15
|
+
```html demo
|
|
16
|
+
<img class="circle" src="https://i.pravatar.cc/48?img=5" alt="Jane Doe" width="48" height="48" />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```css
|
|
20
|
+
.circle {
|
|
21
|
+
border-radius: var(--radius-full);
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Do not add `.rounded-sm`, `.rounded-lg`, `.square`, or `.pill` unless repeated real use proves they are needed.
|