@rcarls/rc-theme-material 0.5.0 → 0.7.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 (57) hide show
  1. package/CHANGELOG.md +600 -0
  2. package/DESIGN.md +1399 -0
  3. package/README.md +138 -5
  4. package/bridge.css +150 -55
  5. package/components/accordion.css +43 -157
  6. package/components/adaptive-menu.css +123 -0
  7. package/components/app-bar.css +49 -7
  8. package/components/bottom-sheet.css +10 -7
  9. package/components/button.css +215 -2
  10. package/components/card.css +2 -0
  11. package/components/carousel.css +23 -0
  12. package/components/chip-group.css +15 -0
  13. package/components/chip.css +12 -1
  14. package/components/combobox.css +68 -14
  15. package/components/dialog.css +77 -15
  16. package/components/disclosure.css +128 -84
  17. package/components/field.css +566 -0
  18. package/components/icons.css +48 -6
  19. package/components/list-item.css +142 -32
  20. package/components/listbox.css +5 -4
  21. package/components/markdown-editor.css +62 -35
  22. package/components/menu-button.css +105 -1
  23. package/components/menu.css +32 -16
  24. package/components/menubar.css +4 -1
  25. package/components/modes.css +36 -17
  26. package/components/navigation-bar.css +3 -5
  27. package/components/navigation-rail.css +5 -7
  28. package/components/popover.css +50 -0
  29. package/components/progress.css +15 -0
  30. package/components/range-slider.css +8 -3
  31. package/components/scroller.css +7 -0
  32. package/components/search-bar.css +12 -2
  33. package/components/segmented-button.css +2 -28
  34. package/components/select.css +106 -14
  35. package/components/splitter.css +4 -1
  36. package/components/switch.css +9 -1
  37. package/components/textarea.css +13 -3
  38. package/components/toolbar.css +2 -1
  39. package/components/tooltip.css +12 -0
  40. package/components/transfer-list.css +5 -1
  41. package/components/virtual-canvas.css +4 -1
  42. package/components/virtual-scroller.css +7 -0
  43. package/components.css +11 -1
  44. package/constraints/material.json +99 -0
  45. package/css-components/button.css +66 -0
  46. package/css-components/card.css +14 -0
  47. package/css-components/chip-group.css +9 -0
  48. package/css-components/chip.css +80 -0
  49. package/css-components/disclosure.css +25 -0
  50. package/css-components/list.css +34 -0
  51. package/css-components/select.css +20 -0
  52. package/css-components/textarea.css +22 -0
  53. package/css-components.css +31 -0
  54. package/defaults.css +329 -14
  55. package/native.css +258 -0
  56. package/package.json +21 -2
  57. package/state-layer.css +5 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,605 @@
1
1
  # @rcarls/rc-theme-material
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f31cca3: Add `--rc-bottom-sheet-handle-offset` to position the handle indicator within its target. It
8
+ defaults to `50%`, which keeps the indicator centered. Set a length to keep the indicator in its
9
+ own row at the top of a handle that also holds the sheet's title.
10
+ - 079e025: Standardize component styling contracts for the breaking 0.7 release.
11
+
12
+ BREAKING CHANGE: Rename the Markdown editor's `--rme-*` properties to
13
+ `--rc-markdown-editor-*`, `--rc-app-bar-background` to `--rc-app-bar-bg`,
14
+ `--rc-textarea-radius` to `--rc-textarea-border-radius`, the transfer-list
15
+ `--rc-transfer-list-panel-*` properties to `--rc-transfer-list-listbox-*`,
16
+ `--rc-chip-group-webkit-scrollbar-display` to
17
+ `--rc-chip-group-scrollbar-display`, and `--rc-text` to `--rc-field-text`.
18
+ Compatibility aliases are intentionally not provided.
19
+
20
+ BREAKING CHANGE: Replace `--rc-select-chip-padding-inline` and
21
+ `--rc-combobox-chip-padding-inline` with explicit `*-padding-inline-start` and
22
+ `*-padding-inline-end` tokens. Generated removable chips now reserve the full
23
+ remove target and its edge offset, so their indicator cannot overlap label text.
24
+
25
+ Add canonical app-bar elevation, transfer-list listbox radius, and textarea
26
+ line-action tokens. Add logical `rc-chip` inline-padding properties so themes
27
+ can implement Material's icon-aware spacing without overriding authored child
28
+ styles. Make `rc-field` consume the shared semantic token layer,
29
+ and place the `rc-chip` and `rc-search-bar` light-DOM structural styles in the
30
+ `rc-base` cascade layer so normal consumer rules override them.
31
+
32
+ Prevent decorative, `aria-hidden` trailing list content from intercepting a
33
+ whole-row action target, and keep segmented-list item geometry from leaking
34
+ into nested standard lists.
35
+
36
+ Remove unused Material navigation-rail toggle tokens and obsolete list-item
37
+ theme tokens. Register the segmented-button private theme seam and enforce
38
+ token ownership, documentation, removed-name, selector-budget, and cascade
39
+ layer contracts through the component architecture audit.
40
+
41
+ - 4341311: Add reusable fullscreen dialogs and declarative dialog popup mode to `rc-select` and
42
+ `rc-combobox`. Dialog selection and creation are staged until Done, while close and Escape
43
+ discard the draft. Fullscreen surfaces follow the visual viewport under browser zoom and
44
+ software keyboards, and anchored popups now clamp to the visual viewport.
45
+ - 5a7a1dd: `rc-dialog` gains `variant="side"`, a modal side sheet. The surface docks to the inline end at
46
+ full block size, pads every edge for the physical safe-area insets, and rounds only its start
47
+ corners. Like the fullscreen variant, it never moves or resizes. Theme it with
48
+ `--rc-dialog-side-inline-size`, `--rc-dialog-side-background`, `--rc-dialog-side-radius`, and
49
+ `--rc-dialog-side-shadow`. A landscape phone can now show a sheet's content beside the page
50
+ instead of in a bottom sheet that leaves only a strip of content visible.
51
+
52
+ A theme or consumer can now set a standard dialog's preferred width through
53
+ `--rc-dialog-inline-size`, which defaults to `fit-content`. Set it to `100%` for a dialog with
54
+ fluid content, such as a search field or a list, which otherwise shrinks to its minimum width.
55
+
56
+ The Material theme maps the side sheet to Material 3: `surface-container-low`, large leading
57
+ corners, and level 1 elevation. Its design guide documents side sheets, task dialog sizing, and
58
+ full-screen dialogs when the window is compact in either dimension. The React and Solid typings
59
+ accept the new variant.
60
+
61
+ - 2c7c80a: Give `rc-dialog` a surface styling contract.
62
+
63
+ It exposed only `--rc-dialog-scrim`, so both themes drew the surface by selecting the native
64
+ `<dialog>` directly. It now installs a light-DOM base stylesheet, the same pattern as `rc-button`
65
+ and `rc-disclosure`, and exposes minimum and maximum inline and block bounds, padding, border, radius, background,
66
+ foreground, and shadow, plus fullscreen-specific padding and background for the two values that
67
+ variant genuinely needs of its own.
68
+
69
+ Fullscreen geometry, meaning position, size, margin, radius, and shadow, stays structural rather
70
+ than something a theme sets: filling the visual viewport is what keeps the surface correct under browser zoom
71
+ and a software keyboard.
72
+
73
+ Material's explicit block bound with `overflow: hidden` moved into the base layer rather than
74
+ staying a theme value. It exists because Chromium does not reliably clip a scrolling element's
75
+ own border radius at the scroll boundary, which is a correctness fix every theme needs.
76
+
77
+ `--rc-dialog-visual-viewport-left`, `-top`, `-width`, and `-height` are no longer documented as
78
+ theme properties. They are geometry the component writes while a fullscreen dialog is open:
79
+ readable if something inside the dialog needs the same measurements, but setting them does not
80
+ move the dialog. They are candidates for private `--_rc-dialog-*` names in a future revision.
81
+
82
+ - 4b9bfe6: Give `rc-disclosure` and `rc-accordion` a public styling contract.
83
+
84
+ Both were styled by targeting the native `<details>` element directly, so neither exposed a
85
+ single `--rc-*` property and no theme could change them without rewriting theme CSS. They now
86
+ follow the light-DOM base pattern `rc-button` and `rc-listbox` already use: `rc-disclosure`
87
+ installs one structural stylesheet per containing `Document` or `ShadowRoot`, in `@layer rc-base`
88
+ behind a `data-rc-light-dom-base` sentinel, reading documented properties with UA-like defaults.
89
+
90
+ One recipe covers both supported child forms, a bare `<details>` inside `rc-accordion` and one
91
+ wrapped in `rc-disclosure`, so neither theme repeats the panel rules. `rc-accordion` owns only
92
+ `--rc-accordion-gap`.
93
+
94
+ Motion is opt-in. `--rc-disclosure-duration` defaults to `0ms`, so a disclosure with no theme keeps
95
+ the platform's snap-open behavior, and the height animation runs on `::details-content` behind a
96
+ `@supports selector()` check. This replaces Material's `60rem` `max-block-size` ceiling, which
97
+ clipped content taller than the guess and made every non-summary child its own animation unit.
98
+
99
+ **Fixes a missing expand affordance in the Material theme.** It set `display: grid` on the
100
+ `<summary>` and then styled `summary::marker`. Any `display` other than `list-item` drops the
101
+ marker box, so that rule styled nothing and the theme drew no replacement: a Material disclosure
102
+ had no disclosure triangle at all. The base layer never sets `display` on a summary, so the
103
+ marker survives. A theme may still change it, as Substrate does, but only alongside a
104
+ replacement affordance.
105
+
106
+ - 19278d4: Group several native controls into one `rc-field` with a direct `<fieldset>`. Its `<legend>` names
107
+ the group and shows as the field label, each control keeps its own accessible name, and supporting
108
+ text describes the fieldset. The first text-like input or textarea is the primary control behind
109
+ `control`, `focus()`, and `data-populated`; focus moving between grouped controls keeps the field
110
+ focused; and `data-disabled`, `data-required`, and `data-invalid` reflect the whole group. New
111
+ read-only `group` and `controls` properties and a `data-group` host attribute support the mode.
112
+
113
+ The primary control grows and other controls attach before or after it. In Material, the legend uses
114
+ the floating label mechanics: it rests on the input line while the group is idle and its primary
115
+ input empty, and floats on focus or once that input has a value; a group with a control before its
116
+ primary input keeps it floated. Grouped placeholders wait for focus. Substrate colors an invalid
117
+ group's legend, and Win31 spaces it like a single field's label.
118
+
119
+ - 6ec0857: Add `ordered` to `rc-list`. Visible items in an ordered list receive `aria-posinset` and
120
+ `aria-setsize` so assistive technology reports their position; no counters render, and authored
121
+ positions from a rendered slice of a longer list are kept.
122
+
123
+ Add an expandable `details` region to `rc-list-item`. A button marked
124
+ `data-rc-list-item-toggle` toggles it; the item wires `aria-expanded`, `aria-controls`, and the
125
+ region's `hidden` state, supports controlled `expanded` and uncontrolled `default-expanded`
126
+ state, and fires `rc-list-item-toggle`. Material styles the region as list supporting text.
127
+
128
+ - c4ee38f: Draw Material disclosures as expandable list items. The summary now centers its
129
+ title in the 56px row and replaces the native disclosure triangle with a
130
+ trailing chevron that points down while closed and turns to point up while open,
131
+ the Android expandable-list-item affordance. The chevron keeps that direction in
132
+ RTL and vertical writing modes and stops turning under reduced motion.
133
+
134
+ Accordions now group their panels like a segmented `rc-list`: a 2px gap instead
135
+ of 8px, no outline, extra-small inner corners, and extra-large logical outer
136
+ corners on the first and last panel. A standalone `rc-disclosure` keeps its
137
+ outlined, uniformly rounded panel. This also removes a duplicate
138
+ `--rc-accordion-gap` declaration in `disclosure.css` that the accordion rule
139
+ always overrode.
140
+
141
+ - 873592e: Add four directional motion tokens to the shared base contract:
142
+ `--rc-motion-effects-easing-enter`/`-exit` and
143
+ `--rc-motion-spatial-easing-enter`/`-exit`. An opening element decelerates
144
+ into place; a closing one accelerates out. There are no matching enter/exit
145
+ duration tokens; pair `-easing-exit` with an existing `-duration-fast` token
146
+ instead.
147
+
148
+ All three themes map the new tokens: Material pairs them with its
149
+ standard/emphasized decelerate and accelerate curves, Substrate keeps its one
150
+ curve as the enter curve and adds a generic accelerate shape for exit
151
+ (refined further once Substrate gets its own full spatial/effects scale), and
152
+ `rc-theme-win31` declares all four as `step-end`, matching its zero-motion
153
+ contract, so an application that loads the shared base tokens alongside
154
+ `rc-theme-win31` does not inherit the base defaults' real easing curves for
155
+ these two directions.
156
+
157
+ - 7c952e2: `rc-theme-material` and `rc-theme-substrate` refine `prefers-reduced-motion:
158
+ reduce` from removing every transition and animation to removing only
159
+ spatial motion; effects motion (color and opacity) is kept, shortened.
160
+ Vestibular harm, the reason for the preference, comes from movement across
161
+ the visual field; a color or opacity change doesn't trigger it, and removing
162
+ it too was also removing motion that aids comprehension.
163
+
164
+ Material's effects duration shortens to 50/70/100&nbsp;ms (from its full
165
+ 150/200/300&nbsp;ms scale); Substrate's to 40/55/70&nbsp;ms, scaled down from
166
+ its own faster 100/160/240&nbsp;ms base. `rc-theme-win31` needs no change: it
167
+ already declares every duration at zero unconditionally.
168
+
169
+ Several component recipes that bypassed the shared motion scale entirely,
170
+ referencing a raw duration primitive directly, are rewired to the
171
+ appropriate effects or spatial token so this refinement actually reaches
172
+ them: Material's `rc-disclosure`, `rc-list-item`, `rc-bottom-sheet`'s snap
173
+ duration, `rc-button`'s ripple, and its shared state-layer opacity fade;
174
+ Substrate's `rc-listbox`, `rc-splitter`, and `rc-disclosure`. Most land on
175
+ their existing value exactly; `rc-button`'s ripple duration normalizes from
176
+ 450&nbsp;ms to 500&nbsp;ms, the nearest real spatial tier.
177
+
178
+ - c62d107: Let opt-in native theme styles reach consumer controls inside RC containers while
179
+ component recipes retain their themed presentation. Apply the same presentation
180
+ boundary and `data-rc-native="off"` subtree opt-out in Material, Substrate, and
181
+ Windows 3.1.
182
+
183
+ Native controls inside an RC host may now gain theme styling when that host does
184
+ not provide their appearance. Add `data-rc-native="off"` to content that should
185
+ keep its own styles, such as a third-party widget.
186
+
187
+ - 622c5c9: Add independent opt-in `native.css` and CSS-only `css-components.css` entrypoints to the
188
+ Material, Substrate, and Windows 3.1 themes. Native controls can use the theme presentation
189
+ without registration, while documented class recipes style common HTML controls and static
190
+ card, list, chip-group, and disclosure markup without changing behavior.
191
+
192
+ Native styles stop at RC controls that own their native children. Add
193
+ `data-rc-native="off"` to an element to keep native styles off it and its subtree.
194
+
195
+ - f1ca82d: Add an anchored, non-modal popover package with a Material rich-tooltip recipe. Share native Popover API visibility and fallback behavior across existing popup components.
196
+ - 687a9be: Add shared popup surface tokens: `--rc-popup-background`, `--rc-popup-color`,
197
+ `--rc-popup-border`, `--rc-popup-radius`, `--rc-popup-shadow`, and
198
+ `--rc-popup-padding-block`. Menus, adaptive-menu popups, and select and
199
+ combobox listboxes read them before their own fallbacks. Themes set them at the
200
+ theme root, so popups rendered inside other shadow roots keep the theme's
201
+ surface. Select and combobox add `--rc-*-listbox-background` and
202
+ `--rc-*-listbox-color`.
203
+
204
+ Breaking: popup surfaces no longer fall back to `--rc-control-radius`. Set
205
+ `--rc-popup-radius` (or the per-component radius token) to change popup
206
+ corners. The Material, Substrate, and Win31 themes no longer set per-component
207
+ popup surface tokens such as `--rc-menu-radius` or
208
+ `--rc-adaptive-menu-popup-background`; override the `--rc-popup-*` tokens
209
+ instead. Material select and combobox listboxes now use the menu container
210
+ color, Material forced-colors popups gain a border, and Substrate listboxes use
211
+ the menu shadow and padding. Material retains its two-layer adaptive-menu popup
212
+ shadow through a component token while other popups continue using the shared
213
+ shadow.
214
+
215
+ - c130173: Add pointer and keyboard reordering to `rc-list`.
216
+
217
+ Set `reorderable` and give each item a native `<button data-rc-reorder-handle>`. People can drag
218
+ a handle, and the items it passes shift out of the way while the nearest scroll container
219
+ scrolls near its edges. On touch and pen, a long press on an item also starts a drag, while
220
+ movement before activation remains available for scrolling. Or they can focus a handle and use
221
+ Space, the block-axis arrow keys, Home, End, and Escape. Each step is announced, focus stays on
222
+ the moved item's handle, and geometry and keys follow the writing mode. `reorderable` implies
223
+ `ordered`.
224
+
225
+ Each committed move fires a cancelable `rc-list-reorder` event with `{ item, from, to }`. Left
226
+ alone, the list moves the node itself; a framework that renders the items cancels the event and
227
+ reorders its own data. `reorderMessages` overrides the announcements and the handle hint.
228
+
229
+ `rc-common` gains the `ReorderController` behind it and a `LiveAnnouncer` live-region helper.
230
+ `rc-theme-material` styles the lifted item with the dragged elevation, surface, and state layer,
231
+ animates the shifting items with standard motion, and presents plain handles as standard icon
232
+ buttons.
233
+
234
+ - 6d126fd: Add shared item type tokens: `--rc-item-font-family`, `--rc-item-font-size`,
235
+ `--rc-item-font-weight`, `--rc-item-line-height`, `--rc-item-letter-spacing`,
236
+ and `--rc-item-icon-size`. Menu, listbox, and adaptive-menu items read them.
237
+ Adaptive menu adds `--rc-adaptive-menu-trigger-hover-background`,
238
+ `--rc-adaptive-menu-trigger-shadow`, and
239
+ `--rc-adaptive-menu-trigger-active-shadow`, and styles overflowed `rc-button`
240
+ and `rc-menu-button` rows from its item tokens. Themes declare their menu,
241
+ adaptive-menu, and item tokens on the theme root, so menus inside other shadow
242
+ roots match menus in the document. Substrate's adaptive-menu trigger now shows
243
+ its hover background.
244
+
245
+ Breaking: theme menu and adaptive-menu tokens are inherited from the theme root
246
+ instead of set on each element, so a value set on an ancestor now reaches
247
+ nested menus. Material sets menu, listbox, and adaptive-menu item type through
248
+ `--rc-item-*` instead of per-component rules; override those tokens to change
249
+ item type. Themes no longer style the adaptive-menu trigger through
250
+ `::part(overflow-trigger)` hover and pressed rules; use the new trigger tokens.
251
+
252
+ - e23a39c: Add an accessible native input and textarea field wrapper with Material 3 filled and outlined
253
+ theme treatments, including an explicit provider contract for enhanced native controls.
254
+ - 6b99ced: **Breaking:** replace `LineDisclosureController` with `FoldingActionController`.
255
+ Pass a caller-owned panel as `target` and render it through a block widget, or pass
256
+ `{ fromLine, toLine }` to fold source lines. Panel creation and content revision now
257
+ belong to the plugin. Set `initiallyExpanded: false` to retain the old diagnostic
258
+ panel default; call `clear()` when document identity changes.
259
+
260
+ Folding actions keep source text, form values, and undo history intact. The Markdown
261
+ plugin adds gutter folds for heading sections, lists, code blocks, block quotes,
262
+ and GFM tables. The base gutter has a 24px minimum width; Material uses 48px.
263
+ Folding buttons expose `fold-trigger` and `fold-icon` CSS parts, and
264
+ `createMarkdownPlugin({ folding: { createTriggerIcon } })` lets consumers choose
265
+ the Markdown fold icon.
266
+
267
+ - 3325191: **Breaking:** take `rc-textarea`'s read-only state from the slotted `<textarea readonly>` and
268
+ remove the `read-only` attribute and its display styling without border or padding. A read-only
269
+ editor keeps the enabled field appearance, stays focusable and selectable, announces `aria-
270
+ readonly` with the native control's label, and rejects edits. The host reflects `data-readonly`,
271
+ and `readOnly` is now a getter. The plugin `transform()` hook runs while the textarea is
272
+ `readonly`.
273
+
274
+ `rc-markdown-editor` passes its `read-only` state to a native textarea in its source editor.
275
+ Material and Substrate fields skip the hover affordance for a read-only control and keep its
276
+ focus indicator.
277
+
278
+ Migration: replace `<rc-textarea read-only>` with `readonly` on the slotted textarea, for
279
+ example `<rc-textarea><textarea aria-label="Notes" readonly></textarea></rc-textarea>`. Replace
280
+ `editor.readOnly = value` with `textarea.readOnly = value`. Read-only content that is not a form
281
+ value belongs in ordinary text or list markup instead.
282
+
283
+ - 0e2d878: **Breaking:** replace `--rc-textarea-padding` with `--rc-textarea-padding-block` and
284
+ `--rc-textarea-padding-inline`. The active line highlight bleeds through the inline padding by
285
+ negating it, which a multi-value shorthand made invalid: inside a Material filled `rc-field`
286
+ (`0 1rem 0.5rem`) the highlight stopped short of the field's edges in the editor and gutter.
287
+ `--rc-textarea-padding-inline` is one length applied to both inline sides, so the bleed stays
288
+ valid and follows RTL and vertical writing modes through logical insets.
289
+ `--rc-textarea-padding-block` accepts any `padding-block` value.
290
+
291
+ Migration: split each `--rc-textarea-padding` declaration. A single length `L` becomes
292
+ `--rc-textarea-padding-block: L; --rc-textarea-padding-inline: L`. A shorthand
293
+ `T X B` becomes `--rc-textarea-padding-block: T B; --rc-textarea-padding-inline: X`.
294
+
295
+ - f5c1a8c: `rc-theme-material` now routes its component motion through the shared
296
+ spatial/effects token scale consistently. Previously, roughly thirty
297
+ `transition`/property declarations across combobox, listbox, menu, menu
298
+ button, menubar, select, range slider, search bar, app bar, textarea,
299
+ transfer list, toolbar, and splitter carried hardcoded `150ms ease` or
300
+ `200ms ease` literals instead of the theme's own motion tokens, and the
301
+ navigation bar/rail's active-item indicator (which resizes to the selected
302
+ item's box, a spatial change) was themed with a raw Material duration/easing
303
+ pair outside either scale. Every color/background-color/border-color/
304
+ box-shadow/opacity transition now uses `--rc-motion-effects-*`, and every
305
+ transform/scale/translate/inline-size/block-size transition uses
306
+ `--rc-motion-spatial-*`, splitting any declaration that mixed both kinds of
307
+ property. `rc-field`'s floating label transition moves its position/size
308
+ properties (`inset-block-start`, `font-size`) from the effects scale to the
309
+ spatial scale they actually belong to.
310
+
311
+ Five component motion tokens the theme previously left unset are now themed:
312
+ `--rc-switch-easing`, `--rc-button-state-layer-duration`,
313
+ `--rc-card-state-layer-duration`, `--rc-card-state-layer-easing`, and
314
+ `--rc-splitter-snap-duration`. `rc-switch`'s single duration/easing pair (it
315
+ has no separate spatial/effects knobs) now takes the spatial scale, since its
316
+ dominant motion, the thumb sliding and resizing, is spatial; this changes its
317
+ default transition speed under this theme from 150&nbsp;ms to 300&nbsp;ms.
318
+ `rc-splitter`'s snap-to-point animation moves from its 200&nbsp;ms component
319
+ default to the same 300&nbsp;ms spatial-fast tier for the same reason.
320
+
321
+ The spatial easing curves are now sourced from the semantic aliases added in
322
+ the last release rather than composed inline from raw control points four
323
+ times over. Material 3's spec spatial durations are
324
+ 350/500/700&nbsp;ms; this theme's own motion guide finds durations past
325
+ roughly 400&nbsp;ms read as waiting rather than feedback, so the spatial
326
+ scale is compressed to 300/400/500&nbsp;ms: a deliberate, recorded departure
327
+ from the spec numbers, not the spec's `emphasized` curve shape, which is
328
+ unchanged.
329
+
330
+ - 40f132d: `rc-theme-material` now declares the Material 3 motion system's seven named
331
+ easing curves (`--md-sys-motion-easing-standard`, `-emphasized`, and their
332
+ decelerate/accelerate variants, plus `-linear`) and sixteen named duration
333
+ bands (`--md-sys-motion-duration-short1` through `-extra-long4`), composed
334
+ from the control points and millisecond primitives already vendored. Several
335
+ component recipes were already reaching for these names with an inline
336
+ fallback (`var(--md-sys-motion-easing-standard, cubic-bezier(0.2, 0, 0, 1))`)
337
+ that silently won every time because nothing declared the token; those
338
+ references now resolve for real, and the fallback silently carrying a
339
+ Material 2 curve (`cubic-bezier(0.4, 0, 0.2, 1)`, in `rc-state-layer`'s
340
+ transition) is fixed to the correct Material 3 curve. Two more vendored-token
341
+ gaps of the same shape are fixed alongside: Material's disabled state-layer
342
+ and container opacity tokens, referenced across a dozen component recipes
343
+ with no local declaration, and two Substrate token names
344
+ (`--substrate-border`, `--substrate-radius-medium`) that never matched their
345
+ real declarations (`--substrate-border-color`, `--substrate-radius-md`) and
346
+ so always fell back to a hardcoded literal instead of the theme's actual
347
+ values; `rc-fab-menu`'s Substrate shadow tokens are corrected the same way.
348
+ - 11b8cb9: Theme `rc-select` and `rc-combobox` as `rc-field` control providers: resting, hover, and
349
+ focus/open chrome resets mirroring the existing `rc-textarea` treatment, so `rc-field`'s own
350
+ `#field` surface owns the visible border, background, and focus ring instead of the wrapped
351
+ control rendering its own on top. Standalone (non-wrapped) usage is unaffected; every new rule
352
+ is scoped to `[data-rc-field-control]`.
353
+ - fb747f6: Declare `rc-base` before each theme's own layers. Components inject their structural
354
+ light-DOM CSS into `rc-base` at runtime, after the theme has loaded, which made it the last
355
+ and strongest layer on pages that don't declare their own order, so it could override theme
356
+ rules. Theme rules now win either way. Apps that declare their own layer order should list
357
+ `rc-base` before the theme layers.
358
+
359
+ Add a fourth theme layer, `rc-theme-*.overrides`, after `.components`. Each theme uses it to
360
+ keep `rc-adaptive-menu` overflow rows on the menu's item tokens. Theme button and menu-button
361
+ variants, such as Material's icon-only sizing and filled colors or Win31's bevelled native
362
+ buttons, no longer restyle an overflowed action as a standalone control. A demoted
363
+ icon-only `rc-menu-button` keeps its row padding and indicator inset.
364
+
365
+ - 877a03f: Add a scoped type scale. An element with `data-rc-type-scale` multiplies every Material
366
+ type size and line height beneath it by `--rc-type-scale`, and derives the RC text
367
+ tokens built on them (`--rc-item-font-size`, `--rc-font-size`, `--rc-button-font`, and
368
+ related line heights) again from the scaled values, so lists, buttons, menus, and plain
369
+ text in the region grow together.
370
+
371
+ Marking the theme root itself scales the whole page, for an app-wide text size setting.
372
+ With `bridge.css` alone, RC text scales from the application's Material type tokens;
373
+ the application's Material tokens remain unchanged.
374
+
375
+ ### Patch Changes
376
+
377
+ - 8d6edf2: With `scroll-behavior="hide"`, `rc-app-bar` now publishes read-only geometry onto its scroll
378
+ target: `--rc-app-bar-block-size`, its measured block size, and
379
+ `--rc-app-bar-visible-block-size`, the same value or `0px` while hidden. Hiding only translates
380
+ the bar, so a layout can now give its space back: stack the bar over the scroll container,
381
+ reserve the block size as the container's block-start padding and scroll padding, and pin
382
+ sticky content at the visible size minus the block size, since sticky offsets are measured
383
+ inside that padding. The bar removes both values when it stops hiding, changes
384
+ target, or disconnects.
385
+
386
+ The Material design guide documents this recipe and the compact-height patterns for landscape
387
+ phones: app bars that hide on scroll, side sheets instead of modal bottom sheets, full-screen
388
+ task dialogs, media capped by the pane's height, and single-row sticky chips.
389
+
390
+ - 3d050f1: Keep wrapped chip rows evenly spaced. Readonly chips in an `rc-chip-group`
391
+ keep the touch-target block size, so expanded rows share the disclosure
392
+ toggle's pitch. `rc-combobox` and `rc-select` return the chip touch-target
393
+ overlap tokens as row gap, so interior chip rows no longer collapse onto each
394
+ other inside a field. Material combobox and select input chips drop their
395
+ extra block padding to render at the 2rem chip height.
396
+ - 011f3c6: Keep combobox chips clear of their trailing toggle, reset native selects inside
397
+ `rc-field`, keep controlled carousel accessibility state synchronized, and align
398
+ Material chips, menus, lists, disclosures, nested editors, and bottom-sheet
399
+ motion with their MD3 defaults.
400
+ - 3f19f57: Disclosure summaries draw their hover layer only for a pointer that can hover, so a tapped
401
+ summary no longer stays highlighted on touch screens. The Material theme also spaces disclosure
402
+ content from its summary.
403
+ - 25375fa: Drop the inner focus ring from `rc-combobox` and `rc-select` when they are
404
+ composed as `rc-field` controls, since the field's label and active indicator
405
+ already show focus.
406
+ - 3f8d110: Clear a page-level focus outline from a native input, select, or textarea inside `rc-field`. The
407
+ field already shows focus, but rc-field's `::slotted()` reset loses to page rules such as a CSS
408
+ reset's Firefox `:-moz-focusring` outline, which drew a dotted box inside the focused field.
409
+ - cc0205d: Use logical CSS properties so layout follows the reading direction and
410
+ writing mode: the textarea gutter border and alignment, line-action and
411
+ diagnostic-message spacing, the markdown editor's block quote and list
412
+ indents, and block-axis scrolling for listbox, select, combobox, and markdown
413
+ panes, each keeping its physical declaration as a fallback.
414
+ - 818d193: Clarify that compact-height layouts show one route page at a time and open
415
+ transient filters or ingredients in full-screen dialogs. Supporting content
416
+ may form a scrolling column when space permits.
417
+ - 6771ce6: Pin floated Material field labels to the container instead of centering them
418
+ with the control. Filled fields reserve 8px of block padding, so every floated
419
+ label sits at the same offset and a taller control grows the field downward;
420
+ outlined labels now ride the top border for select and combobox controls too. Full-size
421
+ chips in a filled field keep a 0.25rem gap below the floated label.
422
+ Select and combobox controls drop their own block padding inside fields, and
423
+ `rc-textarea` text starts on the input line like a native textarea.
424
+
425
+ Add `rc-combobox--dense` and `rc-select--dense`, which render 1.5rem chips so a
426
+ populated chip field keeps the standard 56px height.
427
+
428
+ - f5d33fa: Describe which icons mirror in right-to-left layouts, and how an app maps the
429
+ physical safe-area insets to inline start and end before using them with
430
+ logical properties.
431
+ - e062f7f: Give the Material typefaces a generic fallback. `--md-ref-typeface-plain`
432
+ and `--md-ref-typeface-brand` are now `Roboto, system-ui, sans-serif`, so a
433
+ page without Roboto renders in the system sans-serif instead of the
434
+ browser's default serif.
435
+ - 622a4f8: Theme popovers and tooltips through the shared token layers. `rc-popover` now
436
+ reads the shared `--rc-popup-*` surface tokens before its own fallbacks, like
437
+ menus and listboxes, and `rc-tooltip` takes its default corner from
438
+ `--rc-radius-sm`. The Material theme sets its popover and tooltip tokens on the
439
+ theme root, so surfaces inside other shadow roots inherit them, and the
440
+ Substrate theme adds popover and tooltip styles.
441
+ - 114e38a: `rc-progress`'s determinate fill transition is now themeable through two new
442
+ CSS custom properties, `--rc-progress-fill-transition-duration` (default
443
+ `150ms`) and `--rc-progress-fill-transition-easing` (default `ease-out`),
444
+ replacing a hardcoded `0.15s ease-out` no theme could reach.
445
+
446
+ The indeterminate loop's easing changes from `ease-in-out` to `linear`. A
447
+ loop has no beginning or end to decelerate into or accelerate out of, so an
448
+ eased loop visibly pulses at each cycle boundary; Material 3 specifies linear
449
+ easing for indeterminate loops for the same reason.
450
+
451
+ `rc-theme-material` and `rc-theme-substrate` map the new duration/easing
452
+ properties to their effects-fast motion tokens; `rc-theme-win31` already sets
453
+ `transition: none` on the fill part directly and needs no change.
454
+
455
+ - 5f1628f: Draw the search bar's keyboard focus ring on the field's edge instead of 2px
456
+ outside it, where it floated off the pill and crowded the top of the app bar.
457
+ - fef89dc: Move the segmented appearance into the component behind one switch.
458
+
459
+ Turning the native fieldset into a segmented control took 27 `--_rc-*`
460
+ declarations that every theme had to restate, 23 of them byte-identical. Two of
461
+ those blocks were accessibility recipes rather than taste: the visually hidden
462
+ legend that keeps the group's accessible name, and the hidden but focusable
463
+ radio. A theme that got either wrong removed the accessible name or made the
464
+ control unreachable by keyboard.
465
+
466
+ The component now owns the recipe and a theme sets
467
+ `--rc-segmented-button-appearance: segmented`. Four genuine theme choices become
468
+ public properties: `--rc-segmented-button-cursor`,
469
+ `--rc-segmented-button-disabled-cursor`,
470
+ `--rc-segmented-button-vertical-divider`, and
471
+ `--rc-segmented-button-selected-icon-display`.
472
+
473
+ Unset, the fieldset, legend, and radios keep their browser appearance, as
474
+ before. The switch is read with a style container query (Chrome 111, Safari 18,
475
+ Firefox 128); where that is unsupported the recipe does not apply and the
476
+ control falls back to the same native appearance.
477
+
478
+ To migrate a theme, replace its `--_rc-segmented-button-*` block with the single
479
+ `--rc-segmented-button-appearance: segmented` declaration, plus any of the four
480
+ public properties whose value differs from the default.
481
+
482
+ - 77f9c63: Fix three theme gaps where a token fell through to a system color.
483
+
484
+ **Substrate had no error color.** `--rc-field-error-color` fell through to `rc-field`'s own
485
+ default of `Mark`, the system color for the background of highlighted text, which renders as
486
+ pure yellow and measured 1.07:1 against the field. Validation worked, the message was in the
487
+ accessibility tree, and it could not be read. Substrate now ships `--substrate-error`, held
488
+ at hue 25 so it reads as red rather than as a darker shade of the orange primary at hue 48,
489
+ and the bridge maps it. Both modes clear 7:1.
490
+
491
+ Every remaining error fallback of `Mark`, in `rc-field` and in the Material field styles, now
492
+ falls back to the validation red a user agent uses for an invalid control. The `Mark` usages
493
+ inside `forced-colors` blocks are unchanged, where a system color is correct.
494
+
495
+ **Material never set `--rc-button-text`.** `rc-select`, `rc-combobox`, and `rc-menu-button`
496
+ read it directly for text drawn over `--rc-button-bg`, which Material sets to the primary
497
+ fill, so the `ButtonText` fallback gave 3.26:1 in light and 1.70:1 in dark. It now follows
498
+ `--md-sys-color-on-primary` alongside `--rc-button-color`, giving 6.44:1 and 7.71:1.
499
+
500
+ **Substrate referenced three tokens it never declared.** `--substrate-inverse-surface`,
501
+ `--substrate-inverse-on-surface`, and `--substrate-radius-pill` were used by the bridge and
502
+ component styles but missing from `defaults.css`, leaving `rc-snackbar` on system colors and
503
+ the bottom sheet handle on a literal. All three are declared, and a `defaults` test now
504
+ asserts that every referenced token exists.
505
+
506
+ - edfd374: Icon slots keep their square while empty. An SVG icon element such as
507
+ `<iconify-icon>` draws a frame after it mounts, so swapping one in, such as a
508
+ filter chip's check, no longer collapses the slot and shifts the row for a
509
+ frame. Icon-font glyphs already fill 1em and render the same.
510
+ - 22c23df: Ship `DESIGN.md`, a Material 3 composition guide for AI coding agents covering
511
+ component roles, adaptive layouts by window size class, dialogs, sheets, lists,
512
+ navigation and feedback, with the baseline token values as front matter. The
513
+ guide is exported as `@rcarls/rc-theme-material/DESIGN.md` so Plug'n'Play
514
+ consumers can resolve it.
515
+ - 790c50d: Full-screen dialogs now use the Material 3 `surface` role, matching their top app bar, instead
516
+ of the basic dialog's `surface-container-high`. Apps no longer need to set
517
+ `--rc-dialog-fullscreen-background` themselves.
518
+ - 1aff823: Document icon font wiring as one copy-pasteable rule.
519
+
520
+ The theme sizes icon markers but sets no `font-family`, so a marker without one
521
+ renders as its literal text. That was documented per component, which meant
522
+ adopting a component could reintroduce the problem one marker at a time. The
523
+ README now lists every marker in the catalog in a single rule, and names the
524
+ three that carry no sizing from the theme either.
525
+
526
+ - 3a5d979: Restore a multiline control-provider field's top spacing so its label sits as
527
+ far below the field's top edge as a single-line field's label does. A
528
+ single-line field gets that space for free from centering content within a
529
+ taller field surface; a multiline control-provider's content fills the
530
+ surface's whole height instead, so the label sat flush against the top edge
531
+ with no room above it.
532
+ - 4457e71: Fix two token generator defects that produced plausible but wrong output.
533
+
534
+ A font shorthand read as a single number. `var(--weight, 500) var(--size, 1rem) / var(--lh)
535
+ var(--family)` both starts and ends with `var(`, and the anchored pattern's fallback group is
536
+ greedy, so it matched as one `var(--weight)` whose fallback was the rest of the declaration and
537
+ resolved to `500`. The export carried `card/title-font` and `card/subtitle-font` as floats that
538
+ were really a collapsed shorthand. A value now counts as an alias only when its opening `var(`
539
+ closes at the end of the string.
540
+
541
+ A mix weight written as a `calc` only worked by accident. Material writes its state layers as
542
+ `color-mix(in srgb, var(--color) calc(var(--opacity, 0.08) * 100%), transparent)`. The old code
543
+ pattern-matched a trailing percentage off the operand, leaving a malformed remainder that
544
+ happened to resolve through the greedy match above. Mix operands are now split at parenthesis
545
+ depth zero and the weight resolves through the same resolver.
546
+
547
+ ## 0.6.0
548
+
549
+ ### Minor Changes
550
+
551
+ - ffcbf11: Add adaptive chip-group layouts, native-backed filter chips, and shared
552
+ input-chip rendering. Native-backed chips preserve controlled host state,
553
+ follow form resets when uncontrolled, and accept native link actions. Groups
554
+ restore author-owned chip variants when coordination ends. Keep search input
555
+ chrome inside the search surface and align contextual icon sizes with Material 3.
556
+ - 40f9776: Add an APG carousel built on native CSS scroll snap, with optional navigation,
557
+ pagination, mouse dragging, looping, and consumer-controlled slide sizing.
558
+ Preserve controlled active-index behavior after rejected swipes, keep visual
559
+ loop clones inert and out of forms, and degrade safely without intersection
560
+ observation.
561
+ - a108336: Add shared-column `rc-list` and `rc-list-item` elements with standard and
562
+ segmented appearances, default content truncation, and native-backed single or
563
+ multiple selection coordination. Restore author-owned item state when native
564
+ selection coordination ends.
565
+ - 509ee64: Add `rc-progress`, a native `<progress>` enhancer with a formatted value
566
+ display, a track and fill you can restyle with CSS custom properties, and a
567
+ built-in fix for the indeterminate/undefined-binding footgun.
568
+
569
+ Keep the native element as the uncontrolled source of truth, support releasing
570
+ a controlled value, and react to live native `value`/`max` changes. Preserve a
571
+ native determinate value while `indeterminate` temporarily removes its
572
+ attribute.
573
+
574
+ The bar renders at its intended height with no `display` attribute set,
575
+ matching its own documented default: previously the track/fill/native
576
+ `<progress>` are all absolutely positioned, contributing nothing to the
577
+ control's normal-flow height, so with no value-display text sharing its grid
578
+ row to give it one, the whole bar collapsed to 0px.
579
+
580
+ - d67efde: Add a native-host scroll region with optional centered content and fullbleed
581
+ layout tracks, aggregate framework typings, RTL-aware boundary state, and
582
+ Material layout defaults.
583
+ - 6d3b478: Add Material button emphasis, danger-tone, icon sizing, and adaptive-menu
584
+ contracts. Complete the bundled surface-role palette and forced-colors mappings.
585
+ - 30eb232: Add icon-only activation-area sizing and Material icon-button variants. Align menu
586
+ selection and submenu affordances, and keep anchored popups within the viewport
587
+ across native and fallback positioning.
588
+ - 6d3b478: Default the new touch-target overlap tokens for MD3's own dense/narrow
589
+ icon-button and overflow-trigger conventions: `rc-button`'s and
590
+ `rc-menu-button`'s narrow variant (where the icon is smaller than the
591
+ default 3rem touch target) now reclaim the trailing edge automatically,
592
+ and `rc-adaptive-menu`'s overflow trigger, always the trailing-most
593
+ control in its toolbar by design, does the same unconditionally. Only the
594
+ trailing edge defaults, matching each component's own documented
595
+ "trailing overflow trigger" use case; the leading edge stays an explicit
596
+ opt-in.
597
+
598
+ ### Patch Changes
599
+
600
+ - 6d3b478: Keep generic dialog button styles out of custom control wrappers, support nested
601
+ bottom-sheet handles, and expose the Material disabled-button opacity token.
602
+
3
603
  ## 0.5.0
4
604
 
5
605
  ## 0.4.2