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
package/docs/components.md
DELETED
|
@@ -1,860 +0,0 @@
|
|
|
1
|
-
# Components
|
|
2
|
-
|
|
3
|
-
Components are opt-in and use semantic HTML with a small, predictable class API. This page covers components whose core behavior is native HTML or CSS-only. Components that need a JavaScript enhancer or runtime orchestration live in [UI](ui.md).
|
|
4
|
-
|
|
5
|
-
- Use one component class for the thing being styled: `.btn`, `.card`, `.alert`, `.table`.
|
|
6
|
-
- Use shared intent modifiers when color carries meaning: `.primary`, `.secondary`, `.success`, `.warning`, `.danger`.
|
|
7
|
-
- Use shared visual variants when emphasis changes: `.solid`, `.soft`, `.outline`.
|
|
8
|
-
- Buttons add two button-only variants: `.ghost` and `.link`.
|
|
9
|
-
- Use shared size modifiers when the component supports sizing: `.sm`, `.lg`.
|
|
10
|
-
- Components can compose with each other and with layout utilities.
|
|
11
|
-
- Components own only their intrinsic layout. Page spacing belongs to layout utilities.
|
|
12
|
-
- ARIA roles and attributes are part of the API when they describe behavior or state.
|
|
13
|
-
|
|
14
|
-
Components are presented alphabetically.
|
|
15
|
-
|
|
16
|
-
## Accordion
|
|
17
|
-
|
|
18
|
-
> Collapsible regions built on native details and summary, with optional exclusive groups via the name attribute.
|
|
19
|
-
|
|
20
|
-
- Use native `<details>` and `<summary>` for collapsible content.
|
|
21
|
-
- Use the `name` attribute for exclusive accordions.
|
|
22
|
-
- Supports any valid body element (`div`, `p`, `ul`, ...).
|
|
23
|
-
- Toggle marker is globally customizable with CSS variables (placement and icon).
|
|
24
|
-
|
|
25
|
-
```html
|
|
26
|
-
<div class="accordion">
|
|
27
|
-
<details open>
|
|
28
|
-
<summary>A paragraph body that is opened</summary>
|
|
29
|
-
<p>This is a paragraph.</p>
|
|
30
|
-
</details>
|
|
31
|
-
|
|
32
|
-
<details>
|
|
33
|
-
<summary>With a list</summary>
|
|
34
|
-
<ul>
|
|
35
|
-
<li>First item</li>
|
|
36
|
-
<li>Second item</li>
|
|
37
|
-
</ul>
|
|
38
|
-
</details>
|
|
39
|
-
|
|
40
|
-
<details>
|
|
41
|
-
<summary>
|
|
42
|
-
<i class="ti ti-settings" aria-hidden="true"></i>
|
|
43
|
-
<span>With a custom icon</span>
|
|
44
|
-
</summary>
|
|
45
|
-
<div>
|
|
46
|
-
<p>Any valid flow content can be used here.</p>
|
|
47
|
-
</div>
|
|
48
|
-
</details>
|
|
49
|
-
</div>
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
```html
|
|
53
|
-
<div class="accordion">
|
|
54
|
-
<details name="settings">
|
|
55
|
-
<summary>This is grouped with the next one</summary>
|
|
56
|
-
<p>Using the <code>name</code> attribute groups items like radio buttons.</p>
|
|
57
|
-
</details>
|
|
58
|
-
|
|
59
|
-
<details name="settings">
|
|
60
|
-
<summary>This is grouped with the previous one</summary>
|
|
61
|
-
<p>Only one item in the same named group can be open.</p>
|
|
62
|
-
</details>
|
|
63
|
-
</div>
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
```html
|
|
67
|
-
<div class="accordion accordion-demo">
|
|
68
|
-
<details open>
|
|
69
|
-
<summary>
|
|
70
|
-
<span class="accordion-demo-icon" aria-hidden="true"></span>
|
|
71
|
-
<span>Custom marker at the start</span>
|
|
72
|
-
</summary>
|
|
73
|
-
<p>This demo swaps the default end marker for a local plus/minus icon.</p>
|
|
74
|
-
</details>
|
|
75
|
-
|
|
76
|
-
<details>
|
|
77
|
-
<summary>
|
|
78
|
-
<span class="accordion-demo-icon" aria-hidden="true"></span>
|
|
79
|
-
<span>Another item</span>
|
|
80
|
-
</summary>
|
|
81
|
-
<p>The icon belongs to the example, not the base accordion API.</p>
|
|
82
|
-
</details>
|
|
83
|
-
</div>
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## Alert
|
|
87
|
-
|
|
88
|
-
> Inline status messages for confirmations, warnings, and errors, with intents, icons, and action lists.
|
|
89
|
-
|
|
90
|
-
- Supports intent colors.
|
|
91
|
-
- Supports longer text and lists.
|
|
92
|
-
- Links inherit alert color by default.
|
|
93
|
-
- Alerts are soft by default. Use `.solid` or `.outline` when the message needs stronger or quieter emphasis.
|
|
94
|
-
- Use `<menu class="actions cluster">` for alert action lists.
|
|
95
|
-
- Use `role="alert"` only when the alert is injected dynamically and should be announced.
|
|
96
|
-
- Not a toast.
|
|
97
|
-
- Could have simple or complex html content.
|
|
98
|
-
- Alerts may include a decorative leading icon. Place an `aria-hidden="true"` element as the first direct child.
|
|
99
|
-
- Use `.sm` or `.lg` for density changes. The inline padding stays stable.
|
|
100
|
-
|
|
101
|
-
```html{.stack}
|
|
102
|
-
<div class="alert success">
|
|
103
|
-
<i class="ti ti-circle-check" aria-hidden="true"></i>
|
|
104
|
-
<div>Your changes have been saved. <a href="#">View activity</a>.</div>
|
|
105
|
-
</div>
|
|
106
|
-
|
|
107
|
-
<div class="alert warning" role="alert">
|
|
108
|
-
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
|
|
109
|
-
<div>Please review the <a href="#">failed checks</a> before continuing.</div>
|
|
110
|
-
</div>
|
|
111
|
-
|
|
112
|
-
<div class="alert">
|
|
113
|
-
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M5.255 5.786a.237.237 0 0 0 .241.247h.825c.138 0 .248-.113.266-.25.09-.656.54-1.134 1.342-1.134.686 0 1.314.343 1.314 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.003.217a.25.25 0 0 0 .25.246h.811a.25.25 0 0 0 .25-.25v-.105c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.267 0-2.655.59-2.75 2.286m1.557 5.763c0 .533.425.927 1.01.927.609 0 1.028-.394 1.028-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94"/></svg>
|
|
114
|
-
<div>This is a default alert message.</div>
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
|
-
<div class="alert danger" role="alert">
|
|
118
|
-
<strong>Error!</strong>
|
|
119
|
-
<div>Something went wrong.</div>
|
|
120
|
-
</div>
|
|
121
|
-
|
|
122
|
-
<div class="alert danger" role="alert">
|
|
123
|
-
I'm a simple error
|
|
124
|
-
</div>
|
|
125
|
-
|
|
126
|
-
<div class="alert danger" role="alert">
|
|
127
|
-
I'm a simple error <a href="#">with a link and no joke</a>
|
|
128
|
-
</div>
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
```html
|
|
132
|
-
<div class="alert danger" role="alert">
|
|
133
|
-
<i class="ti ti-alert-triangle" aria-hidden="true"></i>
|
|
134
|
-
|
|
135
|
-
<div class="stack">
|
|
136
|
-
<strong>Payment failed.</strong>
|
|
137
|
-
<p>Check your billing details or try another card.</p>
|
|
138
|
-
|
|
139
|
-
<menu class="actions cluster">
|
|
140
|
-
<li><a class="btn danger sm" href="/billing">Update billing</a></li>
|
|
141
|
-
<li><a href="/support">Contact support</a></li>
|
|
142
|
-
</menu>
|
|
143
|
-
</div>
|
|
144
|
-
</div>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
Variants
|
|
148
|
-
|
|
149
|
-
```html{.stack}
|
|
150
|
-
<div class="alert danger sm" role="alert">
|
|
151
|
-
I'm a small error
|
|
152
|
-
</div>
|
|
153
|
-
|
|
154
|
-
<div class="alert danger lg" role="alert">
|
|
155
|
-
I'm a large error
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
<div class="alert danger outline" role="alert">
|
|
159
|
-
I'm an outline error <a href="#">with a link</a>
|
|
160
|
-
</div>
|
|
161
|
-
|
|
162
|
-
<div class="alert danger solid" role="alert">
|
|
163
|
-
I'm a solid error <a href="#">with a link</a>
|
|
164
|
-
</div>
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
## Avatar
|
|
168
|
-
|
|
169
|
-
> Initials or image representing a person or entity, composable with a status dot.
|
|
170
|
-
|
|
171
|
-
- Supports initials and images.
|
|
172
|
-
- Can be an inert element, link, or button when the link/button has a real destination or action.
|
|
173
|
-
- Stack avatars with `.avatar-stack` for overlapping group displays
|
|
174
|
-
- A status dot attaches as an empty `.badge` child; the badge carries an `aria-label` so the dot conveys its meaning to assistive tech.
|
|
175
|
-
- Does not support shape modifiers as public API. Shape is theme-level.
|
|
176
|
-
- Sizes can be adjusted with CSS variables and optional `.sm` or `.lg`.
|
|
177
|
-
- Background is an exposed css variable (and can use `data-tone`).
|
|
178
|
-
|
|
179
|
-
```html
|
|
180
|
-
<div class="avatar" role="img" aria-label="John Doe, online">
|
|
181
|
-
<span aria-hidden="true">JD</span>
|
|
182
|
-
<span class="badge success" aria-label="Online"></span>
|
|
183
|
-
</div>
|
|
184
|
-
|
|
185
|
-
<div class="avatar lg" role="img" aria-label="John Doe, online">
|
|
186
|
-
<span aria-hidden="true">JD</span>
|
|
187
|
-
<span class="badge success" aria-label="Online"></span>
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
<div class="avatar sm" role="img" aria-label="John Doe, errors">
|
|
191
|
-
<span aria-hidden="true">JD</span>
|
|
192
|
-
<span class="badge danger" aria-label="2 errors"></span>
|
|
193
|
-
</div>
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
```html
|
|
197
|
-
<a href="#" class="avatar">
|
|
198
|
-
<img src="https://mockmind-api.uifaces.co/content/human/219.jpg" alt="Jane Doe" />
|
|
199
|
-
</a>
|
|
200
|
-
|
|
201
|
-
<div class="flyout-trigger">
|
|
202
|
-
<button type="button"
|
|
203
|
-
class="avatar"
|
|
204
|
-
aria-haspopup="menu"
|
|
205
|
-
aria-expanded="false"
|
|
206
|
-
aria-controls="profile-menu"
|
|
207
|
-
id="profile-trigger"
|
|
208
|
-
aria-label="Jane Doe, open profile menu">
|
|
209
|
-
<img src="https://mockmind-api.uifaces.co/content/human/219.jpg" alt="" />
|
|
210
|
-
</button>
|
|
211
|
-
<menu class="flyout" data-enhance="flyout" id="profile-menu" aria-labelledby="profile-trigger" hidden>
|
|
212
|
-
<li><a href="#profile">View profile</a></li>
|
|
213
|
-
<li><button type="button">Sign out</button></li>
|
|
214
|
-
</menu>
|
|
215
|
-
</div>
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
```html
|
|
219
|
-
<div class="avatar-stack" role="group" aria-label="Team members">
|
|
220
|
-
<div class="avatar" role="img" aria-label="John Doe" style="--avatar-bg:#E5EEE4">
|
|
221
|
-
<span aria-hidden="true">JD</span>
|
|
222
|
-
</div>
|
|
223
|
-
<div class="avatar" role="img" aria-label="Jane Doe" style="--avatar-bg:#F6F4E8">
|
|
224
|
-
<span aria-hidden="true">JD</span>
|
|
225
|
-
</div>
|
|
226
|
-
<div class="avatar" role="img" aria-label="99 more team members" style="--avatar-bg:#744577;" data-tone="dark">
|
|
227
|
-
<span aria-hidden="true">+99</span>
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
## Badge
|
|
233
|
-
|
|
234
|
-
> Compact label for counts, status, or category tags, with shared intents and variants.
|
|
235
|
-
|
|
236
|
-
- Supports intent colors.
|
|
237
|
-
- Solid by default. Use `.soft` or `.outline` for quieter emphasis.
|
|
238
|
-
- Use `.sm` or `.lg` for compact density changes.
|
|
239
|
-
- Can be used inline in headings.
|
|
240
|
-
- Can be used as a count badge.
|
|
241
|
-
- Can be used as a stable dot badge when empty and given an accessible name.
|
|
242
|
-
- Empty badges render as dots. The element must be truly empty: no text and no whitespace.
|
|
243
|
-
|
|
244
|
-
```html
|
|
245
|
-
<span class="badge">Default</span>
|
|
246
|
-
<span class="badge secondary">Secondary</span>
|
|
247
|
-
<span class="badge success">Success</span>
|
|
248
|
-
<span class="badge warning">Warning</span>
|
|
249
|
-
<span class="badge danger">Danger</span>
|
|
250
|
-
<span class="badge success outline">Outline success</span>
|
|
251
|
-
<span class="badge warning soft">Soft warning</span>
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
In a title
|
|
255
|
-
|
|
256
|
-
```html
|
|
257
|
-
<h2>New features <span class="badge success soft">New</span></h2>
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
Composed
|
|
261
|
-
|
|
262
|
-
```html
|
|
263
|
-
<button type="button" class="btn ghost" aria-label="Notifications">
|
|
264
|
-
<i class="ti ti-bell" aria-hidden="true"></i>
|
|
265
|
-
<span class="badge danger solid" aria-label="12 unread notifications">12</span>
|
|
266
|
-
</button>
|
|
267
|
-
|
|
268
|
-
<button type="button" class="btn secondary soft" aria-label="Notifications">
|
|
269
|
-
<i class="ti ti-bell" aria-hidden="true"></i>
|
|
270
|
-
<span class="badge danger" aria-label="Errors!"></span>
|
|
271
|
-
</button>
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Empty badge dot
|
|
275
|
-
|
|
276
|
-
```html
|
|
277
|
-
<span class="badge success" aria-label="Online"></span>
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
Size variants
|
|
281
|
-
|
|
282
|
-
```html
|
|
283
|
-
<span class="badge success sm">Small Success</span>
|
|
284
|
-
<span class="badge success">Regular Success</span>
|
|
285
|
-
<span class="badge success lg">Large Success</span>
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
Removable tag pattern
|
|
289
|
-
|
|
290
|
-
Use `.badge soft` for tag visuals. Add a direct dismiss button only when the tag can actually be removed. There is no separate chip component.
|
|
291
|
-
|
|
292
|
-
```html
|
|
293
|
-
<span class="badge primary soft">
|
|
294
|
-
Design
|
|
295
|
-
<button type="button" aria-label="Remove Design">
|
|
296
|
-
<i class="ti ti-x" aria-hidden="true"></i>
|
|
297
|
-
</button>
|
|
298
|
-
</span>
|
|
299
|
-
<span class="badge primary soft">
|
|
300
|
-
<button type="button" aria-label="Remove Design">
|
|
301
|
-
<i class="ti ti-x" aria-hidden="true"></i>
|
|
302
|
-
</button>
|
|
303
|
-
Design
|
|
304
|
-
</span>
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
## Breadcrumb
|
|
308
|
-
|
|
309
|
-
> Trail of links showing the current page's location in a hierarchy.
|
|
310
|
-
|
|
311
|
-
- Use a semantic `<nav>` landmark.
|
|
312
|
-
- Put `.breadcrumb` on the ordered list.
|
|
313
|
-
- Use `aria-current="page"` for the current page.
|
|
314
|
-
- Separators are generated with CSS (`li + li::before`).
|
|
315
|
-
|
|
316
|
-
```html
|
|
317
|
-
<nav aria-label="Breadcrumb">
|
|
318
|
-
<ol class="breadcrumb">
|
|
319
|
-
<li><a href="/home">Home</a></li>
|
|
320
|
-
<li><a href="/projects">Projects</a></li>
|
|
321
|
-
<li><a href="/projects/docs">Docs</a></li>
|
|
322
|
-
<li><a href="/current" aria-current="page">Breadcrumb</a></li>
|
|
323
|
-
</ol>
|
|
324
|
-
</nav>
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
## Button
|
|
328
|
-
|
|
329
|
-
> Actions and navigation with shared intents, variants, sizes, and a loading state.
|
|
330
|
-
|
|
331
|
-
- `.btn` is for actionable elements: `<button>`, `<a href>`, or `input[type="button"|"submit"|"reset"]`. Not a decorative box class.
|
|
332
|
-
- Use a real `<button>` for actions.
|
|
333
|
-
- Use `<a class="btn">` for navigation.
|
|
334
|
-
- Always set `type="button"` when a button is not submitting a form.
|
|
335
|
-
- Supports shared intents, shared variants, button-only variants, and sizes.
|
|
336
|
-
- Adds button-only `.ghost` and `.link` variants.
|
|
337
|
-
- Button groups use `.join` to visually join adjacent buttons.
|
|
338
|
-
- Use `aria-pressed` for toggle buttons. Actual styles the pressed state; application code owns changing the attribute.
|
|
339
|
-
- Disable a `<button>` or `<input>` with the native `disabled` attribute. Anchors have no native disabled state, so `<a class="btn" aria-disabled="true">` is the supported way to disable a link button; application code must also prevent the click since `aria-disabled` does not stop navigation on its own.
|
|
340
|
-
|
|
341
|
-
```html{.cluster}
|
|
342
|
-
<button type="button">Unstyled</button>
|
|
343
|
-
<button class="btn" type="button">Default</button>
|
|
344
|
-
<button class="btn secondary" type="button">Secondary</button>
|
|
345
|
-
<button class="btn danger" type="button">Danger</button>
|
|
346
|
-
<button class="btn outline" type="button">Outline</button>
|
|
347
|
-
<button class="btn danger outline" type="button">Danger outline</button>
|
|
348
|
-
<button class="btn soft" type="button">Soft</button>
|
|
349
|
-
<button class="btn danger soft" type="button">Danger soft</button>
|
|
350
|
-
<button class="btn ghost" type="button">Ghost</button>
|
|
351
|
-
<a class="btn primary" href="/account">Account</a>
|
|
352
|
-
<button class="btn link" type="button">Button as link</button>
|
|
353
|
-
<button class="btn primary" type="button" aria-busy="true" disabled>
|
|
354
|
-
<span class="spinner" aria-hidden="true"></span>
|
|
355
|
-
Loading
|
|
356
|
-
</button>
|
|
357
|
-
<button class="btn primary" type="button" aria-busy="true">In progress</button>
|
|
358
|
-
<button class="btn" type="button" disabled>Disabled</button>
|
|
359
|
-
<a class="btn outline" href="/account" aria-disabled="true">Disabled link</a>
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
Button group using `.join`
|
|
363
|
-
|
|
364
|
-
```html
|
|
365
|
-
<div class="join" role="group" aria-label="Text alignment">
|
|
366
|
-
<button class="btn" type="button">Left</button>
|
|
367
|
-
<button class="btn outline" type="button">Center</button>
|
|
368
|
-
<button class="btn soft" type="button">Right</button>
|
|
369
|
-
</div>
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
Toggle buttons
|
|
373
|
-
|
|
374
|
-
```html
|
|
375
|
-
<button class="btn" type="button" aria-pressed="false" data-demo-toggle>
|
|
376
|
-
Bold
|
|
377
|
-
</button>
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
```html
|
|
381
|
-
<div class="join" role="group" aria-label="Text alignment" data-demo-toggle-group="single">
|
|
382
|
-
<button class="btn" type="button" aria-pressed="true">Left</button>
|
|
383
|
-
<button class="btn outline" type="button" aria-pressed="false">Center</button>
|
|
384
|
-
<button class="btn outline" type="button" aria-pressed="false">Right</button>
|
|
385
|
-
</div>
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
```js
|
|
389
|
-
for (const button of document.querySelectorAll("[data-demo-toggle]")) {
|
|
390
|
-
button.addEventListener("click", () => {
|
|
391
|
-
const pressed = button.getAttribute("aria-pressed") === "true";
|
|
392
|
-
button.setAttribute("aria-pressed", String(!pressed));
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
for (const group of document.querySelectorAll('[data-demo-toggle-group="single"]')) {
|
|
397
|
-
group.addEventListener("click", (event) => {
|
|
398
|
-
const button = event.target.closest("button[aria-pressed]");
|
|
399
|
-
if (!button || !group.contains(button)) return;
|
|
400
|
-
|
|
401
|
-
for (const item of group.querySelectorAll("button[aria-pressed]")) {
|
|
402
|
-
item.setAttribute("aria-pressed", String(item === button));
|
|
403
|
-
}
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
Size variants
|
|
409
|
-
|
|
410
|
-
```html
|
|
411
|
-
<button class="btn sm" type="button">Small</button>
|
|
412
|
-
<button class="btn" type="button">Regular</button>
|
|
413
|
-
<button class="btn lg" type="button">Large</button>
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
With icons, loading state...
|
|
417
|
-
|
|
418
|
-
```html
|
|
419
|
-
<button class="btn" type="button"><i class="ti ti-star"></i> With an icon</button>
|
|
420
|
-
<button class="btn primary" type="button" aria-busy="true" disabled>
|
|
421
|
-
<span class="spinner" aria-hidden="true"></span>
|
|
422
|
-
Saving…
|
|
423
|
-
</button>
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
## Card
|
|
427
|
-
|
|
428
|
-
> Flexible content container with optional header, body, footer, and bleed regions.
|
|
429
|
-
|
|
430
|
-
- Use semantic elements.
|
|
431
|
-
- Supports one or more content sections.
|
|
432
|
-
- Should display nicely in grids with equal-height behavior.
|
|
433
|
-
- Does not own page spacing.
|
|
434
|
-
- A direct `<header>` or `<footer>` is the card's structural slot.
|
|
435
|
-
- Use `.bleed` on a direct child to escape the card padding (full-width images, colored headers or footers).
|
|
436
|
-
|
|
437
|
-
```html
|
|
438
|
-
<div style="max-inline-size: 32rem">
|
|
439
|
-
<article class="card stack">
|
|
440
|
-
<header>
|
|
441
|
-
<hgroup>
|
|
442
|
-
<h3>Understanding Semantic HTML</h3>
|
|
443
|
-
<p class="muted">A quick primer for new contributors</p>
|
|
444
|
-
</hgroup>
|
|
445
|
-
</header>
|
|
446
|
-
|
|
447
|
-
<p>Using the right HTML tags improves both SEO and accessibility. Lean on landmarks and live lists.</p>
|
|
448
|
-
|
|
449
|
-
<ul class="cluster" style="list-style: none; padding: 0; margin: 0; gap: 0.5rem" aria-label="Tags">
|
|
450
|
-
<li><span class="badge primary soft secondary">HTML</span></li>
|
|
451
|
-
<li><span class="badge soft primary">Accessibility</span></li>
|
|
452
|
-
<li><span class="badge outline">5 min read</span></li>
|
|
453
|
-
</ul>
|
|
454
|
-
|
|
455
|
-
<footer>
|
|
456
|
-
<time datetime="2026-06-12" class="muted">June 12, 2026</time>
|
|
457
|
-
<button type="button" class="btn outline">Read more</button>
|
|
458
|
-
</footer>
|
|
459
|
-
</article>
|
|
460
|
-
</div>
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
```html
|
|
464
|
-
<div style="max-inline-size: 32rem">
|
|
465
|
-
<article class="card stack">
|
|
466
|
-
<img class="bleed" src="https://picsum.photos/seed/actual-css-card/600/300" alt="Coastal cliffs at dusk" />
|
|
467
|
-
<header>
|
|
468
|
-
<h3>Coastal cliffs at dusk</h3>
|
|
469
|
-
</header>
|
|
470
|
-
<section class="stack" aria-label="Summary">
|
|
471
|
-
<p>A short caption that wraps across a few lines. The image bleeds to the card edges.</p>
|
|
472
|
-
</section>
|
|
473
|
-
<footer>
|
|
474
|
-
<span class="badge primary soft">Photo</span>
|
|
475
|
-
<button type="button" class="btn outline">View</button>
|
|
476
|
-
</footer>
|
|
477
|
-
</article>
|
|
478
|
-
</div>
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
```html
|
|
482
|
-
<article class="card stack" style="--card-max-inline-size: 24rem">
|
|
483
|
-
<header class="bleed stack items-center text-center" style="background: var(--surface-subtle)">
|
|
484
|
-
<hgroup>
|
|
485
|
-
<h3>Team</h3>
|
|
486
|
-
<p class="muted">For growing products</p>
|
|
487
|
-
</hgroup>
|
|
488
|
-
<p>
|
|
489
|
-
<span style="font-size: 2rem; font-weight: var(--font-weight-strong); line-height: 1">$24</span>
|
|
490
|
-
<span class="muted">/ user / month</span>
|
|
491
|
-
</p>
|
|
492
|
-
</header>
|
|
493
|
-
|
|
494
|
-
<ul class="stack items-center" style="list-style: none; padding: 0">
|
|
495
|
-
<li>Unlimited projects</li>
|
|
496
|
-
<li>Up to 25 seats</li>
|
|
497
|
-
<li>Shared workspaces</li>
|
|
498
|
-
<li>Priority support</li>
|
|
499
|
-
</ul>
|
|
500
|
-
|
|
501
|
-
<footer class="bleed" style="background: var(--surface-subtle); justify-content: center">
|
|
502
|
-
<a class="btn primary" href="/billing">Upgrade</a>
|
|
503
|
-
</footer>
|
|
504
|
-
</article>
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
```html
|
|
508
|
-
<section class="grid">
|
|
509
|
-
<article class="card">
|
|
510
|
-
<header>
|
|
511
|
-
<h3>Components</h3>
|
|
512
|
-
</header>
|
|
513
|
-
<p>Buttons, alerts, dialogs — all opt-in.</p>
|
|
514
|
-
<footer>
|
|
515
|
-
<a class="btn outline" href="components.html">Browse</a>
|
|
516
|
-
</footer>
|
|
517
|
-
</article>
|
|
518
|
-
|
|
519
|
-
<article class="card">
|
|
520
|
-
<header>
|
|
521
|
-
<h3>Layout</h3>
|
|
522
|
-
</header>
|
|
523
|
-
<p>Stack, cluster, grid, switcher, sidebar.</p>
|
|
524
|
-
<footer>
|
|
525
|
-
<a class="btn outline" href="layout.html">Browse</a>
|
|
526
|
-
</footer>
|
|
527
|
-
</article>
|
|
528
|
-
|
|
529
|
-
<article class="card">
|
|
530
|
-
<header>
|
|
531
|
-
<h3>Patterns</h3>
|
|
532
|
-
</header>
|
|
533
|
-
<p>Actions, nav-list — small structural helpers.</p>
|
|
534
|
-
<footer>
|
|
535
|
-
<a class="btn outline" href="patterns.html">Browse</a>
|
|
536
|
-
</footer>
|
|
537
|
-
</article>
|
|
538
|
-
</section>
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
```html
|
|
542
|
-
<section class="grid gap-none">
|
|
543
|
-
<article class="card">
|
|
544
|
-
<header>
|
|
545
|
-
<h3>Design tokens</h3>
|
|
546
|
-
</header>
|
|
547
|
-
<p>Semantic variables for color, shape, spacing, and motion.</p>
|
|
548
|
-
</article>
|
|
549
|
-
|
|
550
|
-
<article class="card">
|
|
551
|
-
<header>
|
|
552
|
-
<h3>Utilities</h3>
|
|
553
|
-
</header>
|
|
554
|
-
<p>Small layout helpers for local composition.</p>
|
|
555
|
-
</article>
|
|
556
|
-
|
|
557
|
-
<article class="card">
|
|
558
|
-
<header>
|
|
559
|
-
<h3>Runtime</h3>
|
|
560
|
-
</header>
|
|
561
|
-
<p>Optional JavaScript for progressive interactions.</p>
|
|
562
|
-
</article>
|
|
563
|
-
</section>
|
|
564
|
-
```
|
|
565
|
-
|
|
566
|
-
```html
|
|
567
|
-
<section class="grid">
|
|
568
|
-
<article class="card raised">
|
|
569
|
-
<hgroup>
|
|
570
|
-
<h3>Raised</h3>
|
|
571
|
-
<p class="muted">Elevated surface with a soft shadow.</p>
|
|
572
|
-
</hgroup>
|
|
573
|
-
</article>
|
|
574
|
-
|
|
575
|
-
<article class="card subtle">
|
|
576
|
-
<hgroup>
|
|
577
|
-
<h3>Subtle</h3>
|
|
578
|
-
<p class="muted">Lower contrast against the page surface.</p>
|
|
579
|
-
</hgroup>
|
|
580
|
-
</article>
|
|
581
|
-
|
|
582
|
-
<article class="card inverted stack">
|
|
583
|
-
<hgroup>
|
|
584
|
-
<h3>Inverted</h3>
|
|
585
|
-
<p>Dark surface for emphasis. Text inherits the light surface color.</p>
|
|
586
|
-
</hgroup>
|
|
587
|
-
<button type="button" class="btn">Action</button>
|
|
588
|
-
</article>
|
|
589
|
-
|
|
590
|
-
<article class="card compact">
|
|
591
|
-
<hgroup>
|
|
592
|
-
<h3>Compact</h3>
|
|
593
|
-
<p class="muted">Tighter padding for dense contexts.</p>
|
|
594
|
-
</hgroup>
|
|
595
|
-
</article>
|
|
596
|
-
</section>
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
## Key
|
|
600
|
-
|
|
601
|
-
> Keyboard keys and shortcut tokens for app UI, command palettes, menus, and help text.
|
|
602
|
-
|
|
603
|
-
- Use `<kbd class="key">` outside prose.
|
|
604
|
-
- Plain `<kbd>` inside `.prose` gets the same visual treatment for authored content.
|
|
605
|
-
- `.shortcut` is a documented composition, not a component class. Compose multiple `.key` elements with text or layout utilities.
|
|
606
|
-
- Use short, familiar labels such as `Ctrl`, `Shift`, `Esc`, or `K`.
|
|
607
|
-
|
|
608
|
-
```html
|
|
609
|
-
<p>Press <kbd class="key">Esc</kbd> to close the panel.</p>
|
|
610
|
-
|
|
611
|
-
<div class="cluster" aria-label="Keyboard shortcut Control K">
|
|
612
|
-
<kbd class="key">Ctrl</kbd>
|
|
613
|
-
<kbd class="key">K</kbd>
|
|
614
|
-
</div>
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
In menus, keep the command label and shortcut in the same interactive item.
|
|
618
|
-
|
|
619
|
-
```html
|
|
620
|
-
<button type="button">
|
|
621
|
-
<span>Search</span>
|
|
622
|
-
<span class="cluster" aria-label="Keyboard shortcut Control K">
|
|
623
|
-
<kbd class="key">Ctrl</kbd>
|
|
624
|
-
<kbd class="key">K</kbd>
|
|
625
|
-
</span>
|
|
626
|
-
</button>
|
|
627
|
-
```
|
|
628
|
-
|
|
629
|
-
## Meter
|
|
630
|
-
|
|
631
|
-
> Scalar measurement within a known range, not a progress indicator.
|
|
632
|
-
|
|
633
|
-
- Use native `<meter class="meter">`.
|
|
634
|
-
- Shares progress styling DNA.
|
|
635
|
-
- Represents a scalar measurement within a known range, not task completion.
|
|
636
|
-
- Use explicit bar height to avoid padding issues
|
|
637
|
-
|
|
638
|
-
```html{.stack}
|
|
639
|
-
<meter class="meter" value="0.8" min="0" max="1" low="0.3" high="0.7" optimum="1"></meter>
|
|
640
|
-
<meter class="meter" value="0.5" min="0" max="1" low="0.3" high="0.7" optimum="1"></meter>
|
|
641
|
-
<meter class="meter" value="0.2" min="0" max="1" low="0.3" high="0.7" optimum="1"></meter>
|
|
642
|
-
```
|
|
643
|
-
|
|
644
|
-
## Pagination
|
|
645
|
-
|
|
646
|
-
> Navigation controls to move between pages of content.
|
|
647
|
-
|
|
648
|
-
- Use a semantic `<nav>` landmark.
|
|
649
|
-
- Put `.pagination` on the ordered list.
|
|
650
|
-
- Use `aria-current="page"` for the current page.
|
|
651
|
-
- Put `.sm` or `.lg` on `.pagination` to change the density of its controls.
|
|
652
|
-
- Numeric links may use `aria-label="Page N"` for clearer screen reader output.
|
|
653
|
-
- Prefer text labels for Previous and Next. Icon-only controls need an accessible name.
|
|
654
|
-
- Page links can compose with `.btn` for button-like hit targets.
|
|
655
|
-
- Truncated ranges are plain text with `.muted` and `aria-hidden="true"`, not `.btn` — they are decorative, not actionable.
|
|
656
|
-
|
|
657
|
-
```html
|
|
658
|
-
<nav aria-label="Pagination">
|
|
659
|
-
<ol class="pagination sm">
|
|
660
|
-
<li><a href="?page=2" class="btn outline" rel="prev">Previous</a></li>
|
|
661
|
-
<li><a href="?page=1" class="btn outline" aria-label="Page 1">1</a></li>
|
|
662
|
-
<li><a href="?page=2" class="btn outline" aria-label="Page 2">2</a></li>
|
|
663
|
-
<li><a href="?page=3" class="btn" aria-current="page" aria-label="Page 3">3</a></li>
|
|
664
|
-
<li><a href="?page=4" class="btn outline" aria-label="Page 4">4</a></li>
|
|
665
|
-
<li><a href="?page=5" class="btn outline" rel="next">Next</a></li>
|
|
666
|
-
</ol>
|
|
667
|
-
</nav>
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
```html
|
|
671
|
-
<nav aria-label="Pagination">
|
|
672
|
-
<ol class="pagination sm">
|
|
673
|
-
<li><a href="?page=1" class="btn outline" rel="prev">Previous</a></li>
|
|
674
|
-
<li><a href="?page=1" class="btn outline" aria-label="Page 1">1</a></li>
|
|
675
|
-
<li><span class="muted" aria-hidden="true">…</span></li>
|
|
676
|
-
<li><a href="?page=7" class="btn outline" aria-label="Page 7">7</a></li>
|
|
677
|
-
<li><a href="?page=8" class="btn" aria-current="page" aria-label="Page 8">8</a></li>
|
|
678
|
-
<li><a href="?page=9" class="btn outline" aria-label="Page 9">9</a></li>
|
|
679
|
-
<li><span class="muted" aria-hidden="true">…</span></li>
|
|
680
|
-
<li><a href="?page=20" class="btn outline" aria-label="Page 20">20</a></li>
|
|
681
|
-
<li><a href="?page=9" class="btn outline" rel="next">Next</a></li>
|
|
682
|
-
</ol>
|
|
683
|
-
</nav>
|
|
684
|
-
```
|
|
685
|
-
|
|
686
|
-
## Progress
|
|
687
|
-
|
|
688
|
-
> Indeterminate or determinate indicator of task completion.
|
|
689
|
-
|
|
690
|
-
- Use native `<progress class="progress">`.
|
|
691
|
-
- Shares meter styling DNA.
|
|
692
|
-
- Supports indeterminate progress by omitting `value`.
|
|
693
|
-
- Can be connected to a busy region with `aria-describedby`.
|
|
694
|
-
- Never self-close `<progress>`.
|
|
695
|
-
|
|
696
|
-
```html{.stack}
|
|
697
|
-
<progress class="progress" value="60" max="100"></progress>
|
|
698
|
-
<progress class="progress" value="30" max="100"></progress>
|
|
699
|
-
<progress class="progress" value="90" max="100"></progress>
|
|
700
|
-
<progress class="progress"></progress>
|
|
701
|
-
|
|
702
|
-
<section aria-busy="true" aria-describedby="upload-progress">
|
|
703
|
-
<h2>Uploading files</h2>
|
|
704
|
-
<progress class="progress" id="upload-progress" value="60" max="100">60%</progress>
|
|
705
|
-
</section>
|
|
706
|
-
```
|
|
707
|
-
|
|
708
|
-
## Spinner
|
|
709
|
-
|
|
710
|
-
> Loading indicator for actions or regions that may take noticeable time.
|
|
711
|
-
|
|
712
|
-
- Most actions do not need a spinner. Use `disabled` alone for fast actions or to prevent duplicate submissions.
|
|
713
|
-
- Use `aria-busy="true"` with a loading label for actions that are visibly in progress.
|
|
714
|
-
- Add `.spinner` only when the operation may take long enough that users need explicit loading feedback.
|
|
715
|
-
- The spinner uses `currentColor`, so it adapts to its context.
|
|
716
|
-
- Decorative spinners should be `aria-hidden="true"`.
|
|
717
|
-
- Use `role="status"` with accessible text when the loading state needs to be announced.
|
|
718
|
-
- Put a direct last-child `.spinner` inside a busy region to show a centered loading overlay. In buttons, spinners remain inline.
|
|
719
|
-
|
|
720
|
-
```html
|
|
721
|
-
<span class="spinner"></span>
|
|
722
|
-
<span class="spinner sm primary"></span>
|
|
723
|
-
<span class="spinner lg danger"></span>
|
|
724
|
-
```
|
|
725
|
-
|
|
726
|
-
```html
|
|
727
|
-
<button class="btn primary" type="submit" aria-busy="true" disabled>
|
|
728
|
-
<span class="spinner" aria-hidden="true"></span>
|
|
729
|
-
Saving…
|
|
730
|
-
</button>
|
|
731
|
-
```
|
|
732
|
-
|
|
733
|
-
```html
|
|
734
|
-
<article class="card" aria-busy="true" aria-label="Loading card content">
|
|
735
|
-
<hgroup>
|
|
736
|
-
<h3>Card Title</h3>
|
|
737
|
-
<p class="muted">Card description goes here.</p>
|
|
738
|
-
</hgroup>
|
|
739
|
-
|
|
740
|
-
<p>This is the card content. It can contain any HTML.</p>
|
|
741
|
-
|
|
742
|
-
<footer class="cluster">
|
|
743
|
-
<button class="btn outline" disabled>Cancel</button>
|
|
744
|
-
<button class="btn" disabled>Save</button>
|
|
745
|
-
</footer>
|
|
746
|
-
|
|
747
|
-
<span class="spinner lg" aria-hidden="true"></span>
|
|
748
|
-
</article>
|
|
749
|
-
```
|
|
750
|
-
|
|
751
|
-
```html
|
|
752
|
-
<div role="status">
|
|
753
|
-
<span class="spinner" aria-hidden="true"></span>
|
|
754
|
-
<span class="sr-only">Loading results</span>
|
|
755
|
-
</div>
|
|
756
|
-
```
|
|
757
|
-
|
|
758
|
-
## Skeleton
|
|
759
|
-
|
|
760
|
-
> Placeholder shapes for content that is loading.
|
|
761
|
-
|
|
762
|
-
- Use `.skeleton` for loading placeholders.
|
|
763
|
-
- Use `data-shape` for common placeholder forms: `text`, `title`, `avatar`, `box`.
|
|
764
|
-
- Put `role="status"` and accessible text on the loading region, not on every placeholder.
|
|
765
|
-
- Use layout utilities for placeholder arrangement.
|
|
766
|
-
- Only relevant for simple placeholders - use more structural solutions like phantom-ui for complex cases.
|
|
767
|
-
|
|
768
|
-
```html
|
|
769
|
-
<article class="card" role="status" aria-label="Loading profile">
|
|
770
|
-
<div class="cluster">
|
|
771
|
-
<div class="skeleton" data-shape="avatar" aria-hidden="true"></div>
|
|
772
|
-
<div class="stack grow">
|
|
773
|
-
<div class="skeleton" data-shape="title" aria-hidden="true"></div>
|
|
774
|
-
<div class="skeleton" data-shape="text" aria-hidden="true"></div>
|
|
775
|
-
</div>
|
|
776
|
-
</div>
|
|
777
|
-
</article>
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
## Table
|
|
781
|
-
|
|
782
|
-
> Data table with caption and scope attributes, and an accessible scroll region for wide content.
|
|
783
|
-
|
|
784
|
-
- Use native `<table class="table">` inside a `.table-wrap` for surface, border, radius, and overflow.
|
|
785
|
-
- Use `<caption>`, `scope="col"`, and `scope="row"` for accessibility.
|
|
786
|
-
- Use `.text-end` for numeric columns and `.nowrap` for non-wrapping cells.
|
|
787
|
-
- For wide tables, make the wrapper an accessible scroll region with `role="region"`, `aria-labelledby`, and `tabindex="0"`.
|
|
788
|
-
- Tables stay content-first and neutral by default.
|
|
789
|
-
|
|
790
|
-
```html
|
|
791
|
-
<div class="table-wrap">
|
|
792
|
-
<table class="table">
|
|
793
|
-
<caption>Team members</caption>
|
|
794
|
-
<thead>
|
|
795
|
-
<tr>
|
|
796
|
-
<th scope="col">Name</th>
|
|
797
|
-
<th scope="col">Email</th>
|
|
798
|
-
<th scope="col">Role</th>
|
|
799
|
-
<th scope="col">Status</th>
|
|
800
|
-
</tr>
|
|
801
|
-
</thead>
|
|
802
|
-
<tbody>
|
|
803
|
-
<tr>
|
|
804
|
-
<td>Alice Johnson</td>
|
|
805
|
-
<td>alice@example.com</td>
|
|
806
|
-
<td>Admin</td>
|
|
807
|
-
<td><span class="badge success soft">Active</span></td>
|
|
808
|
-
</tr>
|
|
809
|
-
<tr>
|
|
810
|
-
<td>Bob Smith</td>
|
|
811
|
-
<td>bob@example.com</td>
|
|
812
|
-
<td>Editor</td>
|
|
813
|
-
<td><span class="badge success soft">Active</span></td>
|
|
814
|
-
</tr>
|
|
815
|
-
<tr>
|
|
816
|
-
<td>Carol White</td>
|
|
817
|
-
<td>carol@example.com</td>
|
|
818
|
-
<td>Viewer</td>
|
|
819
|
-
<td><span class="badge secondary soft">Pending</span></td>
|
|
820
|
-
</tr>
|
|
821
|
-
</tbody>
|
|
822
|
-
</table>
|
|
823
|
-
</div>
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
```html
|
|
827
|
-
<div class="table-wrap" role="region" aria-labelledby="revenue-table" tabindex="0">
|
|
828
|
-
<table class="table" style="--table-min: 64rem">
|
|
829
|
-
<caption id="revenue-table">Revenue by month</caption>
|
|
830
|
-
<thead>
|
|
831
|
-
<tr>
|
|
832
|
-
<th scope="col">Month</th>
|
|
833
|
-
<th scope="col">Plan</th>
|
|
834
|
-
<th scope="col" class="text-end">Revenue</th>
|
|
835
|
-
<th scope="col" class="text-end">Churn</th>
|
|
836
|
-
</tr>
|
|
837
|
-
</thead>
|
|
838
|
-
<tbody>
|
|
839
|
-
<tr>
|
|
840
|
-
<td>March 2026</td>
|
|
841
|
-
<td>Team</td>
|
|
842
|
-
<td class="text-end nowrap">$42,128</td>
|
|
843
|
-
<td class="text-end nowrap">1.2%</td>
|
|
844
|
-
</tr>
|
|
845
|
-
<tr>
|
|
846
|
-
<td>April 2026</td>
|
|
847
|
-
<td>Team + Business</td>
|
|
848
|
-
<td class="text-end nowrap">$48,902</td>
|
|
849
|
-
<td class="text-end nowrap">0.9%</td>
|
|
850
|
-
</tr>
|
|
851
|
-
<tr>
|
|
852
|
-
<td>May 2026</td>
|
|
853
|
-
<td>Team + Business</td>
|
|
854
|
-
<td class="text-end nowrap">$53,470</td>
|
|
855
|
-
<td class="text-end nowrap">0.7%</td>
|
|
856
|
-
</tr>
|
|
857
|
-
</tbody>
|
|
858
|
-
</table>
|
|
859
|
-
</div>
|
|
860
|
-
```
|