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,205 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
Actions and navigation with shared intents, variants, sizes, and loading, pressed, and disabled states.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.btn` | Component | Base button. Solid by default; works on `<button>`, `<a href>`, and button-like `<input>`. |
|
|
10
|
+
| `.primary` | Intent | Primary action. |
|
|
11
|
+
| `.secondary` | Intent | Secondary action. |
|
|
12
|
+
| `.success` | Intent | Positive outcome. |
|
|
13
|
+
| `.warning` | Intent | Caution. |
|
|
14
|
+
| `.danger` | Intent | Destructive action. |
|
|
15
|
+
| `.neutral` | Intent | Neutral tone (the `.btn` default). |
|
|
16
|
+
| `.soft` | Variant | Muted intent-tinted surface. |
|
|
17
|
+
| `.outline` | Variant | Transparent with an intent-colored border. |
|
|
18
|
+
| `.solid` | Variant | Filled intent background — the `.btn` default. |
|
|
19
|
+
| `.ghost` | Variant | Borderless text button (button-only). |
|
|
20
|
+
| `.link` | Variant | Underlined text button (button-only). |
|
|
21
|
+
| `.sm` / `.lg` | Size | Compact or large control height. |
|
|
22
|
+
| `.icon-only` | Variant | Square icon button sized to the control height. |
|
|
23
|
+
|
|
24
|
+
## Basic usage
|
|
25
|
+
|
|
26
|
+
Use `.btn` on actionable elements: `<button>`, `<a href>`, or
|
|
27
|
+
`input[type="button"|"submit"|"reset"]`. Use a real `<button>` for actions and
|
|
28
|
+
`<a class="btn">` for navigation.
|
|
29
|
+
|
|
30
|
+
```html demo
|
|
31
|
+
<div class="cluster">
|
|
32
|
+
<button class="btn" type="button">Default</button>
|
|
33
|
+
<button class="btn primary" type="button">Primary</button>
|
|
34
|
+
<a class="btn primary" href="#">Account</a>
|
|
35
|
+
<input class="btn" type="button" value="Input button" />
|
|
36
|
+
</div>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Intents
|
|
40
|
+
|
|
41
|
+
Shared intent classes set color meaning. They compose with every variant.
|
|
42
|
+
|
|
43
|
+
```html demo
|
|
44
|
+
<div class="cluster">
|
|
45
|
+
<button class="btn primary" type="button">Primary</button>
|
|
46
|
+
<button class="btn secondary" type="button">Secondary</button>
|
|
47
|
+
<button class="btn success" type="button">Success</button>
|
|
48
|
+
<button class="btn warning" type="button">Warning</button>
|
|
49
|
+
<button class="btn danger" type="button">Danger</button>
|
|
50
|
+
<button class="btn neutral" type="button">Neutral</button>
|
|
51
|
+
</div>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Variants
|
|
55
|
+
|
|
56
|
+
`.ghost` and `.link` are button-only; `.soft`, `.outline`, and `.solid` are
|
|
57
|
+
shared with other components.
|
|
58
|
+
|
|
59
|
+
```html demo
|
|
60
|
+
<div class="cluster">
|
|
61
|
+
<button class="btn outline" type="button">Outline</button>
|
|
62
|
+
<button class="btn danger outline" type="button">Danger outline</button>
|
|
63
|
+
<button class="btn soft" type="button">Soft</button>
|
|
64
|
+
<button class="btn danger soft" type="button">Danger soft</button>
|
|
65
|
+
<button class="btn ghost" type="button">Ghost</button>
|
|
66
|
+
<button class="btn link" type="button">Button as link</button>
|
|
67
|
+
</div>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Icon and icon-only buttons
|
|
71
|
+
|
|
72
|
+
```html demo
|
|
73
|
+
<div class="cluster">
|
|
74
|
+
<button class="btn" type="button"><i class="ti ti-star" aria-hidden="true"></i> With an icon</button>
|
|
75
|
+
<button class="btn icon-only" type="button" aria-label="Add">
|
|
76
|
+
<i class="ti ti-plus" aria-hidden="true"></i>
|
|
77
|
+
</button>
|
|
78
|
+
<button class="btn primary icon-only" type="button" aria-label="Search">
|
|
79
|
+
<i class="ti ti-search" aria-hidden="true"></i>
|
|
80
|
+
</button>
|
|
81
|
+
</div>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Use `.btn.icon-only` for a square icon button sized to the control height.
|
|
85
|
+
Always name it with an `aria-label` since there is no visible text.
|
|
86
|
+
|
|
87
|
+
### Button groups
|
|
88
|
+
|
|
89
|
+
Join adjacent buttons with `.join`. The joined group is not a new component —
|
|
90
|
+
the buttons keep their own variants.
|
|
91
|
+
|
|
92
|
+
```html demo
|
|
93
|
+
<div class="join" role="group" aria-label="Text alignment">
|
|
94
|
+
<button class="btn" type="button">Left</button>
|
|
95
|
+
<button class="btn outline" type="button">Center</button>
|
|
96
|
+
<button class="btn soft" type="button">Right</button>
|
|
97
|
+
</div>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Sizes
|
|
101
|
+
|
|
102
|
+
Prefer `.sm` and `.lg` over setting sizes directly. Density variants never
|
|
103
|
+
change typography.
|
|
104
|
+
|
|
105
|
+
```html demo
|
|
106
|
+
<div class="cluster">
|
|
107
|
+
<button class="btn sm" type="button">Small</button>
|
|
108
|
+
<button class="btn" type="button">Regular</button>
|
|
109
|
+
<button class="btn lg" type="button">Large</button>
|
|
110
|
+
</div>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## States
|
|
114
|
+
|
|
115
|
+
### Disabled
|
|
116
|
+
|
|
117
|
+
Disable a `<button>` or `<input>` with the native `disabled` attribute. Anchors
|
|
118
|
+
have no native disabled state, so `<a class="btn" aria-disabled="true">` is the
|
|
119
|
+
supported way to style a disabled link button; application code must also
|
|
120
|
+
prevent the click since `aria-disabled` does not stop navigation on its own.
|
|
121
|
+
|
|
122
|
+
```html demo
|
|
123
|
+
<div class="cluster">
|
|
124
|
+
<button class="btn primary" type="button" disabled>Disabled</button>
|
|
125
|
+
<button class="btn outline" type="button" disabled>Disabled outline</button>
|
|
126
|
+
<a class="btn outline" href="#" aria-disabled="true">Disabled link</a>
|
|
127
|
+
</div>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Loading
|
|
131
|
+
|
|
132
|
+
Set `aria-busy="true"` on the button and add a `.spinner`. The spinner inherits
|
|
133
|
+
the button size.
|
|
134
|
+
|
|
135
|
+
```html demo
|
|
136
|
+
<div class="cluster">
|
|
137
|
+
<button class="btn primary" type="button" aria-busy="true" disabled>
|
|
138
|
+
<span class="spinner" aria-hidden="true"></span>
|
|
139
|
+
Saving…
|
|
140
|
+
</button>
|
|
141
|
+
</div>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Toggle
|
|
145
|
+
|
|
146
|
+
Use `aria-pressed` for toggle buttons. Actual styles the pressed state;
|
|
147
|
+
application code owns changing the attribute. The example scopes its script to
|
|
148
|
+
its own preview so repeated demos on a page cannot cross-bind.
|
|
149
|
+
|
|
150
|
+
```html demo
|
|
151
|
+
<div class="cluster">
|
|
152
|
+
<button class="btn" type="button" aria-pressed="false">Bold</button>
|
|
153
|
+
<button class="btn" type="button" aria-pressed="false">Italic</button>
|
|
154
|
+
</div>
|
|
155
|
+
<script>
|
|
156
|
+
(() => {
|
|
157
|
+
const preview = document.currentScript.closest(".docs-preview");
|
|
158
|
+
for (const button of preview.querySelectorAll("button")) {
|
|
159
|
+
button.addEventListener("click", () => {
|
|
160
|
+
const pressed = button.getAttribute("aria-pressed") === "true";
|
|
161
|
+
button.setAttribute("aria-pressed", String(!pressed));
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
})();
|
|
165
|
+
</script>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
For exclusive groups, manage a single pressed button:
|
|
169
|
+
|
|
170
|
+
```html demo
|
|
171
|
+
<div class="join" role="group" aria-label="Text alignment" data-docs-toggle-group>
|
|
172
|
+
<button class="btn" type="button" aria-pressed="true">Left</button>
|
|
173
|
+
<button class="btn outline" type="button" aria-pressed="false">Center</button>
|
|
174
|
+
<button class="btn outline" type="button" aria-pressed="false">Right</button>
|
|
175
|
+
</div>
|
|
176
|
+
<script>
|
|
177
|
+
(() => {
|
|
178
|
+
const preview = document.currentScript.closest(".docs-preview");
|
|
179
|
+
const group = preview.querySelector("[data-docs-toggle-group]");
|
|
180
|
+
group.addEventListener("click", (event) => {
|
|
181
|
+
const button = event.target.closest("button[aria-pressed]");
|
|
182
|
+
if (!button || !group.contains(button)) return;
|
|
183
|
+
for (const item of group.querySelectorAll("button[aria-pressed]")) {
|
|
184
|
+
item.setAttribute("aria-pressed", String(item === button));
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
})();
|
|
188
|
+
</script>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Accessibility
|
|
192
|
+
|
|
193
|
+
- Always set `type="button"` when a button is not submitting a form.
|
|
194
|
+
- Use a real `<button>` for actions and `<a class="btn">` for navigation.
|
|
195
|
+
- Toggle buttons expose their state with `aria-pressed`; the component styles
|
|
196
|
+
the pressed state but application code owns toggling the attribute.
|
|
197
|
+
- Disabled `<button>` and `<input>` use the native `disabled` attribute;
|
|
198
|
+
disabled link buttons use `aria-disabled="true"` plus an app-side
|
|
199
|
+
activation guard.
|
|
200
|
+
|
|
201
|
+
## CSS hooks
|
|
202
|
+
|
|
203
|
+
- `--btn-radius` — corner radius.
|
|
204
|
+
- `--btn-focus-color` — focus ring base color; the ring itself is derived from it.
|
|
205
|
+
- `--btn-gap` — space between an icon and the label text (default `0.375em`).
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Card
|
|
2
|
+
|
|
3
|
+
Flexible content container with optional header, body, and footer regions, plus full-bleed children.
|
|
4
|
+
|
|
5
|
+
## Class reference
|
|
6
|
+
|
|
7
|
+
| Class | Kind | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `.card` | Component | Neutral raised surface for grouped content. |
|
|
10
|
+
| `.raised` | Variant | Elevated surface with a soft shadow. |
|
|
11
|
+
| `.subtle` | Variant | Lower contrast against the page surface. |
|
|
12
|
+
| `.inverted` | Surface modifier | Inverse surface treatment: paints `--surface-solid` and swaps the foreground to `--surface`, so it inverts in dark themes instead of always reading as dark. Apply as `class="card inverted"`, or on any block. |
|
|
13
|
+
| `.compact` | Variant | Tighter padding for dense contexts. |
|
|
14
|
+
|
|
15
|
+
## Basic usage
|
|
16
|
+
|
|
17
|
+
Use semantic elements inside the card. A direct `<header>` or `<footer>` is the
|
|
18
|
+
card's structural slot. Cards do not own page spacing — compose them with
|
|
19
|
+
layout primitives like `.grid`.
|
|
20
|
+
|
|
21
|
+
```html demo
|
|
22
|
+
<div style="max-inline-size: 32rem">
|
|
23
|
+
<article class="card stack">
|
|
24
|
+
<header>
|
|
25
|
+
<hgroup>
|
|
26
|
+
<h3>Understanding Semantic HTML</h3>
|
|
27
|
+
<p class="muted">A quick primer for new contributors</p>
|
|
28
|
+
</hgroup>
|
|
29
|
+
</header>
|
|
30
|
+
|
|
31
|
+
<p>Using the right HTML tags improves both SEO and accessibility. Lean on landmarks and live lists.</p>
|
|
32
|
+
|
|
33
|
+
<ul class="cluster" style="list-style: none; padding: 0; margin: 0; gap: 0.5rem" aria-label="Tags">
|
|
34
|
+
<li><span class="badge primary soft secondary">HTML</span></li>
|
|
35
|
+
<li><span class="badge soft primary">Accessibility</span></li>
|
|
36
|
+
<li><span class="badge outline">5 min read</span></li>
|
|
37
|
+
</ul>
|
|
38
|
+
|
|
39
|
+
<footer>
|
|
40
|
+
<time datetime="2026-06-12" class="muted">June 12, 2026</time>
|
|
41
|
+
<button type="button" class="btn outline">Read more</button>
|
|
42
|
+
</footer>
|
|
43
|
+
</article>
|
|
44
|
+
</div>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Bleed
|
|
48
|
+
|
|
49
|
+
Use `.bleed` on a direct child to escape the card padding — full-width images,
|
|
50
|
+
colored headers, or footers.
|
|
51
|
+
|
|
52
|
+
```html demo
|
|
53
|
+
<div style="max-inline-size: 32rem">
|
|
54
|
+
<article class="card stack">
|
|
55
|
+
<img class="bleed" src="https://picsum.photos/seed/actual-css-card/600/300" alt="Coastal cliffs at dusk" />
|
|
56
|
+
<header>
|
|
57
|
+
<h3>Coastal cliffs at dusk</h3>
|
|
58
|
+
</header>
|
|
59
|
+
<section class="stack" aria-label="Summary">
|
|
60
|
+
<p>A short caption that wraps across a few lines. The image bleeds to the card edges.</p>
|
|
61
|
+
</section>
|
|
62
|
+
<footer>
|
|
63
|
+
<span class="badge primary soft">Photo</span>
|
|
64
|
+
<button type="button" class="btn outline">View</button>
|
|
65
|
+
</footer>
|
|
66
|
+
</article>
|
|
67
|
+
</div>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```html demo
|
|
71
|
+
<article class="card stack" style="--card-max-inline-size: 24rem">
|
|
72
|
+
<header class="bleed stack items-center text-center" style="background: var(--surface-subtle)">
|
|
73
|
+
<hgroup>
|
|
74
|
+
<h3>Team</h3>
|
|
75
|
+
<p class="muted">For growing products</p>
|
|
76
|
+
</hgroup>
|
|
77
|
+
<p>
|
|
78
|
+
<span style="font-size: 2rem; font-weight: var(--font-weight-strong); line-height: 1">$24</span>
|
|
79
|
+
<span class="muted">/ user / month</span>
|
|
80
|
+
</p>
|
|
81
|
+
</header>
|
|
82
|
+
|
|
83
|
+
<ul class="stack items-center" style="list-style: none; padding: 0">
|
|
84
|
+
<li>Unlimited projects</li>
|
|
85
|
+
<li>Up to 25 seats</li>
|
|
86
|
+
<li>Shared workspaces</li>
|
|
87
|
+
<li>Priority support</li>
|
|
88
|
+
</ul>
|
|
89
|
+
|
|
90
|
+
<footer class="bleed" style="background: var(--surface-subtle); justify-content: center">
|
|
91
|
+
<a class="btn primary" href="#">Upgrade</a>
|
|
92
|
+
</footer>
|
|
93
|
+
</article>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## In grids
|
|
97
|
+
|
|
98
|
+
Cards display nicely in grids with equal-height behavior.
|
|
99
|
+
|
|
100
|
+
```html demo
|
|
101
|
+
<section class="grid">
|
|
102
|
+
<article class="card">
|
|
103
|
+
<header>
|
|
104
|
+
<h3>Components</h3>
|
|
105
|
+
</header>
|
|
106
|
+
<p>Buttons, alerts, dialogs — all opt-in.</p>
|
|
107
|
+
<footer>
|
|
108
|
+
<a class="btn outline" href="#">Browse</a>
|
|
109
|
+
</footer>
|
|
110
|
+
</article>
|
|
111
|
+
|
|
112
|
+
<article class="card">
|
|
113
|
+
<header>
|
|
114
|
+
<h3>Layout</h3>
|
|
115
|
+
</header>
|
|
116
|
+
<p>Stack, cluster, grid, switcher, sidebar.</p>
|
|
117
|
+
<footer>
|
|
118
|
+
<a class="btn outline" href="#">Browse</a>
|
|
119
|
+
</footer>
|
|
120
|
+
</article>
|
|
121
|
+
|
|
122
|
+
<article class="card">
|
|
123
|
+
<header>
|
|
124
|
+
<h3>Patterns</h3>
|
|
125
|
+
</header>
|
|
126
|
+
<p>Actions, nav-list — small structural helpers.</p>
|
|
127
|
+
<footer>
|
|
128
|
+
<a class="btn outline" href="#">Browse</a>
|
|
129
|
+
</footer>
|
|
130
|
+
</article>
|
|
131
|
+
</section>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Surfaces
|
|
135
|
+
|
|
136
|
+
`.inverted` is the generic inverse surface treatment, not a card-specific class:
|
|
137
|
+
it works on any block (`<header class="inverted">`, `<section class="inverted">`,
|
|
138
|
+
or `class="card inverted"`) through the shared `--ui-*` contract.
|
|
139
|
+
|
|
140
|
+
`.inverted` and `.subtle` are competing surface treatments — do not combine
|
|
141
|
+
them. `.subtle` paints the card's background directly while `.inverted` swaps
|
|
142
|
+
the surface tokens, so `.card.subtle.inverted` renders a subtle background with
|
|
143
|
+
inverted foreground. Treat them as mutually exclusive, like two competing
|
|
144
|
+
variants.
|
|
145
|
+
|
|
146
|
+
```html demo
|
|
147
|
+
<section class="grid">
|
|
148
|
+
<article class="card raised">
|
|
149
|
+
<hgroup>
|
|
150
|
+
<h3>Raised</h3>
|
|
151
|
+
<p class="muted">Elevated surface with a soft shadow.</p>
|
|
152
|
+
</hgroup>
|
|
153
|
+
</article>
|
|
154
|
+
|
|
155
|
+
<article class="card subtle">
|
|
156
|
+
<hgroup>
|
|
157
|
+
<h3>Subtle</h3>
|
|
158
|
+
<p class="muted">Lower contrast against the page surface.</p>
|
|
159
|
+
</hgroup>
|
|
160
|
+
</article>
|
|
161
|
+
|
|
162
|
+
<article class="card inverted stack">
|
|
163
|
+
<hgroup>
|
|
164
|
+
<h3>Inverted</h3>
|
|
165
|
+
<p>Inverse surface for emphasis. Text inherits the contrasting surface color.</p>
|
|
166
|
+
</hgroup>
|
|
167
|
+
<button type="button" class="btn">Action</button>
|
|
168
|
+
</article>
|
|
169
|
+
|
|
170
|
+
<article class="card compact">
|
|
171
|
+
<hgroup>
|
|
172
|
+
<h3>Compact</h3>
|
|
173
|
+
<p class="muted">Tighter padding for dense contexts.</p>
|
|
174
|
+
</hgroup>
|
|
175
|
+
</article>
|
|
176
|
+
</section>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## CSS hooks
|
|
180
|
+
|
|
181
|
+
- `--card-radius` — corner radius.
|
|
182
|
+
- `--card-max-inline-size` — maximum width.
|
|
183
|
+
- `--card-pad` — inner padding; also drives the negative offsets that let a `.bleed` child reach the card edge. `.compact` lowers it.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Chat
|
|
2
|
+
|
|
3
|
+
> **Optional** — import `actual-css/css/optional/chat` or `actual-css/css/optional/index`.
|
|
4
|
+
|
|
5
|
+
Chat lays out message metadata, an optional avatar, and a content-sized bubble
|
|
6
|
+
at either edge of a conversation.
|
|
7
|
+
|
|
8
|
+
```html demo
|
|
9
|
+
<div class="stack" aria-label="Conversation">
|
|
10
|
+
<div class="chat chat-start">
|
|
11
|
+
<div class="chat-avatar avatar sm" role="img" aria-label="Thomas">
|
|
12
|
+
<span aria-hidden="true">T</span>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="chat-header">
|
|
15
|
+
Thomas <time datetime="2026-08-18T21:30">21:30</time>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="chat-bubble">Are we still shipping today?</div>
|
|
18
|
+
<div class="chat-footer">Delivered</div>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="chat chat-end">
|
|
22
|
+
<div class="chat-header">You</div>
|
|
23
|
+
<div class="chat-bubble primary">Yes, the checks are green.</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Use `.chat-start` and `.chat-end` for logical inline placement, so the layout
|
|
29
|
+
also follows right-to-left writing direction. The avatar is optional. Bubble
|
|
30
|
+
colors compose with intents and shared variants: `.primary`, `.primary.soft`,
|
|
31
|
+
and `.primary.outline` all work without chat-specific color classes.
|
|
32
|
+
|
|
33
|
+
For a live conversation, put an appropriate live-region or `role="log"` on the
|
|
34
|
+
conversation container according to the product's announcement needs. Do not
|
|
35
|
+
put `role="log"` on individual messages.
|
|
36
|
+
|
|
37
|
+
## Class reference
|
|
38
|
+
|
|
39
|
+
| Class | Description |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `.chat` | Message row grid. |
|
|
42
|
+
| `.chat-start` / `.chat-end` | Logical inline placement. |
|
|
43
|
+
| `.chat-avatar` | Avatar grid slot; compose it with `.avatar`. |
|
|
44
|
+
| `.chat-header` / `.chat-footer` | Muted message metadata. |
|
|
45
|
+
| `.chat-bubble` | Content-sized message surface. |
|
|
46
|
+
|
|
47
|
+
## CSS hooks
|
|
48
|
+
|
|
49
|
+
- `--chat-gap` — gap between the avatar and message content.
|
|
50
|
+
- `--chat-max-size` — maximum inline size of a bubble.
|