@rcarls/rc-theme-substrate 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 (44) hide show
  1. package/CHANGELOG.md +417 -0
  2. package/README.md +23 -0
  3. package/bridge.css +47 -17
  4. package/components/accordion.css +10 -111
  5. package/components/adaptive-menu.css +98 -0
  6. package/components/app-bar.css +1 -5
  7. package/components/bottom-sheet.css +1 -1
  8. package/components/carousel.css +31 -0
  9. package/components/chip-group.css +21 -0
  10. package/components/dialog.css +15 -11
  11. package/components/disclosure.css +56 -72
  12. package/components/fab-menu.css +3 -3
  13. package/components/field.css +155 -0
  14. package/components/list-item.css +36 -33
  15. package/components/listbox.css +4 -2
  16. package/components/markdown-editor.css +45 -32
  17. package/components/menu.css +11 -6
  18. package/components/modes.css +36 -0
  19. package/components/popover.css +13 -0
  20. package/components/progress.css +11 -0
  21. package/components/scroller.css +19 -0
  22. package/components/search-bar.css +3 -1
  23. package/components/segmented-button.css +2 -27
  24. package/components/select.css +21 -0
  25. package/components/splitter.css +27 -2
  26. package/components/textarea.css +3 -2
  27. package/components/toolbar.css +9 -4
  28. package/components/tooltip.css +15 -0
  29. package/components/transfer-list.css +3 -3
  30. package/components/virtual-canvas.css +10 -0
  31. package/components/virtual-scroller.css +7 -0
  32. package/components.css +11 -1
  33. package/css-components/button.css +66 -0
  34. package/css-components/card.css +14 -0
  35. package/css-components/chip-group.css +9 -0
  36. package/css-components/chip.css +80 -0
  37. package/css-components/disclosure.css +25 -0
  38. package/css-components/list.css +34 -0
  39. package/css-components/select.css +20 -0
  40. package/css-components/textarea.css +22 -0
  41. package/css-components.css +31 -0
  42. package/defaults.css +34 -5
  43. package/native.css +249 -0
  44. package/package.json +5 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,422 @@
1
1
  # @rcarls/rc-theme-substrate
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
+ - 2c7c80a: Give `rc-dialog` a surface styling contract.
46
+
47
+ It exposed only `--rc-dialog-scrim`, so both themes drew the surface by selecting the native
48
+ `<dialog>` directly. It now installs a light-DOM base stylesheet, the same pattern as `rc-button`
49
+ and `rc-disclosure`, and exposes minimum and maximum inline and block bounds, padding, border, radius, background,
50
+ foreground, and shadow, plus fullscreen-specific padding and background for the two values that
51
+ variant genuinely needs of its own.
52
+
53
+ Fullscreen geometry, meaning position, size, margin, radius, and shadow, stays structural rather
54
+ than something a theme sets: filling the visual viewport is what keeps the surface correct under browser zoom
55
+ and a software keyboard.
56
+
57
+ Material's explicit block bound with `overflow: hidden` moved into the base layer rather than
58
+ staying a theme value. It exists because Chromium does not reliably clip a scrolling element's
59
+ own border radius at the scroll boundary, which is a correctness fix every theme needs.
60
+
61
+ `--rc-dialog-visual-viewport-left`, `-top`, `-width`, and `-height` are no longer documented as
62
+ theme properties. They are geometry the component writes while a fullscreen dialog is open:
63
+ readable if something inside the dialog needs the same measurements, but setting them does not
64
+ move the dialog. They are candidates for private `--_rc-dialog-*` names in a future revision.
65
+
66
+ - 4b9bfe6: Give `rc-disclosure` and `rc-accordion` a public styling contract.
67
+
68
+ Both were styled by targeting the native `<details>` element directly, so neither exposed a
69
+ single `--rc-*` property and no theme could change them without rewriting theme CSS. They now
70
+ follow the light-DOM base pattern `rc-button` and `rc-listbox` already use: `rc-disclosure`
71
+ installs one structural stylesheet per containing `Document` or `ShadowRoot`, in `@layer rc-base`
72
+ behind a `data-rc-light-dom-base` sentinel, reading documented properties with UA-like defaults.
73
+
74
+ One recipe covers both supported child forms, a bare `<details>` inside `rc-accordion` and one
75
+ wrapped in `rc-disclosure`, so neither theme repeats the panel rules. `rc-accordion` owns only
76
+ `--rc-accordion-gap`.
77
+
78
+ Motion is opt-in. `--rc-disclosure-duration` defaults to `0ms`, so a disclosure with no theme keeps
79
+ the platform's snap-open behavior, and the height animation runs on `::details-content` behind a
80
+ `@supports selector()` check. This replaces Material's `60rem` `max-block-size` ceiling, which
81
+ clipped content taller than the guess and made every non-summary child its own animation unit.
82
+
83
+ **Fixes a missing expand affordance in the Material theme.** It set `display: grid` on the
84
+ `<summary>` and then styled `summary::marker`. Any `display` other than `list-item` drops the
85
+ marker box, so that rule styled nothing and the theme drew no replacement: a Material disclosure
86
+ had no disclosure triangle at all. The base layer never sets `display` on a summary, so the
87
+ marker survives. A theme may still change it, as Substrate does, but only alongside a
88
+ replacement affordance.
89
+
90
+ - 19278d4: Group several native controls into one `rc-field` with a direct `<fieldset>`. Its `<legend>` names
91
+ the group and shows as the field label, each control keeps its own accessible name, and supporting
92
+ text describes the fieldset. The first text-like input or textarea is the primary control behind
93
+ `control`, `focus()`, and `data-populated`; focus moving between grouped controls keeps the field
94
+ focused; and `data-disabled`, `data-required`, and `data-invalid` reflect the whole group. New
95
+ read-only `group` and `controls` properties and a `data-group` host attribute support the mode.
96
+
97
+ The primary control grows and other controls attach before or after it. In Material, the legend uses
98
+ the floating label mechanics: it rests on the input line while the group is idle and its primary
99
+ input empty, and floats on focus or once that input has a value; a group with a control before its
100
+ primary input keeps it floated. Grouped placeholders wait for focus. Substrate colors an invalid
101
+ group's legend, and Win31 spaces it like a single field's label.
102
+
103
+ - 873592e: Add four directional motion tokens to the shared base contract:
104
+ `--rc-motion-effects-easing-enter`/`-exit` and
105
+ `--rc-motion-spatial-easing-enter`/`-exit`. An opening element decelerates
106
+ into place; a closing one accelerates out. There are no matching enter/exit
107
+ duration tokens; pair `-easing-exit` with an existing `-duration-fast` token
108
+ instead.
109
+
110
+ All three themes map the new tokens: Material pairs them with its
111
+ standard/emphasized decelerate and accelerate curves, Substrate keeps its one
112
+ curve as the enter curve and adds a generic accelerate shape for exit
113
+ (refined further once Substrate gets its own full spatial/effects scale), and
114
+ `rc-theme-win31` declares all four as `step-end`, matching its zero-motion
115
+ contract, so an application that loads the shared base tokens alongside
116
+ `rc-theme-win31` does not inherit the base defaults' real easing curves for
117
+ these two directions.
118
+
119
+ - 7c952e2: `rc-theme-material` and `rc-theme-substrate` refine `prefers-reduced-motion:
120
+ reduce` from removing every transition and animation to removing only
121
+ spatial motion; effects motion (color and opacity) is kept, shortened.
122
+ Vestibular harm, the reason for the preference, comes from movement across
123
+ the visual field; a color or opacity change doesn't trigger it, and removing
124
+ it too was also removing motion that aids comprehension.
125
+
126
+ Material's effects duration shortens to 50/70/100&nbsp;ms (from its full
127
+ 150/200/300&nbsp;ms scale); Substrate's to 40/55/70&nbsp;ms, scaled down from
128
+ its own faster 100/160/240&nbsp;ms base. `rc-theme-win31` needs no change: it
129
+ already declares every duration at zero unconditionally.
130
+
131
+ Several component recipes that bypassed the shared motion scale entirely,
132
+ referencing a raw duration primitive directly, are rewired to the
133
+ appropriate effects or spatial token so this refinement actually reaches
134
+ them: Material's `rc-disclosure`, `rc-list-item`, `rc-bottom-sheet`'s snap
135
+ duration, `rc-button`'s ripple, and its shared state-layer opacity fade;
136
+ Substrate's `rc-listbox`, `rc-splitter`, and `rc-disclosure`. Most land on
137
+ their existing value exactly; `rc-button`'s ripple duration normalizes from
138
+ 450&nbsp;ms to 500&nbsp;ms, the nearest real spatial tier.
139
+
140
+ - c62d107: Let opt-in native theme styles reach consumer controls inside RC containers while
141
+ component recipes retain their themed presentation. Apply the same presentation
142
+ boundary and `data-rc-native="off"` subtree opt-out in Material, Substrate, and
143
+ Windows 3.1.
144
+
145
+ Native controls inside an RC host may now gain theme styling when that host does
146
+ not provide their appearance. Add `data-rc-native="off"` to content that should
147
+ keep its own styles, such as a third-party widget.
148
+
149
+ - 622c5c9: Add independent opt-in `native.css` and CSS-only `css-components.css` entrypoints to the
150
+ Material, Substrate, and Windows 3.1 themes. Native controls can use the theme presentation
151
+ without registration, while documented class recipes style common HTML controls and static
152
+ card, list, chip-group, and disclosure markup without changing behavior.
153
+
154
+ Native styles stop at RC controls that own their native children. Add
155
+ `data-rc-native="off"` to an element to keep native styles off it and its subtree.
156
+
157
+ - 622a4f8: Theme popovers and tooltips through the shared token layers. `rc-popover` now
158
+ reads the shared `--rc-popup-*` surface tokens before its own fallbacks, like
159
+ menus and listboxes, and `rc-tooltip` takes its default corner from
160
+ `--rc-radius-sm`. The Material theme sets its popover and tooltip tokens on the
161
+ theme root, so surfaces inside other shadow roots inherit them, and the
162
+ Substrate theme adds popover and tooltip styles.
163
+ - 687a9be: Add shared popup surface tokens: `--rc-popup-background`, `--rc-popup-color`,
164
+ `--rc-popup-border`, `--rc-popup-radius`, `--rc-popup-shadow`, and
165
+ `--rc-popup-padding-block`. Menus, adaptive-menu popups, and select and
166
+ combobox listboxes read them before their own fallbacks. Themes set them at the
167
+ theme root, so popups rendered inside other shadow roots keep the theme's
168
+ surface. Select and combobox add `--rc-*-listbox-background` and
169
+ `--rc-*-listbox-color`.
170
+
171
+ Breaking: popup surfaces no longer fall back to `--rc-control-radius`. Set
172
+ `--rc-popup-radius` (or the per-component radius token) to change popup
173
+ corners. The Material, Substrate, and Win31 themes no longer set per-component
174
+ popup surface tokens such as `--rc-menu-radius` or
175
+ `--rc-adaptive-menu-popup-background`; override the `--rc-popup-*` tokens
176
+ instead. Material select and combobox listboxes now use the menu container
177
+ color, Material forced-colors popups gain a border, and Substrate listboxes use
178
+ the menu shadow and padding. Material retains its two-layer adaptive-menu popup
179
+ shadow through a component token while other popups continue using the shared
180
+ shadow.
181
+
182
+ - 6d126fd: Add shared item type tokens: `--rc-item-font-family`, `--rc-item-font-size`,
183
+ `--rc-item-font-weight`, `--rc-item-line-height`, `--rc-item-letter-spacing`,
184
+ and `--rc-item-icon-size`. Menu, listbox, and adaptive-menu items read them.
185
+ Adaptive menu adds `--rc-adaptive-menu-trigger-hover-background`,
186
+ `--rc-adaptive-menu-trigger-shadow`, and
187
+ `--rc-adaptive-menu-trigger-active-shadow`, and styles overflowed `rc-button`
188
+ and `rc-menu-button` rows from its item tokens. Themes declare their menu,
189
+ adaptive-menu, and item tokens on the theme root, so menus inside other shadow
190
+ roots match menus in the document. Substrate's adaptive-menu trigger now shows
191
+ its hover background.
192
+
193
+ Breaking: theme menu and adaptive-menu tokens are inherited from the theme root
194
+ instead of set on each element, so a value set on an ancestor now reaches
195
+ nested menus. Material sets menu, listbox, and adaptive-menu item type through
196
+ `--rc-item-*` instead of per-component rules; override those tokens to change
197
+ item type. Themes no longer style the adaptive-menu trigger through
198
+ `::part(overflow-trigger)` hover and pressed rules; use the new trigger tokens.
199
+
200
+ - 7549dde: Theme the nine components Substrate left without a token contract.
201
+
202
+ `rc-adaptive-menu`, `rc-carousel`, `rc-chip-group`, and `rc-scroller` had no component CSS at
203
+ all. `rc-toolbar` and `rc-virtual-canvas` had a file that styled the element directly without
204
+ declaring a single `--rc-*` property. `rc-splitter` declared two colors that mixed against the
205
+ bare `Canvas` and `ButtonBorder` system colors, and the dialog scrim mixed against `CanvasText`,
206
+ so none of the three had a value that could leave CSS.
207
+
208
+ All are themed now, and the mixes point at the theme's own surface, border, and inverse surface
209
+ instead of at system colors. Every new color clears WCAG AA against the surface it is drawn on,
210
+ most of them AAA.
211
+
212
+ The splitter keeps its existing division of labor: this theme paints it and leaves its geometry
213
+ to the component's own defaults.
214
+
215
+ `rc-accordion` and `rc-disclosure` are unchanged. They read no `--rc-*` property anywhere in
216
+ their own styles, so there is nothing for a theme to set; giving them a contract is a change to
217
+ those components.
218
+
219
+ - 77f9c63: Fix three theme gaps where a token fell through to a system color.
220
+
221
+ **Substrate had no error color.** `--rc-field-error-color` fell through to `rc-field`'s own
222
+ default of `Mark`, the system color for the background of highlighted text, which renders as
223
+ pure yellow and measured 1.07:1 against the field. Validation worked, the message was in the
224
+ accessibility tree, and it could not be read. Substrate now ships `--substrate-error`, held
225
+ at hue 25 so it reads as red rather than as a darker shade of the orange primary at hue 48,
226
+ and the bridge maps it. Both modes clear 7:1.
227
+
228
+ Every remaining error fallback of `Mark`, in `rc-field` and in the Material field styles, now
229
+ falls back to the validation red a user agent uses for an invalid control. The `Mark` usages
230
+ inside `forced-colors` blocks are unchanged, where a system color is correct.
231
+
232
+ **Material never set `--rc-button-text`.** `rc-select`, `rc-combobox`, and `rc-menu-button`
233
+ read it directly for text drawn over `--rc-button-bg`, which Material sets to the primary
234
+ fill, so the `ButtonText` fallback gave 3.26:1 in light and 1.70:1 in dark. It now follows
235
+ `--md-sys-color-on-primary` alongside `--rc-button-color`, giving 6.44:1 and 7.71:1.
236
+
237
+ **Substrate referenced three tokens it never declared.** `--substrate-inverse-surface`,
238
+ `--substrate-inverse-on-surface`, and `--substrate-radius-pill` were used by the bridge and
239
+ component styles but missing from `defaults.css`, leaving `rc-snackbar` on system colors and
240
+ the bottom sheet handle on a literal. All three are declared, and a `defaults` test now
241
+ asserts that every referenced token exists.
242
+
243
+ - 1207f3c: Theme `rc-field`, the last component Substrate left without coverage.
244
+
245
+ The field takes Substrate's palette and the hover, focus, and invalid treatment
246
+ its other form controls already share, so it reads as one of them. `rc-field`
247
+ keeps owning its layout, invalid border, disabled opacity, focus outline, and
248
+ forced-colors fallbacks; the theme only supplies values.
249
+
250
+ An `rc-select`, `rc-combobox`, or `rc-textarea` acting as the field's control
251
+ provider now stops drawing its own border, background, and focus ring, which
252
+ otherwise nested visibly inside the field's. A standalone control outside a
253
+ field is unaffected.
254
+
255
+ The field also fills its container up to a readable measure instead of
256
+ shrink-wrapping, so a provider-backed field with no value no longer collapses
257
+ to its toggle.
258
+
259
+ - 3325191: **Breaking:** take `rc-textarea`'s read-only state from the slotted `<textarea readonly>` and
260
+ remove the `read-only` attribute and its display styling without border or padding. A read-only
261
+ editor keeps the enabled field appearance, stays focusable and selectable, announces `aria-
262
+ readonly` with the native control's label, and rejects edits. The host reflects `data-readonly`,
263
+ and `readOnly` is now a getter. The plugin `transform()` hook runs while the textarea is
264
+ `readonly`.
265
+
266
+ `rc-markdown-editor` passes its `read-only` state to a native textarea in its source editor.
267
+ Material and Substrate fields skip the hover affordance for a read-only control and keep its
268
+ focus indicator.
269
+
270
+ Migration: replace `<rc-textarea read-only>` with `readonly` on the slotted textarea, for
271
+ example `<rc-textarea><textarea aria-label="Notes" readonly></textarea></rc-textarea>`. Replace
272
+ `editor.readOnly = value` with `textarea.readOnly = value`. Read-only content that is not a form
273
+ value belongs in ordinary text or list markup instead.
274
+
275
+ - 0e2d878: **Breaking:** replace `--rc-textarea-padding` with `--rc-textarea-padding-block` and
276
+ `--rc-textarea-padding-inline`. The active line highlight bleeds through the inline padding by
277
+ negating it, which a multi-value shorthand made invalid: inside a Material filled `rc-field`
278
+ (`0 1rem 0.5rem`) the highlight stopped short of the field's edges in the editor and gutter.
279
+ `--rc-textarea-padding-inline` is one length applied to both inline sides, so the bleed stays
280
+ valid and follows RTL and vertical writing modes through logical insets.
281
+ `--rc-textarea-padding-block` accepts any `padding-block` value.
282
+
283
+ Migration: split each `--rc-textarea-padding` declaration. A single length `L` becomes
284
+ `--rc-textarea-padding-block: L; --rc-textarea-padding-inline: L`. A shorthand
285
+ `T X B` becomes `--rc-textarea-padding-block: T B; --rc-textarea-padding-inline: X`.
286
+
287
+ - fb747f6: Declare `rc-base` before each theme's own layers. Components inject their structural
288
+ light-DOM CSS into `rc-base` at runtime, after the theme has loaded, which made it the last
289
+ and strongest layer on pages that don't declare their own order, so it could override theme
290
+ rules. Theme rules now win either way. Apps that declare their own layer order should list
291
+ `rc-base` before the theme layers.
292
+
293
+ Add a fourth theme layer, `rc-theme-*.overrides`, after `.components`. Each theme uses it to
294
+ keep `rc-adaptive-menu` overflow rows on the menu's item tokens. Theme button and menu-button
295
+ variants, such as Material's icon-only sizing and filled colors or Win31's bevelled native
296
+ buttons, no longer restyle an overflowed action as a standalone control. A demoted
297
+ icon-only `rc-menu-button` keeps its row padding and indicator inset.
298
+
299
+ - 58f4e71: `rc-theme-substrate` and `rc-theme-win31` now map the full shared
300
+ spatial/effects motion scale that `rc-theme-material` already implements,
301
+ closing a gap where each declared only its own single compatibility duration.
302
+
303
+ Substrate adds a small, quicker scale of its own: 100/160/240&nbsp;ms for
304
+ effects and 160/240/320&nbsp;ms for spatial, with its existing single easing
305
+ curve as the spatial curve (it is already decelerate-shaped) and `ease-out`
306
+ for effects. The compatibility token now follows the effects default rather
307
+ than its own literal, matching the shared base contract's own convention.
308
+ The one remaining hardcoded duration, `rc-list-item`'s 100&nbsp;ms row
309
+ transition, now reads from the effects-fast token. Substrate's
310
+ `prefers-reduced-motion` override moves from the bridge layer into
311
+ `components/modes.css`, in the components layer, matching where the other
312
+ two themes keep their mode overrides; a cascade layer test now proves the
313
+ later layer's override wins rather than assuming it.
314
+
315
+ win31 declares all thirteen shared tokens, plus the four directional ones
316
+ added last release, at zero duration with `step-end` easing. Previously only
317
+ the single compatibility token was set, so an application loading the shared
318
+ base tokens alongside this theme inherited base's real 180/300/450&nbsp;ms
319
+ spatial motion for every other token in the scale, silently contradicting the
320
+ theme's own zero-motion contract. `rc-chip`'s existing zero-duration override
321
+ gets its matching `step-end` easing token.
322
+
323
+ Verifying that claim surfaced a limit worth knowing about even after this
324
+ fix: it holds only when the theme class is applied to a container, the
325
+ documented pattern, not to `<html>`. The shared `base.css` declares no cascade
326
+ layer, so its `:root` values outrank any theme layer whenever both target the
327
+ same element, which happens only when the theme class sits on `<html>` itself.
328
+ No theme package can fix this by declaring more tokens; see the styling guide
329
+ for details.
330
+
331
+ ### Patch Changes
332
+
333
+ - 0de2332: Size fullscreen dialogs correctly under ancestor CSS zoom in browsers without
334
+ `currentCSSZoom`. The Substrate dialog entrance now fades without scaling the
335
+ surface, so resizing during the transition reads stable geometry.
336
+ - 3f8d110: Clear a page-level focus outline from a native input, select, or textarea inside `rc-field`. The
337
+ field already shows focus, but rc-field's `::slotted()` reset loses to page rules such as a CSS
338
+ reset's Firefox `:-moz-focusring` outline, which drew a dotted box inside the focused field.
339
+ - 114e38a: `rc-progress`'s determinate fill transition is now themeable through two new
340
+ CSS custom properties, `--rc-progress-fill-transition-duration` (default
341
+ `150ms`) and `--rc-progress-fill-transition-easing` (default `ease-out`),
342
+ replacing a hardcoded `0.15s ease-out` no theme could reach.
343
+
344
+ The indeterminate loop's easing changes from `ease-in-out` to `linear`. A
345
+ loop has no beginning or end to decelerate into or accelerate out of, so an
346
+ eased loop visibly pulses at each cycle boundary; Material 3 specifies linear
347
+ easing for indeterminate loops for the same reason.
348
+
349
+ `rc-theme-material` and `rc-theme-substrate` map the new duration/easing
350
+ properties to their effects-fast motion tokens; `rc-theme-win31` already sets
351
+ `transition: none` on the fill part directly and needs no change.
352
+
353
+ - fef89dc: Move the segmented appearance into the component behind one switch.
354
+
355
+ Turning the native fieldset into a segmented control took 27 `--_rc-*`
356
+ declarations that every theme had to restate, 23 of them byte-identical. Two of
357
+ those blocks were accessibility recipes rather than taste: the visually hidden
358
+ legend that keeps the group's accessible name, and the hidden but focusable
359
+ radio. A theme that got either wrong removed the accessible name or made the
360
+ control unreachable by keyboard.
361
+
362
+ The component now owns the recipe and a theme sets
363
+ `--rc-segmented-button-appearance: segmented`. Four genuine theme choices become
364
+ public properties: `--rc-segmented-button-cursor`,
365
+ `--rc-segmented-button-disabled-cursor`,
366
+ `--rc-segmented-button-vertical-divider`, and
367
+ `--rc-segmented-button-selected-icon-display`.
368
+
369
+ Unset, the fieldset, legend, and radios keep their browser appearance, as
370
+ before. The switch is read with a style container query (Chrome 111, Safari 18,
371
+ Firefox 128); where that is unsupported the recipe does not apply and the
372
+ control falls back to the same native appearance.
373
+
374
+ To migrate a theme, replace its `--_rc-segmented-button-*` block with the single
375
+ `--rc-segmented-button-appearance: segmented` declaration, plus any of the four
376
+ public properties whose value differs from the default.
377
+
378
+ - 40f132d: `rc-theme-material` now declares the Material 3 motion system's seven named
379
+ easing curves (`--md-sys-motion-easing-standard`, `-emphasized`, and their
380
+ decelerate/accelerate variants, plus `-linear`) and sixteen named duration
381
+ bands (`--md-sys-motion-duration-short1` through `-extra-long4`), composed
382
+ from the control points and millisecond primitives already vendored. Several
383
+ component recipes were already reaching for these names with an inline
384
+ fallback (`var(--md-sys-motion-easing-standard, cubic-bezier(0.2, 0, 0, 1))`)
385
+ that silently won every time because nothing declared the token; those
386
+ references now resolve for real, and the fallback silently carrying a
387
+ Material 2 curve (`cubic-bezier(0.4, 0, 0.2, 1)`, in `rc-state-layer`'s
388
+ transition) is fixed to the correct Material 3 curve. Two more vendored-token
389
+ gaps of the same shape are fixed alongside: Material's disabled state-layer
390
+ and container opacity tokens, referenced across a dozen component recipes
391
+ with no local declaration, and two Substrate token names
392
+ (`--substrate-border`, `--substrate-radius-medium`) that never matched their
393
+ real declarations (`--substrate-border-color`, `--substrate-radius-md`) and
394
+ so always fell back to a hardcoded literal instead of the theme's actual
395
+ values; `rc-fab-menu`'s Substrate shadow tokens are corrected the same way.
396
+
397
+ ## 0.6.0
398
+
399
+ ### Minor Changes
400
+
401
+ - a108336: Add shared-column `rc-list` and `rc-list-item` elements with standard and
402
+ segmented appearances, default content truncation, and native-backed single or
403
+ multiple selection coordination. Restore author-owned item state when native
404
+ selection coordination ends.
405
+ - 509ee64: Add `rc-progress`, a native `<progress>` enhancer with a formatted value
406
+ display, a track and fill you can restyle with CSS custom properties, and a
407
+ built-in fix for the indeterminate/undefined-binding footgun.
408
+
409
+ Keep the native element as the uncontrolled source of truth, support releasing
410
+ a controlled value, and react to live native `value`/`max` changes. Preserve a
411
+ native determinate value while `indeterminate` temporarily removes its
412
+ attribute.
413
+
414
+ The bar renders at its intended height with no `display` attribute set,
415
+ matching its own documented default: previously the track/fill/native
416
+ `<progress>` are all absolutely positioned, contributing nothing to the
417
+ control's normal-flow height, so with no value-display text sharing its grid
418
+ row to give it one, the whole bar collapsed to 0px.
419
+
3
420
  ## 0.5.0
4
421
 
5
422
  ## 0.4.2
package/README.md CHANGED
@@ -58,6 +58,29 @@ reference layer:
58
58
  @import '@rcarls/rc-theme-substrate/components/dialog.css';
59
59
  ```
60
60
 
61
+ Native HTML can opt into the same presentation without registering an RC
62
+ element. Import the defaults and bridge when needed, then opt into the native
63
+ layer and CSS-only recipes:
64
+
65
+ ```css
66
+ @import '@rcarls/rc-theme-substrate/defaults.css';
67
+ @import '@rcarls/rc-theme-substrate/bridge.css';
68
+ @import '@rcarls/rc-theme-substrate/native.css';
69
+ @import '@rcarls/rc-theme-substrate/css-components.css';
70
+ ```
71
+
72
+ `native.css` is an optional convenience layer for styling ordinary buttons,
73
+ text fields, selects, textareas, checkboxes, radios, ranges, and progress
74
+ controls throughout `.rc-theme-substrate`. Component recipes style native
75
+ children when their presentation belongs to a themed menu, toolbar, or other
76
+ component context. Add `data-rc-native="off"` to an element to opt it and its
77
+ descendants out of the native layer. The
78
+ opt-in `css-components.css` recipes cover `.rc-button`, `.rc-chip`,
79
+ `.rc-chip-group`, `.rc-select`, `.rc-textarea`, `.rc-card`, `.rc-list`, and
80
+ `details.rc-disclosure`; each is also exported as
81
+ `css-components/<name>.css`. They provide appearance and CSS-visible states
82
+ only, not behavior, events, popup replacement, or measured overflow.
83
+
61
84
  Tag general icon-font markup with `data-rc-icon`; component-specific markers
62
85
  such as `data-rc-button-icon` and `data-rc-navigation-icon` opt in
63
86
  automatically. The shared `--rc-icon-font-size` and
package/bridge.css CHANGED
@@ -1,4 +1,5 @@
1
- @layer rc-theme-substrate.defaults, rc-theme-substrate.bridge, rc-theme-substrate.components;
1
+ @layer rc-base, rc-theme-substrate.defaults, rc-theme-substrate.bridge, rc-theme-substrate.native, rc-theme-substrate.components, rc-theme-substrate.css-components,
2
+ rc-theme-substrate.overrides;
2
3
 
3
4
  @layer rc-theme-substrate.bridge {
4
5
  /*
@@ -12,6 +13,7 @@
12
13
  --rc-field: var(--substrate-field, Field);
13
14
  --rc-button-bg: var(--substrate-surface-raised, ButtonFace);
14
15
  --rc-field-text: var(--substrate-on-surface, FieldText);
16
+ --rc-field-error-color: var(--substrate-error, red);
15
17
  --rc-button-text: var(--substrate-on-surface, ButtonText);
16
18
  --rc-highlight: var(--substrate-primary-container, Highlight);
17
19
  --rc-highlight-text: var(--substrate-on-primary-container, HighlightText);
@@ -22,6 +24,12 @@
22
24
  --rc-border-style: solid;
23
25
  --rc-border: var(--rc-border-width) var(--rc-border-style) var(--rc-border-color);
24
26
  --rc-shadow: var(--substrate-shadow-md, 0 2px 8px rgb(0 0 0 / 15%));
27
+ --rc-popup-background: var(--substrate-surface, Canvas);
28
+ --rc-popup-color: var(--rc-field-text, CanvasText);
29
+ --rc-popup-border: var(--rc-border);
30
+ --rc-popup-radius: var(--substrate-radius-lg, 0.75rem);
31
+ --rc-popup-shadow: var(--substrate-shadow-lg, none);
32
+ --rc-popup-padding-block: 0.375rem;
25
33
  --rc-font-family: var(--substrate-font-family, inherit);
26
34
  --rc-font-size: var(--substrate-font-size, 1em);
27
35
  --rc-font-weight: var(--substrate-font-weight, 400);
@@ -101,8 +109,35 @@
101
109
  --rc-focus-ring: var(--substrate-focus-ring, 2px solid Highlight);
102
110
  --rc-focus-ring-offset: var(--substrate-focus-ring-offset, 2px);
103
111
  --rc-disabled-opacity: var(--substrate-disabled-opacity, 0.52);
104
- --rc-motion-duration: var(--substrate-motion-duration, 160ms);
105
- --rc-dialog-scrim: color-mix(in srgb, CanvasText 32%, transparent);
112
+ --rc-motion-effects-duration-fast: var(--substrate-motion-effects-duration-fast, 100ms);
113
+ --rc-motion-effects-easing-fast: ease-out;
114
+ --rc-motion-effects-duration-default: var(--substrate-motion-effects-duration-default, 160ms);
115
+ --rc-motion-effects-easing-default: var(--rc-motion-effects-easing-fast);
116
+ --rc-motion-effects-duration-slow: var(--substrate-motion-effects-duration-slow, 240ms);
117
+ --rc-motion-effects-easing-slow: var(--rc-motion-effects-easing-fast);
118
+ --rc-motion-spatial-duration-fast: var(--substrate-motion-spatial-duration-fast, 160ms);
119
+ --rc-motion-spatial-easing-fast: var(--substrate-motion-easing, cubic-bezier(0.2, 0, 0, 1));
120
+ --rc-motion-spatial-duration-default: var(--substrate-motion-spatial-duration-default, 240ms);
121
+ --rc-motion-spatial-easing-default: var(--rc-motion-spatial-easing-fast);
122
+ --rc-motion-spatial-duration-slow: var(--substrate-motion-spatial-duration-slow, 320ms);
123
+ --rc-motion-spatial-easing-slow: var(--rc-motion-spatial-easing-fast);
124
+ /* Substrate's one curve is decelerate-shaped, so it is the enter curve. */
125
+ --rc-motion-effects-easing-enter: ease-out;
126
+ --rc-motion-effects-easing-exit: ease-in;
127
+ --rc-motion-spatial-easing-enter: var(--rc-motion-spatial-easing-fast);
128
+ --rc-motion-spatial-easing-exit: cubic-bezier(0.3, 0, 1, 1);
129
+ /* Matches base.css: the compatibility token follows the effects default. */
130
+ --rc-motion-duration: var(--rc-motion-effects-duration-default);
131
+ /*
132
+ * Mixed against the theme's own inverse surface rather than `CanvasText`,
133
+ * so the scrim carries the palette's warmth and resolves to a real color
134
+ * rather than to a system one that cannot leave CSS.
135
+ */
136
+ --rc-dialog-scrim: color-mix(
137
+ in srgb,
138
+ var(--substrate-inverse-surface, CanvasText) 42%,
139
+ transparent
140
+ );
106
141
  }
107
142
 
108
143
  .rc-theme-substrate rc-listbox,
@@ -127,15 +162,9 @@
127
162
  :host(.rc-theme-substrate) rc-combobox {
128
163
  --rc-select-control-block-size: var(--rc-control-block-size);
129
164
  --rc-select-radius: var(--rc-control-radius);
130
- --rc-select-shadow: var(--rc-shadow);
131
- --rc-select-listbox-radius: var(--substrate-radius-lg, 0.75rem);
132
- --rc-select-listbox-border: var(--rc-border);
133
165
  --rc-select-chip-radius: var(--substrate-radius-sm, 0.25rem);
134
166
  --rc-combobox-control-block-size: var(--rc-control-block-size);
135
167
  --rc-combobox-radius: var(--rc-control-radius);
136
- --rc-combobox-shadow: var(--rc-shadow);
137
- --rc-combobox-listbox-radius: var(--substrate-radius-lg, 0.75rem);
138
- --rc-combobox-listbox-border: var(--rc-border);
139
168
  --rc-combobox-chip-radius: var(--substrate-radius-sm, 0.25rem);
140
169
  }
141
170
 
@@ -154,6 +183,15 @@
154
183
  --rc-thumb-radius: 0.5625rem;
155
184
  }
156
185
 
186
+ .rc-theme-substrate rc-progress,
187
+ :host(.rc-theme-substrate) rc-progress {
188
+ --rc-progress-track-background: color-mix(in srgb, var(--rc-border-color) 70%, transparent);
189
+ --rc-progress-track-opacity: 1;
190
+ --rc-progress-track-radius: 999px;
191
+ --rc-progress-fill-background: var(--rc-accent);
192
+ --rc-progress-value-color: var(--substrate-on-surface-muted, GrayText);
193
+ }
194
+
157
195
  .rc-theme-substrate rc-bottom-sheet,
158
196
  :host(.rc-theme-substrate) rc-bottom-sheet {
159
197
  --rc-bottom-sheet-bg: var(--substrate-surface-raised, Canvas);
@@ -164,12 +202,4 @@
164
202
  --rc-bottom-sheet-handle-color: var(--rc-border-color, GrayText);
165
203
  --rc-bottom-sheet-handle-radius: var(--substrate-radius-pill, 999px);
166
204
  }
167
- @media (prefers-reduced-motion: reduce) {
168
- .rc-theme-substrate,
169
- :host(.rc-theme-substrate) {
170
- --substrate-motion-duration: 0ms;
171
- --substrate-motion-duration-slow: 0ms;
172
- --rc-motion-duration: 0ms;
173
- }
174
- }
175
205
  }