@rcarls/rc-theme-material 0.6.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 (52) hide show
  1. package/CHANGELOG.md +544 -0
  2. package/DESIGN.md +1399 -0
  3. package/README.md +88 -5
  4. package/bridge.css +132 -55
  5. package/components/accordion.css +43 -157
  6. package/components/adaptive-menu.css +47 -86
  7. package/components/app-bar.css +4 -2
  8. package/components/bottom-sheet.css +2 -2
  9. package/components/button.css +2 -1
  10. package/components/card.css +2 -0
  11. package/components/chip.css +12 -1
  12. package/components/combobox.css +61 -14
  13. package/components/dialog.css +27 -26
  14. package/components/disclosure.css +128 -84
  15. package/components/field.css +566 -0
  16. package/components/icons.css +9 -0
  17. package/components/list-item.css +65 -3
  18. package/components/listbox.css +5 -4
  19. package/components/markdown-editor.css +62 -35
  20. package/components/menu-button.css +4 -1
  21. package/components/menu.css +18 -31
  22. package/components/menubar.css +4 -1
  23. package/components/modes.css +22 -5
  24. package/components/navigation-bar.css +3 -5
  25. package/components/navigation-rail.css +5 -7
  26. package/components/popover.css +50 -0
  27. package/components/progress.css +5 -0
  28. package/components/range-slider.css +3 -2
  29. package/components/search-bar.css +12 -2
  30. package/components/segmented-button.css +2 -28
  31. package/components/select.css +99 -14
  32. package/components/splitter.css +4 -1
  33. package/components/switch.css +9 -1
  34. package/components/textarea.css +7 -3
  35. package/components/toolbar.css +2 -1
  36. package/components/tooltip.css +12 -0
  37. package/components/transfer-list.css +5 -1
  38. package/components/virtual-scroller.css +7 -0
  39. package/components.css +6 -1
  40. package/css-components/button.css +66 -0
  41. package/css-components/card.css +14 -0
  42. package/css-components/chip-group.css +9 -0
  43. package/css-components/chip.css +80 -0
  44. package/css-components/disclosure.css +25 -0
  45. package/css-components/list.css +34 -0
  46. package/css-components/select.css +20 -0
  47. package/css-components/textarea.css +22 -0
  48. package/css-components.css +31 -0
  49. package/defaults.css +189 -3
  50. package/native.css +258 -0
  51. package/package.json +20 -6
  52. package/state-layer.css +5 -1
package/README.md CHANGED
@@ -34,6 +34,30 @@ Selective component styles are also exported:
34
34
  @import '@rcarls/rc-theme-material/components/menu.css';
35
35
  ```
36
36
 
37
+ Native HTML can opt into the same presentation without registering an RC
38
+ element. Import the defaults and bridge when needed, then opt into the native
39
+ layer and the CSS-only recipes independently:
40
+
41
+ ```css
42
+ @import '@rcarls/rc-theme-material/defaults.css';
43
+ @import '@rcarls/rc-theme-material/bridge.css';
44
+ @import '@rcarls/rc-theme-material/native.css';
45
+ @import '@rcarls/rc-theme-material/css-components.css';
46
+ ```
47
+
48
+ `native.css` is an optional convenience layer for giving ordinary buttons, text
49
+ fields, selects, textareas, checkboxes, radios, ranges, and progress controls a
50
+ Material treatment throughout `.rc-theme-material`. Component recipes style
51
+ native children when their presentation belongs to a themed menu, toolbar, or
52
+ other component context. Add `data-rc-native="off"` to an element to opt it and
53
+ its descendants out of the native layer. The
54
+ opt-in `css-components.css` recipes cover `.rc-button`, `.rc-chip`,
55
+ `.rc-chip-group`, `.rc-select`, `.rc-textarea`, `.rc-card`, `.rc-list`, and
56
+ `details.rc-disclosure`; each recipe is also available under
57
+ `css-components/<name>.css`. These styles provide appearance and CSS-visible
58
+ states only: they do not add behavior, events, popup replacement, or measured
59
+ overflow.
60
+
37
61
  The state-layer utility is included by `components.css` and `theme.css`, and is
38
62
  also exported separately for selective imports:
39
63
 
@@ -59,6 +83,9 @@ The default `rc-button` treatment is filled. Use `rc-button--tonal`,
59
83
  levels. Icon-only buttons use `rc-icon-button--standard`,
60
84
  `rc-icon-button--tonal`, or `rc-icon-button--outlined`.
61
85
 
86
+ `rc-field` uses the Material 3 filled text-field treatment by default. Add
87
+ `rc-field--outlined` for the outlined variant.
88
+
62
89
  Add `data-tone="danger"` to any of those variants for the corresponding error
63
90
  or error-container color roles. These classes and data attributes are theme
64
91
  hooks; they do not change the component's native-button behavior or public API.
@@ -82,6 +109,23 @@ bridge and component style layers:
82
109
  @import '@rcarls/rc-theme-material/theme.css';
83
110
  ```
84
111
 
112
+ ## Designing with the theme
113
+
114
+ [`DESIGN.md`](./DESIGN.md) is a Material 3 composition guide written for AI
115
+ coding agents. It covers which component fills which Material role, adaptive
116
+ layouts by window size class, dialogs, sheets, lists, navigation and
117
+ feedback, with the baseline token values in machine-readable front matter. It
118
+ ships in the package and is exported as `@rcarls/rc-theme-material/DESIGN.md`,
119
+ so agents in a consuming app can read it from `node_modules`, or under Yarn
120
+ Plug'n'Play with:
121
+
122
+ ```sh
123
+ yarn node -e "process.stdout.write(require('fs').readFileSync(require.resolve('@rcarls/rc-theme-material/DESIGN.md'), 'utf8'))"
124
+ ```
125
+
126
+ App design documents should reference it for Material 3 composition and keep
127
+ only their own overrides, branding and product patterns.
128
+
85
129
  ## Theming scope
86
130
 
87
131
  The full style layer styles native controls when their intent is established by
@@ -91,11 +135,50 @@ unrelated application controls and follows design-token conventions.
91
135
  Fonts and icons are not bundled; websites and applications may provide
92
136
  [Roboto](https://fonts.google.com/specimen/Roboto) and
93
137
  [Material Symbols](https://fonts.google.com/icons) through other means.
94
- Tag general icon-font markup with `data-rc-icon`; component-specific markers
95
- such as `data-rc-button-icon` and `data-rc-navigation-icon` opt in
96
- automatically. The shared `--rc-icon-font-size` and
97
- `--rc-icon-font-line-height` tokens keep glyph geometry consistent and can be
98
- overridden at the theme boundary or on one component.
138
+
139
+ ### Scoped type scale
140
+
141
+ Mark a region with `data-rc-type-scale` and set `--rc-type-scale` to enlarge or
142
+ shrink its text, such as a reading view used at arm's length. Every Material type
143
+ size and line height beneath the marked element, and the RC text tokens built on
144
+ them, are multiplied by the factor. Text outside the region is unchanged.
145
+
146
+ ```html
147
+ <main data-rc-type-scale style="--rc-type-scale: 1.25">…</main>
148
+ ```
149
+
150
+ Marking the theme root itself scales the whole page, for an app-wide text size
151
+ setting. A nested marked region uses its own `--rc-type-scale`; to compound it
152
+ with a page-wide factor, keep that factor in a separate custom property and
153
+ multiply, since a property can't refer to its own inherited value:
154
+
155
+ ```html
156
+ <html
157
+ class="rc-theme-material"
158
+ data-rc-type-scale
159
+ style="--app-scale: 0.75; --rc-type-scale: var(--app-scale)"
160
+ >
161
+ …
162
+ <p data-rc-type-scale style="--rc-type-scale: calc(var(--app-scale) * 1.25)">…</p>
163
+ </html>
164
+ ```
165
+
166
+ With `theme.css`, the Material type tokens and RC text tokens scale from the
167
+ bundled `defaults.css` values. With `bridge.css` alone, RC text tokens scale from
168
+ the application's Material type tokens; the application's own
169
+ `--md-sys-typescale-*` tokens remain unchanged. Supply both size and line-height
170
+ tokens for the roles used by RC components when customizing the bridge. If your
171
+ Material token environment also defines matching `*-size-value` or
172
+ `*-line-height-value` source tokens, those are the scale baseline; update them
173
+ alongside branded final values.
174
+
175
+ ### Icon font wiring
176
+
177
+ The theme sizes and centers icon markers but never sets `font-family` on them,
178
+ because no font ships with it. Until the application supplies one, a marker
179
+ renders its literal text, so a navigation toggle shows the word `menu`. See
180
+ [Fonts and icons](./DESIGN.md#fonts-and-icons) in the design guide for the
181
+ one rule that wires every marker.
99
182
 
100
183
  ### Icon-button modifiers
101
184
 
package/bridge.css CHANGED
@@ -1,4 +1,5 @@
1
- @layer rc-theme-material.defaults, rc-theme-material.bridge, rc-theme-material.components;
1
+ @layer rc-base, rc-theme-material.defaults, rc-theme-material.bridge, rc-theme-material.native, rc-theme-material.components, rc-theme-material.css-components,
2
+ rc-theme-material.overrides;
2
3
 
3
4
  @layer rc-theme-material.bridge {
4
5
  /*
@@ -34,6 +35,31 @@
34
35
  calc(var(--md-sys-elevation-level4, 8px) * 2)
35
36
  color-mix(in srgb, var(--md-sys-color-shadow, #000) 24%, transparent);
36
37
  --rc-shadow: var(--rc-shadow-level2);
38
+ /*
39
+ * Menus, select and combobox listboxes, and adaptive-menu popups share the
40
+ * MD3 menu container. Set here rather than per element so the values also
41
+ * inherit into popups rendered inside other shadow roots.
42
+ */
43
+ --rc-popup-background: var(
44
+ --md-menu-container-color,
45
+ var(--md-sys-color-surface-container, Canvas)
46
+ );
47
+ --rc-popup-color: var(--md-sys-color-on-surface, CanvasText);
48
+ --rc-popup-border: 0;
49
+ --rc-popup-radius: var(
50
+ --md-menu-container-shape,
51
+ var(--md-sys-shape-corner-extra-small, 0.25rem)
52
+ );
53
+ --rc-popup-shadow: var(--rc-shadow);
54
+ --rc-adaptive-menu-popup-shadow: 0 1px 2px rgb(0 0 0 / 30%), 0 2px 6px 2px rgb(0 0 0 / 15%);
55
+ --rc-popup-padding-block: 0.5rem;
56
+ /* Menu, listbox, and adaptive-menu items use the MD3 body-large scale. */
57
+ --rc-item-font-family: var(--md-sys-typescale-body-large-font, inherit);
58
+ --rc-item-font-size: var(--md-sys-typescale-body-large-size, 1rem);
59
+ --rc-item-font-weight: var(--md-sys-typescale-body-large-weight, 400);
60
+ --rc-item-line-height: var(--md-sys-typescale-body-large-line-height, 1.5rem);
61
+ --rc-item-letter-spacing: var(--md-sys-typescale-body-large-tracking, 0.03125rem);
62
+ --rc-item-icon-size: 1.5rem;
37
63
  --rc-font-family: var(--md-sys-typescale-body-medium-font, inherit);
38
64
  --rc-font-size: var(--md-sys-typescale-body-medium-size, 0.875rem);
39
65
  --rc-line-height: var(--md-sys-typescale-body-medium-line-height, 1.25rem);
@@ -51,7 +77,14 @@
51
77
  --rc-list-item-selected-bg: var(--md-sys-color-secondary-container, Highlight);
52
78
  --rc-list-item-selected-color: var(--md-sys-color-on-secondary-container, HighlightText);
53
79
  --rc-button-bg: var(--md-sys-color-primary, ButtonFace);
54
- --rc-button-color: var(--md-sys-color-on-primary, ButtonText);
80
+ /*
81
+ * Both of these sit on --rc-button-bg, so both take the on-primary color.
82
+ * rc-select, rc-combobox, and rc-menu-button read --rc-button-text directly
83
+ * for their trigger and chip text; leaving it unset dropped them onto the
84
+ * ButtonText system color over the primary fill.
85
+ */
86
+ --rc-button-text: var(--md-sys-color-on-primary, ButtonText);
87
+ --rc-button-color: var(--rc-button-text, ButtonText);
55
88
  --rc-button-block-size: var(--rc-control-block-size);
56
89
  --rc-button-radius: var(--rc-control-radius);
57
90
  --rc-button-border: 0;
@@ -122,27 +155,38 @@
122
155
  --rc-focus-ring-offset: 2px;
123
156
  --rc-disabled-opacity: var(--md-sys-state-disabled-state-layer-opacity, 0.38);
124
157
  --rc-motion-effects-duration-fast: var(--md-sys-motion-duration-150, 150ms);
125
- --rc-motion-effects-easing-fast: cubic-bezier(
126
- var(--md-sys-motion-easing-standard-x0, 0.2),
127
- var(--md-sys-motion-easing-standard-y0, 0),
128
- var(--md-sys-motion-easing-standard-x1, 0),
129
- var(--md-sys-motion-easing-standard-y1, 1)
130
- );
158
+ --rc-motion-effects-easing-fast: var(--md-sys-motion-easing-standard, ease-out);
131
159
  --rc-motion-effects-duration-default: var(--md-sys-motion-duration-200, 200ms);
132
160
  --rc-motion-effects-easing-default: var(--rc-motion-effects-easing-fast);
133
161
  --rc-motion-effects-duration-slow: var(--md-sys-motion-duration-300, 300ms);
134
162
  --rc-motion-effects-easing-slow: var(--rc-motion-effects-easing-fast);
135
- --rc-motion-spatial-duration-fast: var(--md-sys-motion-duration-350, 350ms);
136
- --rc-motion-spatial-easing-fast: cubic-bezier(
137
- var(--md-sys-motion-easing-emphasized-x0, 0.2),
138
- var(--md-sys-motion-easing-emphasized-y0, 0),
139
- var(--md-sys-motion-easing-emphasized-x1, 0),
140
- var(--md-sys-motion-easing-emphasized-y1, 1)
141
- );
142
- --rc-motion-spatial-duration-default: var(--md-sys-motion-duration-500, 500ms);
163
+ /*
164
+ * Spec spatial durations are 350/500/700ms. This project's own motion
165
+ * guide finds anything past ~400ms reads as waiting rather than
166
+ * feedback, so the scale is compressed to 300/400/500ms — a deliberate
167
+ * departure recorded here rather than a silent guess. The curve shape
168
+ * (emphasized) is unchanged from spec.
169
+ */
170
+ --rc-motion-spatial-duration-fast: var(--md-sys-motion-duration-medium2, 300ms);
171
+ --rc-motion-spatial-easing-fast: var(
172
+ --md-sys-motion-easing-emphasized,
173
+ cubic-bezier(0.2, 0, 0, 1)
174
+ );
175
+ --rc-motion-spatial-duration-default: var(--md-sys-motion-duration-medium4, 400ms);
143
176
  --rc-motion-spatial-easing-default: var(--rc-motion-spatial-easing-fast);
144
- --rc-motion-spatial-duration-slow: var(--md-sys-motion-duration-700, 700ms);
177
+ --rc-motion-spatial-duration-slow: var(--md-sys-motion-duration-long2, 500ms);
145
178
  --rc-motion-spatial-easing-slow: var(--rc-motion-spatial-easing-fast);
179
+ /* Decelerate for arriving, accelerate for leaving; family matches above. */
180
+ --rc-motion-effects-easing-enter: var(--md-sys-motion-easing-standard-decelerate, ease-out);
181
+ --rc-motion-effects-easing-exit: var(--md-sys-motion-easing-standard-accelerate, ease-in);
182
+ --rc-motion-spatial-easing-enter: var(
183
+ --md-sys-motion-easing-emphasized-decelerate,
184
+ cubic-bezier(0, 0, 0, 1)
185
+ );
186
+ --rc-motion-spatial-easing-exit: var(
187
+ --md-sys-motion-easing-emphasized-accelerate,
188
+ cubic-bezier(0.3, 0, 1, 1)
189
+ );
146
190
  --rc-motion-duration: var(--rc-motion-effects-duration-default);
147
191
  --rc-dialog-scrim: color-mix(in srgb, var(--md-sys-color-scrim, #000) 32%, transparent);
148
192
  }
@@ -157,16 +201,9 @@
157
201
  );
158
202
  --rc-select-border: 1px solid
159
203
  var(--md-outlined-select-text-field-outline-color, var(--md-sys-color-outline, ButtonBorder));
160
- --rc-select-listbox-radius: var(
161
- --md-menu-container-shape,
162
- var(--md-sys-shape-corner-extra-small, 0.25rem)
163
- );
164
- --rc-select-listbox-border: 0;
165
- --rc-select-listbox-padding-block: 0.5rem;
166
- --rc-select-shadow: var(--rc-shadow);
167
204
  --rc-select-chip-radius: var(--md-sys-shape-corner-small, 0.5rem);
168
- --rc-select-chip-padding-block: 0.375rem;
169
- --rc-select-chip-padding-inline: 0.75rem;
205
+ --rc-select-chip-padding-block: 0;
206
+ --rc-select-chip-padding-inline-start: 0.75rem;
170
207
  --rc-field: var(
171
208
  --md-outlined-select-text-field-container-color,
172
209
  var(--md-sys-color-surface, Field)
@@ -215,16 +252,9 @@
215
252
  );
216
253
  --rc-combobox-border: 1px solid
217
254
  var(--md-outlined-text-field-outline-color, var(--md-sys-color-outline, ButtonBorder));
218
- --rc-combobox-listbox-radius: var(
219
- --md-menu-container-shape,
220
- var(--md-sys-shape-corner-extra-small, 0.25rem)
221
- );
222
- --rc-combobox-listbox-border: 0;
223
- --rc-combobox-listbox-padding-block: 0.5rem;
224
- --rc-combobox-shadow: var(--rc-shadow);
225
255
  --rc-combobox-chip-radius: var(--md-sys-shape-corner-small, 0.5rem);
226
- --rc-combobox-chip-padding-block: 0.375rem;
227
- --rc-combobox-chip-padding-inline: 0.75rem;
256
+ --rc-combobox-chip-padding-block: 0;
257
+ --rc-combobox-chip-padding-inline-start: 0.75rem;
228
258
  --rc-field: var(--md-outlined-text-field-container-color, var(--md-sys-color-surface, Field));
229
259
  --rc-field-text: var(
230
260
  --md-outlined-text-field-input-text-color,
@@ -408,19 +438,9 @@
408
438
  );
409
439
  }
410
440
 
411
- .rc-theme-material rc-menu,
412
- :host(.rc-theme-material) rc-menu {
413
- --rc-menu-padding-block: 0.5rem;
414
- --rc-menu-background: var(
415
- --md-menu-container-color,
416
- var(--md-sys-color-surface-container, Canvas)
417
- );
418
- --rc-menu-border: 0;
419
- --rc-menu-radius: var(
420
- --md-menu-container-shape,
421
- var(--md-sys-shape-corner-extra-small, 0.25rem)
422
- );
423
- --rc-menu-shadow: var(--rc-shadow);
441
+ /* Declared on the theme root so menus inside other shadow roots inherit it. */
442
+ .rc-theme-material,
443
+ :host(.rc-theme-material) {
424
444
  --rc-menu-color: var(
425
445
  --md-menu-item-label-text-color,
426
446
  var(--md-sys-color-on-surface, CanvasText)
@@ -529,10 +549,10 @@
529
549
 
530
550
  .rc-theme-material rc-markdown-editor,
531
551
  :host(.rc-theme-material) rc-markdown-editor {
532
- --rme-background: var(--md-sys-color-surface, Canvas);
533
- --rme-color: var(--md-sys-color-on-surface, CanvasText);
534
- --rme-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
535
- --rme-focus-outline: 2px solid var(--md-sys-color-primary, Highlight);
552
+ --rc-markdown-editor-background: var(--md-sys-color-surface, Canvas);
553
+ --rc-markdown-editor-color: var(--md-sys-color-on-surface, CanvasText);
554
+ --rc-markdown-editor-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
555
+ --rc-markdown-editor-focus-outline: 2px solid var(--md-sys-color-primary, Highlight);
536
556
  }
537
557
 
538
558
  .rc-theme-material rc-transfer-list,
@@ -558,9 +578,6 @@
558
578
  --rc-navigation-rail-item-text-decoration: none;
559
579
  --rc-navigation-rail-indicator-bg: var(--md-sys-color-secondary-container, Highlight);
560
580
  --rc-navigation-rail-indicator-border: 0;
561
- --rc-navigation-rail-toggle-padding: 0;
562
- --rc-navigation-rail-toggle-border: 0;
563
- --rc-navigation-rail-toggle-font: inherit;
564
581
  }
565
582
  .rc-theme-material rc-navigation-rail > rc-fab[slot='header'],
566
583
  :host(.rc-theme-material) rc-navigation-rail > rc-fab[slot='header'] {
@@ -633,6 +650,65 @@
633
650
  );
634
651
  }
635
652
 
653
+ /*
654
+ * Scale RC text from the unscaled Material values. The bundled defaults
655
+ * expose *-value tokens; bridge-only consumers can supply Material type
656
+ * tokens, which the bridge leaves unchanged.
657
+ */
658
+ /* A marked theme root itself must outrank its own token rule above. */
659
+ :where(.rc-theme-material [data-rc-type-scale], :host(.rc-theme-material) [data-rc-type-scale]),
660
+ .rc-theme-material[data-rc-type-scale],
661
+ :host(.rc-theme-material[data-rc-type-scale]) {
662
+ --rc-item-font-size: calc(
663
+ var(--md-sys-typescale-body-large-size-value, var(--md-sys-typescale-body-large-size, 1rem)) *
664
+ var(--rc-type-scale, 1)
665
+ );
666
+ --rc-item-line-height: calc(
667
+ var(
668
+ --md-sys-typescale-body-large-line-height-value,
669
+ var(--md-sys-typescale-body-large-line-height, 1.5rem)
670
+ ) *
671
+ var(--rc-type-scale, 1)
672
+ );
673
+ --rc-font-size: calc(
674
+ var(
675
+ --md-sys-typescale-body-medium-size-value,
676
+ var(--md-sys-typescale-body-medium-size, 0.875rem)
677
+ ) *
678
+ var(--rc-type-scale, 1)
679
+ );
680
+ --rc-line-height: calc(
681
+ var(
682
+ --md-sys-typescale-body-medium-line-height-value,
683
+ var(--md-sys-typescale-body-medium-line-height, 1.25rem)
684
+ ) *
685
+ var(--rc-type-scale, 1)
686
+ );
687
+ --rc-button-font: 500
688
+ calc(
689
+ var(
690
+ --md-sys-typescale-label-large-size-value,
691
+ var(--md-sys-typescale-label-large-size, 0.875rem)
692
+ ) *
693
+ var(--rc-type-scale, 1)
694
+ ) /
695
+ calc(
696
+ var(
697
+ --md-sys-typescale-label-large-line-height-value,
698
+ var(--md-sys-typescale-label-large-line-height, 1.25rem)
699
+ ) *
700
+ var(--rc-type-scale, 1)
701
+ )
702
+ var(--rc-font-family);
703
+ --rc-menu-shortcut-size: calc(
704
+ var(
705
+ --md-sys-typescale-label-large-size-value,
706
+ var(--md-sys-typescale-label-large-size, 0.875rem)
707
+ ) *
708
+ var(--rc-type-scale, 1)
709
+ );
710
+ }
711
+
636
712
  @media (forced-colors: active) {
637
713
  .rc-theme-material,
638
714
  :host(.rc-theme-material) {
@@ -641,6 +717,7 @@
641
717
  --rc-shadow-level2: none;
642
718
  --rc-shadow-level3: none;
643
719
  --rc-shadow: none;
720
+ --rc-popup-border: 1px solid ButtonBorder;
644
721
  --rc-disabled-opacity: 1;
645
722
  }
646
723
 
@@ -1,181 +1,67 @@
1
1
  @layer rc-theme-material.components {
2
+ /*
3
+ * Only the group box and the panel shapes. Panels inside an accordion take
4
+ * the same `--rc-disclosure-*` mapping as a standalone disclosure, which
5
+ * disclosure.css sets for `rc-accordion` as well, so the panel recipe is not
6
+ * repeated here.
7
+ */
2
8
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion {
9
+ /*
10
+ * Grouped like a segmented `rc-list`: a 2px gap, no outline, extra-small
11
+ * inner corners, and extra-large outer corners on the first and last panel,
12
+ * so an accordion reads as one expandable list rather than a card stack.
13
+ */
14
+ --rc-accordion-gap: 0.125rem;
15
+
16
+ /* Laid out before the element upgrades; see disclosure.css. */
3
17
  display: grid;
4
- gap: 0.5rem;
18
+ gap: var(--rc-accordion-gap, 0.125rem);
5
19
  border: 0;
6
20
  background: transparent;
7
- --rc-theme-material-accordion-easing: cubic-bezier(
8
- var(--md-sys-motion-easing-standard-x0, 0.2),
9
- var(--md-sys-motion-easing-standard-y0, 0),
10
- var(--md-sys-motion-easing-standard-x1, 0),
11
- var(--md-sys-motion-easing-standard-y1, 1)
12
- );
13
21
  }
14
22
 
15
23
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > rc-disclosure {
16
24
  display: block;
17
25
  }
18
26
 
19
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details,
20
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > rc-disclosure > details {
21
- overflow: clip;
22
- border: 1px solid var(--md-sys-color-outline-variant, ButtonBorder);
23
- border-radius: var(--md-sys-shape-corner-large, 1rem);
24
- background: var(--md-sys-color-surface-container-low, Canvas);
25
- color: var(--md-sys-color-on-surface, CanvasText);
26
- transition:
27
- background-color var(--md-sys-motion-duration-200, 200ms)
28
- var(--rc-theme-material-accordion-easing),
29
- border-color var(--md-sys-motion-duration-200, 200ms)
30
- var(--rc-theme-material-accordion-easing),
31
- box-shadow var(--md-sys-motion-duration-200, 200ms) var(--rc-theme-material-accordion-easing);
32
- }
33
-
34
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details[open],
35
- :where(.rc-theme-material, :host(.rc-theme-material))
36
- rc-accordion
37
- > rc-disclosure
38
- > details[open] {
39
- background: var(--md-sys-color-surface-container, Canvas);
40
- box-shadow: var(
41
- --rc-shadow-level1,
42
- 0 1px 2px 0 rgb(0 0 0 / 0.3),
43
- 0 1px 3px 1px rgb(0 0 0 / 0.15)
44
- );
45
- }
46
-
47
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details > summary,
48
- :where(.rc-theme-material, :host(.rc-theme-material))
49
- rc-accordion
50
- > rc-disclosure
51
- > details
52
- > summary {
53
- display: grid;
54
- grid-template-columns: minmax(0, 1fr);
55
- align-items: center;
56
- box-sizing: border-box;
57
- min-block-size: 3.5rem;
58
- padding-block: 0.75rem;
59
- padding-inline: 1rem;
60
- border-radius: calc(var(--md-sys-shape-corner-large, 1rem) - 1px);
61
- color: var(--md-sys-color-on-surface, CanvasText);
62
- cursor: pointer;
63
- font-family: var(--md-sys-typescale-title-small-font, inherit);
64
- font-size: var(--md-sys-typescale-title-small-size, 0.875rem);
65
- font-weight: var(--md-sys-typescale-title-small-weight, 500);
66
- line-height: var(--md-sys-typescale-title-small-line-height, 1.25rem);
67
- transition: background-color var(--md-sys-motion-duration-100, 100ms)
68
- var(--rc-theme-material-accordion-easing);
69
- }
70
-
71
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details > summary::marker,
72
- :where(.rc-theme-material, :host(.rc-theme-material))
73
- rc-accordion
74
- > rc-disclosure
75
- > details
76
- > summary::marker {
77
- color: var(--md-sys-color-on-surface-variant, GrayText);
78
- }
79
-
80
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details > summary:hover,
81
- :where(.rc-theme-material, :host(.rc-theme-material))
82
- rc-accordion
83
- > rc-disclosure
84
- > details
85
- > summary:hover {
86
- background: color-mix(in srgb, var(--md-sys-color-on-surface, CanvasText) 8%, transparent);
87
- background: color-mix(
88
- in srgb,
89
- var(--md-sys-color-on-surface, CanvasText)
90
- calc(var(--md-sys-state-hover-state-layer-opacity, 0.08) * 100%),
91
- transparent
92
- );
27
+ /*
28
+ * Set on the items, not inherited from the group: disclosure.css maps the
29
+ * standalone outline and radius onto every `rc-disclosure`, wrapped or not.
30
+ */
31
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > :is(rc-disclosure, details) {
32
+ --rc-disclosure-border: 0;
33
+ --rc-disclosure-radius: var(--md-sys-shape-corner-extra-small, 0.25rem);
93
34
  }
94
35
 
36
+ /* Shape both the native panel and its summary hover surface at logical ends. */
95
37
  :where(.rc-theme-material, :host(.rc-theme-material))
96
- rc-accordion
97
- > details
98
- > summary:focus-visible,
99
- :where(.rc-theme-material, :host(.rc-theme-material))
100
- rc-accordion
101
- > rc-disclosure
102
- > details
103
- > summary:focus-visible {
104
- outline: var(--rc-focus-ring, 2px solid Highlight);
105
- outline-offset: -2px;
38
+ :is(
39
+ rc-accordion > details:first-child,
40
+ rc-accordion > details:first-child > summary,
41
+ rc-accordion > rc-disclosure:first-child > details,
42
+ rc-accordion > rc-disclosure:first-child > details > summary
43
+ ) {
44
+ border-start-start-radius: var(--md-sys-shape-corner-extra-large, 1.75rem);
45
+ border-start-end-radius: var(--md-sys-shape-corner-extra-large, 1.75rem);
106
46
  }
107
47
 
108
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details > :not(summary),
109
48
  :where(.rc-theme-material, :host(.rc-theme-material))
110
- rc-accordion
111
- > rc-disclosure
112
- > details
113
- > :not(summary) {
114
- box-sizing: border-box;
115
- max-block-size: 0;
116
- overflow: clip;
117
- padding-block: 0;
118
- padding-inline: 1rem;
119
- color: var(--md-sys-color-on-surface-variant, CanvasText);
120
- font-family: var(--md-sys-typescale-body-medium-font, inherit);
121
- font-size: var(--md-sys-typescale-body-medium-size, 0.875rem);
122
- line-height: var(--md-sys-typescale-body-medium-line-height, 1.25rem);
123
- opacity: 0;
124
- transition:
125
- max-block-size var(--md-sys-motion-duration-300, 300ms)
126
- var(--rc-theme-material-accordion-easing),
127
- opacity var(--md-sys-motion-duration-200, 200ms) var(--rc-theme-material-accordion-easing),
128
- padding-block var(--md-sys-motion-duration-200, 200ms)
129
- var(--rc-theme-material-accordion-easing);
49
+ :is(
50
+ rc-accordion > details:last-child,
51
+ rc-accordion > details:last-child > summary,
52
+ rc-accordion > rc-disclosure:last-child > details,
53
+ rc-accordion > rc-disclosure:last-child > details > summary
54
+ ) {
55
+ border-end-start-radius: var(--md-sys-shape-corner-extra-large, 1.75rem);
56
+ border-end-end-radius: var(--md-sys-shape-corner-extra-large, 1.75rem);
130
57
  }
131
58
 
132
- :where(.rc-theme-material, :host(.rc-theme-material))
133
- rc-accordion
134
- > details[open]
135
- > :not(summary),
136
- :where(.rc-theme-material, :host(.rc-theme-material))
137
- rc-accordion
138
- > rc-disclosure
139
- > details[open]
140
- > :not(summary) {
141
- max-block-size: 60rem;
142
- padding-block: 0 1rem;
143
- opacity: 1;
144
- }
145
-
146
- @supports (transition-behavior: allow-discrete) {
147
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details > :not(summary),
148
- :where(.rc-theme-material, :host(.rc-theme-material))
149
- rc-accordion
150
- > rc-disclosure
151
- > details
152
- > :not(summary) {
153
- transition:
154
- content-visibility var(--md-sys-motion-duration-300, 300ms) allow-discrete,
155
- max-block-size var(--md-sys-motion-duration-300, 300ms)
156
- var(--rc-theme-material-accordion-easing),
157
- opacity var(--md-sys-motion-duration-200, 200ms) var(--rc-theme-material-accordion-easing),
158
- padding-block var(--md-sys-motion-duration-200, 200ms)
159
- var(--rc-theme-material-accordion-easing);
160
- }
161
- }
162
-
163
- @media (prefers-reduced-motion: reduce) {
164
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details,
165
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > rc-disclosure > details,
166
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details > summary,
167
- :where(.rc-theme-material, :host(.rc-theme-material))
168
- rc-accordion
169
- > rc-disclosure
170
- > details
171
- > summary,
172
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-accordion > details > :not(summary),
59
+ /* Without the surface fills, gaps alone would not separate the panels. */
60
+ @media (forced-colors: active) {
173
61
  :where(.rc-theme-material, :host(.rc-theme-material))
174
62
  rc-accordion
175
- > rc-disclosure
176
- > details
177
- > :not(summary) {
178
- transition-duration: 0ms;
63
+ > :is(rc-disclosure, details) {
64
+ --rc-disclosure-border: 1px solid CanvasText;
179
65
  }
180
66
  }
181
67
  }