actual-css 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/CHANGELOG.md +214 -1
  2. package/README.md +13 -11
  3. package/components.json +668 -0
  4. package/dist/actual.css +166 -37
  5. package/dist/actual.full.css +1005 -550
  6. package/dist/actual.full.js +1 -1
  7. package/dist/actual.full.min.css +1 -1
  8. package/dist/actual.js +1 -1
  9. package/dist/actual.min.css +1 -1
  10. package/docs/design-notes/accessibility-decisions.md +33 -0
  11. package/docs/design-notes/browser-support.md +82 -25
  12. package/docs/design-notes/column-layout.md +3 -3
  13. package/docs/design-notes/css-anchor.md +75 -21
  14. package/docs/design-notes/enhancement-contract.md +14 -6
  15. package/docs/design-notes/grid.md +4 -4
  16. package/docs/design-notes/naming.md +6 -1
  17. package/docs/design-notes/platform-alignment.md +99 -2
  18. package/docs/design-notes/popover-manual-poc.md +328 -0
  19. package/docs/design-notes/surface-reparenting.md +131 -0
  20. package/docs/design-notes/tooltip-coordinate-space.md +132 -0
  21. package/docs/design-notes/widget-primitives.md +9 -6
  22. package/docs/pages/components/accordion.md +41 -2
  23. package/docs/pages/components/alert.md +80 -30
  24. package/docs/pages/components/app-navigation.md +6 -0
  25. package/docs/pages/components/avatar.md +6 -6
  26. package/docs/pages/components/badge.md +101 -16
  27. package/docs/pages/components/button.md +16 -8
  28. package/docs/pages/components/card.md +10 -10
  29. package/docs/pages/components/dialog.md +16 -6
  30. package/docs/pages/components/fab.md +4 -3
  31. package/docs/pages/components/list.md +42 -4
  32. package/docs/pages/components/navbar.md +17 -1
  33. package/docs/pages/components/pagination.md +2 -2
  34. package/docs/pages/components/steps.md +19 -0
  35. package/docs/pages/components/table.md +3 -2
  36. package/docs/pages/enhancements/flyout.md +144 -24
  37. package/docs/pages/enhancements/overview.md +25 -0
  38. package/docs/pages/enhancements/status-bar.md +20 -0
  39. package/docs/pages/enhancements/tabs.md +45 -37
  40. package/docs/pages/enhancements/tooltip.md +40 -2
  41. package/docs/pages/examples/overview.md +38 -5
  42. package/docs/pages/forms/choice-cards.md +6 -2
  43. package/docs/pages/forms/combobox.md +1 -1
  44. package/docs/pages/forms/floating-field.md +4 -3
  45. package/docs/pages/forms/joined-controls.md +22 -0
  46. package/docs/pages/forms/otp.md +2 -1
  47. package/docs/pages/forms/overview.md +1 -1
  48. package/docs/pages/forms/states-and-sizes.md +16 -18
  49. package/docs/pages/forms/sticky-actions.md +2 -2
  50. package/docs/pages/forms/switch.md +1 -1
  51. package/docs/pages/foundations/philosophy.md +67 -22
  52. package/docs/pages/foundations/theming.md +10 -2
  53. package/docs/pages/foundations/tokens.md +118 -21
  54. package/docs/pages/foundations/typography.md +35 -14
  55. package/docs/pages/guides/introduction.md +11 -9
  56. package/docs/pages/guides/progressive-enhancement.md +136 -49
  57. package/docs/pages/guides/tailwind.md +3 -2
  58. package/docs/pages/layout/media.md +1 -1
  59. package/docs/pages/layout/overview.md +11 -1
  60. package/docs/pages/layout/scroll-snap.md +3 -3
  61. package/docs/pages/layout/stack.md +17 -9
  62. package/docs/pages/patterns/icon-input.md +4 -2
  63. package/docs/pages/patterns/icon-slot.md +2 -0
  64. package/docs/pages/patterns/intent-nesting.md +1 -1
  65. package/docs/pages/utilities/overview.md +23 -2
  66. package/docs/pages/utilities/sizing-wrapping.md +1 -1
  67. package/docs/pages/utilities/spacing.md +10 -8
  68. package/llms.txt +2 -1
  69. package/package.json +19 -8
  70. package/{scripts/reserved-classes.json → reserved-classes.json} +4 -6
  71. package/src/css/components/accordion.css +42 -3
  72. package/src/css/components/alert.css +25 -13
  73. package/src/css/components/app-nav.css +18 -8
  74. package/src/css/components/avatar.css +13 -1
  75. package/src/css/components/badge.css +78 -12
  76. package/src/css/components/breadcrumb.css +2 -3
  77. package/src/css/components/button.css +9 -16
  78. package/src/css/components/card.css +9 -2
  79. package/src/css/components/chat.css +1 -0
  80. package/src/css/components/data-list.css +1 -1
  81. package/src/css/components/drawer.css +79 -25
  82. package/src/css/components/fab.css +0 -6
  83. package/src/css/components/flyout.css +46 -63
  84. package/src/css/components/index.css +0 -1
  85. package/src/css/components/indicator.css +21 -0
  86. package/src/css/components/join.css +7 -0
  87. package/src/css/components/key.css +10 -0
  88. package/src/css/components/list.css +40 -4
  89. package/src/css/components/menu.css +18 -11
  90. package/src/css/components/modal.css +48 -33
  91. package/src/css/components/navbar.css +37 -4
  92. package/src/css/components/pagination.css +1 -0
  93. package/src/css/components/spinner.css +6 -6
  94. package/src/css/components/status-bar.css +0 -5
  95. package/src/css/components/steps.css +45 -59
  96. package/src/css/components/tab.css +29 -9
  97. package/src/css/components/table.css +5 -5
  98. package/src/css/components/tooltip.css +45 -13
  99. package/src/css/core/base.css +23 -1
  100. package/src/css/core/intents.css +17 -6
  101. package/src/css/core/theme.css +27 -0
  102. package/src/css/core/tokens.css +35 -15
  103. package/src/css/core/variants.css +64 -15
  104. package/src/css/forms/choice-card.css +4 -4
  105. package/src/css/forms/choice.css +6 -3
  106. package/src/css/forms/control.css +2 -1
  107. package/src/css/forms/floating-field.css +3 -3
  108. package/src/css/forms/form.css +4 -3
  109. package/src/css/forms/input-icon.css +20 -14
  110. package/src/css/forms/native.css +6 -1
  111. package/src/css/forms/otp.css +9 -1
  112. package/src/css/forms/range.css +2 -0
  113. package/src/css/forms/select.css +29 -9
  114. package/src/css/forms/switch.css +19 -5
  115. package/src/css/layout/app-layout.css +1 -1
  116. package/src/css/layout/grid.css +50 -76
  117. package/src/css/layout/scroll-snap.css +11 -7
  118. package/src/css/layout/scroller.css +3 -4
  119. package/src/css/layout/stack.css +2 -2
  120. package/src/css/typography/fluid.css +4 -3
  121. package/src/css/typography/prose.css +6 -5
  122. package/src/css/utilities/base.css +2 -1
  123. package/src/css/utilities/extra.css +20 -17
  124. package/src/js/context-menu.js +27 -26
  125. package/src/js/dialog.js +2 -1
  126. package/src/js/dismiss.js +5 -0
  127. package/src/js/enhance.js +34 -2
  128. package/src/js/enhancement-loader.js +36 -43
  129. package/src/js/events.js +0 -3
  130. package/src/js/filter.js +0 -1
  131. package/src/js/floating-space.js +42 -0
  132. package/src/js/flyout.js +9 -44
  133. package/src/js/focus-group.js +7 -0
  134. package/src/js/focus.js +6 -0
  135. package/src/js/menu.js +10 -1
  136. package/src/js/selectors.js +5 -9
  137. package/src/js/status.js +44 -7
  138. package/src/js/surface.js +106 -132
  139. package/src/js/tab.js +6 -1
  140. package/src/js/tooltip.js +152 -53
  141. package/src/js/validation.js +1 -1
  142. package/src/css/components/surface.css +0 -49
  143. package/src/js/floating.js +0 -432
@@ -5,7 +5,8 @@
5
5
  - Use native `<details>` and `<summary>` for collapsible content.
6
6
  - Use the `name` attribute for exclusive accordions.
7
7
  - Supports any valid body element (`div`, `p`, `ul`, ...).
8
- - The toggle marker color is customizable with `--accordion-marker-color`; the marker icon comes from the shared `--icon-chevron` token.
8
+ - Three container treatments: the default common shell, `.flush` (bare separators, for embedding inside an existing surface), and `.separated` (independent items).
9
+ - The toggle marker color is customizable with `--accordion-marker-color`; it reinforces to the summary text color on hover, and the marker icon comes from the shared `--icon-chevron` token.
9
10
 
10
11
  ```html demo
11
12
  <div class="accordion">
@@ -34,6 +35,44 @@
34
35
  </div>
35
36
  ```
36
37
 
38
+ ## Variants
39
+
40
+ The default builds one raised shell around the whole group. `.flush` and `.separated` only change that chrome — they are integration modes between the component and its container, not decorative skins.
41
+
42
+ - **`flush`** — the ambient box disappears and only the item separators remain, so the group sits edge to edge inside a surface that already exists: a card, a drawer, a page section. A FAQ list without a box inside a box.
43
+
44
+ ```html demo
45
+ <div class="accordion flush">
46
+ <details open>
47
+ <summary>Flush keeps just the separators</summary>
48
+ <p>No shell: embed the group in a card, drawer, or page section.</p>
49
+ </details>
50
+
51
+ <details>
52
+ <summary>Edge to edge</summary>
53
+ <p>The summary and panel follow the surrounding surface's own gutter.</p>
54
+ </details>
55
+ </div>
56
+ ```
57
+
58
+ - **`separated`** — each `<details>` becomes its own card, for groups of standalone items.
59
+
60
+ ```html demo
61
+ <div class="accordion separated">
62
+ <details open>
63
+ <summary>Each item is its own card</summary>
64
+ <p>Standalone items share the same gap, border, radius, and raised surface.</p>
65
+ </details>
66
+
67
+ <details>
68
+ <summary>Still native details</summary>
69
+ <p>Exclusive <code>name</code> groups and per-item icons work exactly as in the base component.</p>
70
+ </details>
71
+ </div>
72
+ ```
73
+
74
+ The accordion owns its disclosure marker; the trigger content belongs to the markup. Item accents, per-item shadows, an underlined trigger label, and alternative markers stay application recipes, not framework variants.
75
+
37
76
  ## Exclusive groups
38
77
 
39
78
  ```html demo
@@ -77,4 +116,4 @@ The end marker is a shared token-based chevron; swapping it for a local icon is
77
116
  ## CSS hooks
78
117
 
79
118
  - `--accordion-radius` — outer corner radius.
80
- - `--accordion-marker-color` — color of the end marker; forced-colors mode overrides it to `CanvasText`.
119
+ - `--accordion-marker-color` — color of the end marker; it reinforces to the summary text color on hover, and forced-colors mode overrides it to `CanvasText`.
@@ -5,13 +5,14 @@
5
5
  - Supports intent colors.
6
6
  - Supports longer text and lists.
7
7
  - Links inherit alert color by default.
8
- - Alerts are soft by default. Use `.solid` or `.outline` when the message needs stronger or quieter emphasis.
8
+ - Alerts are soft by default. Use `.surface` for neutral chrome with the intent only in the ink, `.solid` or `.outline` when the message needs stronger or quieter emphasis, and `.inverted` for an inverse surface.
9
9
  - Use `<menu class="actions cluster">` for alert action lists.
10
10
  - Use `role="alert"` only when the alert is injected dynamically and should be announced.
11
11
  - Not a toast.
12
12
  - Could have simple or complex html content.
13
+ - A title and a description are plain siblings: the alert owns the small space between its direct content blocks, so neither needs a wrapper. Nested content keeps its own rhythm — wrap several paragraphs in `.prose`, or a differently spaced group in `.stack`, when the message needs a rhythm of its own.
13
14
  - Alerts may include a decorative leading icon. Use `.alert-icon` on the icon element; the rest of the content flows into the remaining text column.
14
- - Use `.sm` or `.lg` for density changes. The inline padding stays stable.
15
+ - Use `.compact` or `.spacious` for density changes. The inline padding stays stable.
15
16
  - Use `.alert-dismiss` for a compact dismiss button. It is a direct trailing child in standard alerts and lives inside `.alert-title` in admonitions. It uses the shared `--icon-close` mask and the `--dismiss` runtime command — no icon font or custom JS.
16
17
 
17
18
  Because alerts are soft by default, adding `.soft` to an intent (`.alert.soft.primary`,
@@ -21,26 +22,33 @@ itself needs to change, not `.soft`.
21
22
 
22
23
  ## Class reference
23
24
 
24
- | Class | Kind | Description |
25
- | ---------------- | ----------- | --------------------------------------------- |
26
- | `.alert` | Component | Inline status surface; soft by default. |
27
- | `.alert-icon` | Composition | Decorative leading icon, in the first column. |
28
- | `.alert-dismiss` | Modifier | Compact dismiss button. |
29
- | `.callout` | Variant | Neutral panel, thick accent leading edge. |
30
- | `.admonition` | Variant | Tinted title bar, body on the page surface. |
31
-
32
- `.alert-dismiss` draws itself with the `--icon-close` mask and acts through the
33
- `--dismiss` command.
34
- | `.alert-title` | Composition | Admonition title bar; hosts the dismiss button. |
35
- | `.alert-body` | Composition | Admonition body resting on the page surface. |
36
- | Shared intents | Intent | `.primary`, `.secondary`, `.success`, `.warning`, `.danger`. |
37
- | Shared variants | Variant | `.solid`, `.outline`, and `.surface` emphasis. |
38
- | `.sm` / `.lg` | Size | Density; inline padding stays stable. |
25
+ | Class | Kind | Description |
26
+ | ---------------- | ----------- | ----------------------------------------------- |
27
+ | `.alert` | Component | Inline status surface; soft by default. |
28
+ | `.alert-icon` | Composition | Decorative leading icon, in the first column. |
29
+ | `.alert-dismiss` | Modifier | Compact dismiss button. |
30
+ | `.alert-title` | Composition | Admonition title bar; hosts the dismiss button. |
31
+ | `.alert-body` | Composition | Admonition body on the page surface. |
32
+ | `.callout` | Variant | Leading-edge flag; owns the border geometry. |
33
+ | `.admonition` | Variant | Tinted title bar, body on the page surface. |
34
+ | Shared intents | Intent | `.primary`, `.secondary`, `.success`, … |
35
+ | Shared variants | Variant | `.solid`, `.outline`, `.surface`. |
36
+ | `.inverted` | Surface | Inverse surface, any intent. |
37
+ | Density contexts | Density | Descendant rhythm; inline padding stays stable. |
39
38
 
40
39
  ## Basic usage
41
40
 
41
+ `.surface` comes first on purpose: it keeps the theme's own chrome and puts the
42
+ intent in the ink alone, which is what most informational messages want. Add an
43
+ intent treatment when the color itself carries the meaning.
44
+
42
45
  ```html demo
43
46
  <div class="stack">
47
+ <div class="alert surface">
48
+ <i class="ti ti-info-circle alert-icon" aria-hidden="true"></i>
49
+ <div><strong>New message.</strong> 12 unread. <a href="#">Open inbox</a>.</div>
50
+ </div>
51
+
44
52
  <div class="alert success">
45
53
  <i class="ti ti-circle-check alert-icon" aria-hidden="true"></i>
46
54
  <div>Your changes have been saved. <a href="#">View activity</a>.</div>
@@ -91,16 +99,41 @@ itself needs to change, not `.soft`.
91
99
  </div>
92
100
  ```
93
101
 
102
+ ## Trailing action
103
+
104
+ The grid pins `.alert-icon` and `.alert-dismiss` to the outer columns. A
105
+ trailing link or button is content, not anatomy, so it lives in the text column:
106
+ wrap the row in a `.cluster` and push the two ends apart. Same recipe as any
107
+ split / spread row — there is no `.alert-action` class.
108
+
109
+ ```html demo
110
+ <div class="alert surface">
111
+ <i class="ti ti-info-circle alert-icon" aria-hidden="true"></i>
112
+ <div class="cluster justify-content-space-between">
113
+ <strong>New message!</strong>
114
+ <a class="btn sm outline" href="#">Open</a>
115
+ </div>
116
+ </div>
117
+ ```
118
+
94
119
  ## Variants
95
120
 
96
121
  ```html demo
97
122
  <div class="stack">
98
- <div class="alert danger sm" role="alert">
99
- I'm a small error
123
+ <div class="alert surface" role="alert">
124
+ I'm a surface alert — theme chrome, intent in the ink
125
+ </div>
126
+
127
+ <div class="alert inverted" role="alert">
128
+ I'm an inverted alert <a href="#">with a link</a>
100
129
  </div>
101
130
 
102
- <div class="alert danger lg" role="alert">
103
- I'm a large error
131
+ <div class="alert danger compact" role="alert">
132
+ I'm an error in a compact context
133
+ </div>
134
+
135
+ <div class="alert danger spacious" role="alert">
136
+ I'm an error in a spacious context
104
137
  </div>
105
138
 
106
139
  <div class="alert danger outline" role="alert">
@@ -120,11 +153,8 @@ Use `.alert-dismiss` to let a user remove an inline alert. The button is transpa
120
153
  ```html demo
121
154
  <div class="alert warning" id="warning-alert">
122
155
  <i class="ti ti-alert-triangle alert-icon" aria-hidden="true"></i>
123
-
124
- <div class="stack" style="--gap: var(--space-10)">
125
- <strong>Warning</strong>
126
- <p>Something needs your attention.</p>
127
- </div>
156
+ <strong>Warning</strong>
157
+ <p>Something needs your attention.</p>
128
158
 
129
159
  <button
130
160
  class="alert-dismiss"
@@ -156,22 +186,42 @@ In an admonition, place `.alert-dismiss` inside `.alert-title`; it rides the inl
156
186
 
157
187
  ## Callout
158
188
 
159
- Use `.callout` for a neutral panel with a thick accent border on the leading edge. Intent classes tint the border color.
189
+ `.callout` is a **leading-edge flag treatment**: it owns the border geometry and
190
+ nothing else, so the surface and the ink keep coming from the alert's own intent
191
+ and treatment. Bare is the soft panel, `.surface` the page surface, `.solid` a
192
+ filled one — and `.outline` has no fill and no other side, since the flag *is*
193
+ the border.
160
194
 
161
195
  ```html demo
162
196
  <div class="stack">
163
197
  <div class="alert callout">
164
198
  <strong>Note</strong>
165
- <p>This is a callout — a neutral panel with a thick accent border on the leading edge.</p>
199
+ <p>A neutral panel with a thick accent flag on the leading edge.</p>
166
200
  </div>
167
201
 
168
202
  <div class="alert warning callout" role="alert">
169
203
  <strong>Heads up</strong>
170
- <p>The border color follows the intent. No other borders are drawn.</p>
204
+ <p>The intent tints the panel and the flag together.</p>
205
+ </div>
206
+
207
+ <div class="alert success callout surface">
208
+ <strong>On the page surface</strong>
209
+ <p>The flag keeps the intent, the panel drops the tint.</p>
171
210
  </div>
172
211
  </div>
173
212
  ```
174
213
 
214
+ Tune the flag with `--alert-border-inline-start-width` and
215
+ `--alert-border-inline-start-color`; `--alert-radius: 0` turns it into a
216
+ full-bleed notice.
217
+
218
+ ```html demo
219
+ <div class="alert danger callout" style="--alert-radius: 0">
220
+ <i class="ti ti-user-x alert-icon" aria-hidden="true"></i>
221
+ <div>Your request to join the team is denied.</div>
222
+ </div>
223
+ ```
224
+
175
225
  ## Admonition
176
226
 
177
227
  An admonition is a structured box with a tinted title bar, an optional icon, and body content on the page surface — like the `!!! note` callouts in mkdocs. Use `.alert-title` for the header and `.alert-body` for the content. Intent classes tint the title bar background and the border.
@@ -202,7 +252,7 @@ An admonition is a structured box with a tinted title bar, an optional icon, and
202
252
 
203
253
  ## CSS hooks
204
254
 
205
- - `--alert-pad-inline` — inline padding. Stays stable across `.sm`/`.lg`.
255
+ - `--alert-pad-inline` — inline padding. Stays stable across density contexts.
206
256
  - `--alert-pad-block` — block padding.
207
257
  - `--alert-font-size` — base font size.
208
258
  - `--alert-icon-size` — size of a leading `.alert-icon`.
@@ -5,6 +5,12 @@
5
5
  Use one `.app-nav` landmark for the application's primary destinations. Links
6
6
  remain links, and `aria-current="page"` is the only current-page state.
7
7
 
8
+ Reach for `.app-nav` only as part of a persistent application shell: it exists
9
+ as a direct child of `.app-layout`, which turns the landmark from a bottom bar
10
+ into side navigation. A site or webapp header with normal scrolling stays
11
+ `.navbar` — `.app-nav` is not a stacked-icon variant of the horizontal bar. See
12
+ [Navbar](navbar.md).
13
+
8
14
  **Related terms:** tab bar, bottom navigation, bottom nav, navigation rail, side navigation.
9
15
 
10
16
  ```html demo
@@ -12,12 +12,12 @@
12
12
 
13
13
  ## Class reference
14
14
 
15
- | Class | Kind | Description |
16
- | --------------- | ----------- | --------------------------------------- |
17
- | `.avatar` | Component | Initials or image in a circular box. |
18
- | `.avatar-stack` | Composition | Overlapping avatar group. |
19
- | `.badge:empty` | Composition | Status dot, at the bottom-end corner. |
20
- | `.sm` / `.lg` | Size | Density; also rescales `.avatar-stack`. |
15
+ | Class | Kind | Description |
16
+ | --------------- | ----------- | -------------------------------------------- |
17
+ | `.avatar` | Component | Initials or image in a circular box. |
18
+ | `.avatar-stack` | Composition | Overlapping avatar group. |
19
+ | `.badge:empty` | Composition | Status dot, at the bottom-end corner. |
20
+ | `.sm` / `.lg` | Size | Optical size; also rescales `.avatar-stack`. |
21
21
 
22
22
  `.avatar` works on `div`, `a` and `button`. The status dot is an empty
23
23
  `.badge` inside an `.avatar`, and needs an `aria-label` of its own.
@@ -4,17 +4,18 @@
4
4
 
5
5
  - Supports intent colors.
6
6
  - Soft by default. Use `.solid` for counters and notification badges, or `.outline` for quieter emphasis.
7
- - Dots stay solid regardless of variant.
8
- - Use `.sm` or `.lg` for compact density changes.
7
+ - Empty badges are solid status dots: visual variants such as `.soft` and `.outline` do not change their fill.
8
+ - Use `.sm` or `.lg` to scale the badge locally.
9
+ - Use `.compact` or `.spacious` on a context to change geometry without changing the label or icon size.
9
10
  - Can be used inline in headings.
10
11
  - Can be used as a count badge.
11
12
  - Can be used as a stable dot badge when empty and given an accessible name.
12
13
  - Empty badges render as dots. The element must be truly empty: no text and no whitespace.
13
14
 
14
15
  A badge is **content-sized**: it never stretches to fill its container, even as a
15
- direct child of `.stack` (where flex children otherwise stretch). Use
16
- `inline-size: 100%` — or the optional `.inline-size-full` utility — when a
17
- full-width badge is intentional.
16
+ direct child of `.stack` (where flex children otherwise stretch), and a flex
17
+ parent never compresses it (`flex: none`). Use `inline-size: 100%` — or the
18
+ optional `.inline-size-full` utility — when a full-width badge is intentional.
18
19
 
19
20
  **Related terms:** chip, tag, pill, removable tag.
20
21
 
@@ -24,9 +25,10 @@ full-width badge is intentional.
24
25
  | --------------- | ----------- | ----------------------------------------- |
25
26
  | `.badge` | Component | Compact label; soft by default. |
26
27
  | `.badge:empty` | Composition | Truly-empty badge renders as a solid dot. |
28
+ | `.dot` | Composition | Status dot inside a badge. |
27
29
  | Shared intents | Intent | `.primary`, `.secondary`, `.success`, … |
28
30
  | Shared variants | Variant | `.solid`, `.outline`, `.surface`. |
29
- | `.sm` / `.lg` | Size | Compact density. |
31
+ | `.sm` / `.lg` | Size | Smaller or larger optical scale. |
30
32
 
31
33
  The shared intents are `.primary`, `.secondary`, `.success`, `.warning` and
32
34
  `.danger`. The variants set emphasis: `.solid` is filled, `.outline` bordered,
@@ -42,6 +44,9 @@ The shared intents are `.primary`, `.secondary`, `.success`, `.warning` and
42
44
  <span class="badge danger">Danger</span>
43
45
  <span class="badge success outline">Outline success</span>
44
46
  <span class="badge warning soft">Soft warning</span>
47
+ <span class="badge primary solid">Solid primary</span>
48
+ <span class="badge success solid">Solid success</span>
49
+ <span class="badge danger solid">Solid danger</span>
45
50
  ```
46
51
 
47
52
  ## In a title
@@ -73,6 +78,29 @@ The shared intents are `.primary`, `.secondary`, `.success`, `.warning` and
73
78
  An autonomous dot conveys state without visible text, so give it an accessible
74
79
  name.
75
80
 
81
+ For a dot beside a label, put the shared `.dot` utility inside the badge. It
82
+ paints with `currentColor`, so it follows the badge ink instead of needing the
83
+ intent class repeated on it.
84
+
85
+ ```html demo
86
+ <span class="badge warning">
87
+ <span class="dot" aria-hidden="true"></span>
88
+ In progress
89
+ </span>
90
+ <span class="badge danger">
91
+ <span class="dot" aria-hidden="true"></span>
92
+ Blocked
93
+ </span>
94
+ <span class="badge success">
95
+ <span class="dot" aria-hidden="true"></span>
96
+ Completed
97
+ </span>
98
+ ```
99
+
100
+ Custom status or category dots define a custom intent (`--intent` /
101
+ `--intent-fg`); `--ui-*` controls treatment, while empty dots intentionally
102
+ remain solid.
103
+
76
104
  ## Color marker
77
105
 
78
106
  Use an empty badge as a compact intent-colored marker in legends and status
@@ -87,9 +115,64 @@ Regular
87
115
  ## Size variants
88
116
 
89
117
  ```html demo
90
- <span class="badge success sm">Small Success</span>
91
- <span class="badge success">Regular Success</span>
92
- <span class="badge success lg">Large Success</span>
118
+ <span class="badge success sm">Small</span>
119
+ <span class="badge success">Default</span>
120
+ <span class="badge success lg">Large</span>
121
+ ```
122
+
123
+ ## Density
124
+
125
+ Density changes the pill geometry without scaling its label or icon.
126
+
127
+ ```html demo
128
+ <span class="compact"><span class="badge success">Compact</span></span>
129
+ <span><span class="badge success">Default</span></span>
130
+ <span class="spacious"><span class="badge success">Spacious</span></span>
131
+ ```
132
+
133
+ ## With an icon
134
+
135
+ Decorative SVG, image, or `[aria-hidden="true"]` children follow
136
+ `--badge-icon-size`.
137
+
138
+ ```html demo
139
+ <span class="badge success">
140
+ <i class="ti ti-rosette-discount-check" aria-hidden="true"></i>
141
+ Verified
142
+ </span>
143
+ <span class="badge warning">
144
+ <i class="ti ti-clock" aria-hidden="true"></i>
145
+ Pending
146
+ </span>
147
+ <span class="badge danger solid">
148
+ <i class="ti ti-alert-circle" aria-hidden="true"></i>
149
+ Failed
150
+ </span>
151
+ ```
152
+
153
+ ## Loading status
154
+
155
+ A decorative spinner follows the badge color and optical size.
156
+
157
+ ```html demo
158
+ <span class="badge danger sm">
159
+ <span class="spinner" aria-hidden="true"></span>
160
+ Deleting
161
+ </span>
162
+ <span class="badge sm">
163
+ Generating
164
+ <span class="spinner" aria-hidden="true"></span>
165
+ </span>
166
+ ```
167
+
168
+ ## Custom sizing
169
+
170
+ Override the existing hooks when the three-step scale does not fit the content.
171
+
172
+ ```html demo
173
+ <span class="badge primary" style="--badge-size: 2rem; --badge-font-size: var(--font-size-md);">
174
+ Prominent
175
+ </span>
93
176
  ```
94
177
 
95
178
  ## Removable tag pattern
@@ -98,17 +181,17 @@ Use `.badge soft` for tag visuals. Add a direct dismiss button only when the tag
98
181
  For a compact action or filter, use `.btn.sm` instead; badges describe content
99
182
  and must not be turned into toggle controls merely to obtain a compact shape.
100
183
 
184
+ Leave the dismiss button empty: it paints its own X, so the pattern needs no
185
+ icon font and no text glyph. Put your own icon inside it and that content is
186
+ used instead.
187
+
101
188
  ```html demo
102
189
  <span class="badge primary soft">
103
190
  Design
104
- <button type="button" aria-label="Remove Design">
105
- <i class="ti ti-x" aria-hidden="true"></i>
106
- </button>
191
+ <button type="button" aria-label="Remove Design"></button>
107
192
  </span>
108
193
  <span class="badge primary soft">
109
- <button type="button" aria-label="Remove Design">
110
- <i class="ti ti-x" aria-hidden="true"></i>
111
- </button>
194
+ <button type="button" aria-label="Remove Design"></button>
112
195
  Design
113
196
  </span>
114
197
  ```
@@ -119,4 +202,6 @@ and must not be turned into toggle controls merely to obtain a compact shape.
119
202
  - `--badge-size` — minimum block size; also the square size of an `:empty` dot badge.
120
203
  - `--badge-dot-size` — size of an `:empty` dot badge.
121
204
  - `--badge-font-size` — label font size.
122
- - `--badge-pad-x` — inline padding.
205
+ - `--badge-icon-size` — decorative child size; `1em` follows the label by default.
206
+ - `--badge-pad-x` — inline padding. Derived from `--badge-size`, so it stays proportional to the pill; set it to opt out.
207
+ - `--badge-dismiss-icon-size` — size of the X painted by an empty dismiss button.
@@ -110,21 +110,29 @@ Always name it with an `aria-label` since there is no visible text.
110
110
 
111
111
  ### Button groups
112
112
 
113
- Join adjacent buttons with `.join`. The joined group is not a new component —
114
- the buttons keep their own variants.
113
+ Join adjacent buttons with `.join`. The joined group is not a new component:
114
+ each button keeps its own classes, and `.join` only reshapes the outer corners
115
+ and collapses the shared edges.
115
116
 
116
117
  ```html demo
117
- <div class="join" role="group" aria-label="Text alignment">
118
- <button class="btn" type="button">Left</button>
119
- <button class="btn outline" type="button">Center</button>
120
- <button class="btn soft" type="button">Right</button>
118
+ <div class="join" role="group" aria-label="Row actions">
119
+ <button class="btn outline" type="button">Edit</button>
120
+ <button class="btn outline" type="button">Duplicate</button>
121
+ <button class="btn outline" type="button">Archive</button>
121
122
  </div>
122
123
  ```
123
124
 
125
+ Keep one variant family inside a group. Because each button keeps its own
126
+ classes, nothing stops `.btn`, `.btn outline` and `.btn soft` from sitting side
127
+ by side — but three fills and three border treatments in one shape read as
128
+ unrelated controls that happen to touch, not as one unit. Change the variant
129
+ only to carry meaning: [Toggle](#toggle) marks the active segment with a solid
130
+ button among outlines, which is the pattern a segmented control wants.
131
+
124
132
  ## Sizes
125
133
 
126
- Prefer `.sm` and `.lg` over setting sizes directly. Density variants never
127
- change typography.
134
+ Prefer `.sm` and `.lg` over setting sizes directly. They scale control geometry
135
+ and typography together; `.compact` and `.spacious` only change density.
128
136
 
129
137
  ```html demo
130
138
  <div class="cluster">
@@ -4,14 +4,14 @@ Flexible content container with optional header, body, and footer regions, plus
4
4
 
5
5
  ## Class reference
6
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
- | `.surface` | Variant | The page surface; intent in the text only. |
13
- | `.inverted` | Surface modifier | Inverse surface treatment. |
14
- | `.compact` | Variant | Tighter padding for dense contexts. |
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
+ | `.surface` | Variant | The page surface; intent in the text only. |
13
+ | `.inverted` | Surface modifier | Inverse surface treatment. |
14
+ | `.compact` | Density | Tighter padding and compact descendant context. |
15
15
 
16
16
  `.surface` is a shared variant: it paints the page surface instead of
17
17
  `--surface-raised` and leaves the intent to the text.
@@ -88,7 +88,7 @@ colored headers, or footers.
88
88
  <p class="muted">For growing products</p>
89
89
  </hgroup>
90
90
  <p>
91
- <span style="font-size: 2rem; font-weight: var(--font-weight-strong); line-height: 1">$24</span>
91
+ <span style="font-size: 2rem; font-weight: var(--font-weight-semibold); line-height: 1">$24</span>
92
92
  <span class="muted">/ user / month</span>
93
93
  </p>
94
94
  </header>
@@ -220,4 +220,4 @@ treatments on either side of it.
220
220
  - `--card-radius` — corner radius.
221
221
  - `--card-max-inline-size` — maximum width.
222
222
  - `--card-pad` — inner padding; also drives the negative offsets that let a `.bleed` child reach the card edge. `.compact` lowers it.
223
- - `--card-gap` — space between direct children of a bare card. A composed layout primitive owns its own gap instead. `.compact` does not change this hook.
223
+ - `--card-gap` — space between direct children of a bare card. A composed layout primitive owns its own gap instead.
@@ -167,7 +167,8 @@ Use `modal scrollable` when the header and footer should stay visible while the
167
167
  dialog body scrolls. Modal dialogs lock page scroll while a modal is open: the
168
168
  runtime writes `html.has-modal-open`, and the stylesheet applies `overflow:
169
169
  hidden` (and reserves the scrollbar gutter with `scrollbar-gutter: stable` when
170
- one was present).
170
+ one was present). The height cap follows the small viewport, so the panel keeps
171
+ a stable size while mobile browser chrome expands or collapses.
171
172
 
172
173
  ```html demo
173
174
  <button class="btn"
@@ -213,8 +214,15 @@ one was present).
213
214
 
214
215
  ## Overlays inside modals
215
216
 
216
- Flyouts and tooltips opened from inside a modal dialog are mounted inside the
217
- dialog so they stay in the same top-layer context.
217
+ Flyouts and tooltips opened from inside a modal dialog stay exactly where they
218
+ are authored. The runtime promotes them to the top layer instead of moving
219
+ them, which is what keeps them inside every scope that reaches them by
220
+ inheritance.
221
+
222
+ Author them inside the dialog. Promotion paints an element above a modal, but
223
+ it does not lift it out of the modal's inertness — that is computed on the DOM,
224
+ not on paint order — so an overlay authored outside the dialog would be
225
+ promoted above it and still unclickable.
218
226
 
219
227
  ```html demo
220
228
  <button class="btn"
@@ -295,7 +303,7 @@ Available options:
295
303
  ## Browser support
296
304
 
297
305
  Actual relies on the native `<dialog>` API in its supported JavaScript range
298
- (Safari 15.4+, Firefox 98+, Chromium 99+). No dialog polyfill or fallback shim
306
+ (Safari 17+, Firefox 125+, Chromium 116+). No dialog polyfill or fallback shim
299
307
  is shipped.
300
308
 
301
309
  ## Animation
@@ -306,7 +314,7 @@ remain in the top layer while `display` and `overlay` transition out. Browsers
306
314
  without that support keep native close behavior.
307
315
 
308
316
  The open dialog root intentionally ends at `transform: none`; fixed flyouts and
309
- tooltips mounted inside a modal dialog rely on viewport coordinates.
317
+ tooltips authored inside a modal dialog rely on viewport coordinates.
310
318
 
311
319
  ### View transition
312
320
 
@@ -362,7 +370,9 @@ Keep the button a direct child of `dialog.modal` so the scrolling content
362
370
 
363
371
  ## CSS hooks
364
372
 
365
- - `--modal-size` — maximum dialog width.
373
+ - `--modal-size` — maximum dialog width. Fallback-only, so a class on the
374
+ dialog or an inherited value both reach it. A dialog is shrink-to-fit: a
375
+ composition that must fill this width sets `inline-size` as well.
366
376
  - `--dialog-viewport-gap` — distance kept between the dialog and the viewport edges.
367
377
  - `--dialog-icon-size` — diameter of the `.dialog-icon` circle.
368
378
  - `--dialog-icon-glyph-size` — size of the glyph centered inside `.dialog-icon`.
@@ -96,7 +96,7 @@ does not close automatically after an action, on outside click, or on Escape;
96
96
  add application behavior only when the product requires those policies.
97
97
 
98
98
  Each `.fab-action` keeps its `.fab-label` and secondary button on one compact
99
- line. The example uses the button's existing `.lg` density for 44px secondary
99
+ line. The example uses the button's existing `.lg` size for 44px secondary
100
100
  actions and its `--btn-min-size` hook for a dominant 56px trigger. Size still
101
101
  belongs to Button rather than introducing FAB-specific size modifiers.
102
102
  Unlike the plain FAB, the speed dial trigger takes no icon: FAB owns it as a
@@ -120,5 +120,6 @@ two states stay visually identical in size and stroke.
120
120
  - `--fab-gap` — gap between actions and between the trigger and action list.
121
121
  - `--fab-icon-size` — size of the speed dial toggle's open and close markers.
122
122
 
123
- FAB is hidden in print and uses `--z-menu`, leaving tooltips and status UI above
124
- it. Dialogs remain in the browser's top layer.
123
+ FAB uses `--z-menu`, leaving `status-bar` above it on the scale. Open flyouts
124
+ and tooltips are promoted to the top layer and paint above it whatever their
125
+ number. Dialogs remain in the browser's top layer.