@rcarls/rc-theme-material 0.4.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,63 @@
1
1
  # @rcarls/rc-theme-material
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ffcbf11: Add adaptive chip-group layouts, native-backed filter chips, and shared
8
+ input-chip rendering. Native-backed chips preserve controlled host state,
9
+ follow form resets when uncontrolled, and accept native link actions. Groups
10
+ restore author-owned chip variants when coordination ends. Keep search input
11
+ chrome inside the search surface and align contextual icon sizes with Material 3.
12
+ - 40f9776: Add an APG carousel built on native CSS scroll snap, with optional navigation,
13
+ pagination, mouse dragging, looping, and consumer-controlled slide sizing.
14
+ Preserve controlled active-index behavior after rejected swipes, keep visual
15
+ loop clones inert and out of forms, and degrade safely without intersection
16
+ observation.
17
+ - a108336: Add shared-column `rc-list` and `rc-list-item` elements with standard and
18
+ segmented appearances, default content truncation, and native-backed single or
19
+ multiple selection coordination. Restore author-owned item state when native
20
+ selection coordination ends.
21
+ - 509ee64: Add `rc-progress`, a native `<progress>` enhancer with a formatted value
22
+ display, a track and fill you can restyle with CSS custom properties, and a
23
+ built-in fix for the indeterminate/undefined-binding footgun.
24
+
25
+ Keep the native element as the uncontrolled source of truth, support releasing
26
+ a controlled value, and react to live native `value`/`max` changes. Preserve a
27
+ native determinate value while `indeterminate` temporarily removes its
28
+ attribute.
29
+
30
+ The bar renders at its intended height with no `display` attribute set,
31
+ matching its own documented default: previously the track/fill/native
32
+ `<progress>` are all absolutely positioned, contributing nothing to the
33
+ control's normal-flow height, so with no value-display text sharing its grid
34
+ row to give it one, the whole bar collapsed to 0px.
35
+
36
+ - d67efde: Add a native-host scroll region with optional centered content and fullbleed
37
+ layout tracks, aggregate framework typings, RTL-aware boundary state, and
38
+ Material layout defaults.
39
+ - 6d3b478: Add Material button emphasis, danger-tone, icon sizing, and adaptive-menu
40
+ contracts. Complete the bundled surface-role palette and forced-colors mappings.
41
+ - 30eb232: Add icon-only activation-area sizing and Material icon-button variants. Align menu
42
+ selection and submenu affordances, and keep anchored popups within the viewport
43
+ across native and fallback positioning.
44
+ - 6d3b478: Default the new touch-target overlap tokens for MD3's own dense/narrow
45
+ icon-button and overflow-trigger conventions: `rc-button`'s and
46
+ `rc-menu-button`'s narrow variant (where the icon is smaller than the
47
+ default 3rem touch target) now reclaim the trailing edge automatically,
48
+ and `rc-adaptive-menu`'s overflow trigger, always the trailing-most
49
+ control in its toolbar by design, does the same unconditionally. Only the
50
+ trailing edge defaults, matching each component's own documented
51
+ "trailing overflow trigger" use case; the leading edge stays an explicit
52
+ opt-in.
53
+
54
+ ### Patch Changes
55
+
56
+ - 6d3b478: Keep generic dialog button styles out of custom control wrappers, support nested
57
+ bottom-sheet handles, and expose the Material disabled-button opacity token.
58
+
59
+ ## 0.5.0
60
+
3
61
  ## 0.4.2
4
62
 
5
63
  ## 0.4.1
package/README.md CHANGED
@@ -52,6 +52,27 @@ Theme styles are scoped under a `.rc-theme-material` class.
52
52
  </body>
53
53
  ```
54
54
 
55
+ ### Button variants and tones
56
+
57
+ The default `rc-button` treatment is filled. Use `rc-button--tonal`,
58
+ `rc-button--outlined`, or `rc-button--text` for the other Material emphasis
59
+ levels. Icon-only buttons use `rc-icon-button--standard`,
60
+ `rc-icon-button--tonal`, or `rc-icon-button--outlined`.
61
+
62
+ Add `data-tone="danger"` to any of those variants for the corresponding error
63
+ or error-container color roles. These classes and data attributes are theme
64
+ hooks; they do not change the component's native-button behavior or public API.
65
+
66
+ ```html
67
+ <rc-button class="rc-button--tonal">
68
+ <button type="button">Save draft</button>
69
+ </rc-button>
70
+
71
+ <rc-button class="rc-button--outlined" data-tone="danger">
72
+ <button type="button">Delete</button>
73
+ </rc-button>
74
+ ```
75
+
55
76
  ### Full standalone Material 3 theme
56
77
 
57
78
  Includes bundled light and dark Material 3 token defaults and the full
@@ -76,6 +97,35 @@ automatically. The shared `--rc-icon-font-size` and
76
97
  `--rc-icon-font-line-height` tokens keep glyph geometry consistent and can be
77
98
  overridden at the theme boundary or on one component.
78
99
 
100
+ ### Icon-button modifiers
101
+
102
+ Apply these classes to `rc-button[icon-only]` to use the Material 3 expressive
103
+ container and icon sizes. The default, unmodified size is small: a `2.5rem`
104
+ container with a `1.5rem` icon.
105
+
106
+ | Class | Container | Icon |
107
+ | ------------------------ | --------: | --------: |
108
+ | `rc-button--extra-small` | `2rem` | `1.25rem` |
109
+ | `rc-button--medium` | `3.5rem` | `1.5rem` |
110
+ | `rc-button--large` | `6rem` | `2rem` |
111
+ | `rc-button--extra-large` | `8.5rem` | `2.5rem` |
112
+
113
+ Combine a size class with `rc-button--narrow` or `rc-button--wide` to select
114
+ that size's narrower or wider container width without changing its height or
115
+ icon size. `rc-menu-button[icon-only]` supports `rc-menu-button--narrow` for a
116
+ `2rem`-wide small trigger. The component packages continue to reserve a `3rem`
117
+ activation area around visual containers smaller than that target.
118
+
119
+ `rc-adaptive-menu` uses the same Material small narrow geometry for its
120
+ overflow trigger: a `2rem × 2.5rem` visible container centered in the
121
+ component-owned `3rem × 3rem` activation area. The theme also aligns overflow
122
+ rows with Material menu geometry while leaving the component's controlled or
123
+ uncontrolled `open` contract unchanged.
124
+
125
+ Direct native buttons in an `rc-app-bar`'s `leading` and `trailing` slots also
126
+ receive the Material small icon-button geometry. Controls nested in an
127
+ `rc-button` or `rc-menu-button` keep their component-owned sizing.
128
+
79
129
  [Material Web](material-web.dev) token names are used where a corresponding component
80
130
  exists. Search bar and top app bar mappings follow Material 3 token terminology and
81
131
  fall back through Material system roles.
package/bridge.css CHANGED
@@ -259,6 +259,24 @@
259
259
  --rc-thumb-radius: calc(var(--md-slider-handle-width, 1.25rem) / 2);
260
260
  }
261
261
 
262
+ .rc-theme-material rc-progress,
263
+ :host(.rc-theme-material) rc-progress {
264
+ --rc-progress-track-background: var(
265
+ --md-linear-progress-track-color,
266
+ var(--md-sys-color-surface-container-highest, CanvasText)
267
+ );
268
+ --rc-progress-track-opacity: 1;
269
+ --rc-progress-track-radius: var(
270
+ --md-linear-progress-track-shape,
271
+ var(--md-sys-shape-corner-full, 999px)
272
+ );
273
+ --rc-progress-fill-background: var(
274
+ --md-linear-progress-active-indicator-color,
275
+ var(--md-sys-color-primary, Highlight)
276
+ );
277
+ --rc-progress-value-color: var(--md-sys-color-on-surface-variant, GrayText);
278
+ }
279
+
262
280
  .rc-theme-material rc-range-slider,
263
281
  :host(.rc-theme-material) rc-range-slider {
264
282
  --rc-range-slider-accent: var(
@@ -0,0 +1,162 @@
1
+ @layer rc-theme-material.components {
2
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-adaptive-menu {
3
+ --rc-adaptive-menu-gap: 0;
4
+ --rc-adaptive-menu-trigger-inline-size: 2rem;
5
+ --rc-adaptive-menu-trigger-block-size: 2.5rem;
6
+ --rc-adaptive-menu-touch-target-block-size: 3rem;
7
+ /*
8
+ * Unlike rc-button's narrow variant (opt-in, usable anywhere), the
9
+ * overflow trigger is always the trailing-most control in its toolbar
10
+ * by design -- there's no legitimate placement where something else
11
+ * needs the space this reclaims -- so this defaults unconditionally
12
+ * rather than needing its own opt-in variant. (3rem touch target - 2rem
13
+ * trigger-inline-size) / 2, matching --rc-adaptive-menu-trigger-inline-size
14
+ * above.
15
+ */
16
+ --rc-adaptive-menu-touch-target-overlap-inline-end: 0.5rem;
17
+ --rc-adaptive-menu-trigger-padding: 0.25rem;
18
+ --rc-adaptive-menu-trigger-border: 0;
19
+ --rc-adaptive-menu-trigger-radius: var(--md-sys-shape-corner-full, 9999px);
20
+ --rc-adaptive-menu-trigger-background: transparent;
21
+ --rc-adaptive-menu-trigger-color: var(--md-sys-color-on-surface-variant, ButtonText);
22
+ --rc-adaptive-menu-icon-size: 1.5rem;
23
+ --rc-adaptive-menu-popup-min-inline-size: 7rem;
24
+ --rc-adaptive-menu-popup-padding-block: 0.5rem;
25
+ --rc-adaptive-menu-popup-border: 0;
26
+ --rc-adaptive-menu-popup-radius: var(
27
+ --md-menu-container-shape,
28
+ var(--md-sys-shape-corner-extra-small, 0.25rem)
29
+ );
30
+ --rc-adaptive-menu-popup-background: var(
31
+ --md-menu-container-color,
32
+ var(--md-sys-color-surface-container, Canvas)
33
+ );
34
+ --rc-adaptive-menu-popup-color: var(--md-sys-color-on-surface, CanvasText);
35
+ --rc-adaptive-menu-popup-shadow: 0 1px 2px rgb(0 0 0 / 30%), 0 2px 6px 2px rgb(0 0 0 / 15%);
36
+ --rc-adaptive-menu-item-min-block-size: 3rem;
37
+ --rc-adaptive-menu-item-padding-block: 0;
38
+ --rc-adaptive-menu-item-padding-inline: 0.75rem;
39
+ --rc-adaptive-menu-item-gap: 0.75rem;
40
+ }
41
+
42
+ :where(.rc-theme-material, :host(.rc-theme-material))
43
+ rc-adaptive-menu::part(overflow-trigger):hover {
44
+ background: color-mix(
45
+ in srgb,
46
+ var(--md-sys-color-on-surface-variant, CanvasText)
47
+ calc(var(--md-sys-state-hover-state-layer-opacity, 0.08) * 100%),
48
+ transparent
49
+ );
50
+ }
51
+
52
+ :where(.rc-theme-material, :host(.rc-theme-material))
53
+ rc-adaptive-menu::part(overflow-trigger):focus-visible {
54
+ outline: var(--rc-focus-ring, 2px solid Highlight);
55
+ outline-offset: var(--rc-focus-ring-offset, 2px);
56
+ }
57
+
58
+ :where(.rc-theme-material, :host(.rc-theme-material))
59
+ rc-adaptive-menu
60
+ > [data-rc-action-promoted]:has([data-rc-menu-leading])
61
+ [data-rc-menu-label] {
62
+ position: absolute;
63
+ inline-size: 1px;
64
+ block-size: 1px;
65
+ padding: 0;
66
+ margin: -1px;
67
+ overflow: hidden;
68
+ clip-path: inset(50%);
69
+ white-space: nowrap;
70
+ }
71
+
72
+ :where(.rc-theme-material, :host(.rc-theme-material))
73
+ rc-adaptive-menu
74
+ > rc-menu-button[data-rc-action-promoted] {
75
+ --rc-menu-button-indicator-size: 0px;
76
+ --rc-menu-button-indicator-inset: 0px;
77
+ }
78
+
79
+ :where(.rc-theme-material, :host(.rc-theme-material))
80
+ rc-adaptive-menu
81
+ > rc-menu-button[data-rc-action-promoted]
82
+ > [slot='indicator'] {
83
+ display: none;
84
+ }
85
+
86
+ :where(.rc-theme-material, :host(.rc-theme-material))
87
+ rc-adaptive-menu
88
+ > [data-rc-action-overflowed] {
89
+ inline-size: 100%;
90
+ color: var(--md-sys-color-on-surface, CanvasText);
91
+ }
92
+
93
+ :where(.rc-theme-material, :host(.rc-theme-material))
94
+ rc-adaptive-menu
95
+ > rc-button[data-rc-action-overflowed] {
96
+ display: block;
97
+ min-inline-size: 100%;
98
+ min-block-size: 0;
99
+ --rc-button-block-size: 3rem;
100
+ --rc-button-icon-size: 100%;
101
+ --rc-button-touch-target-inline-size: 100%;
102
+ --rc-button-touch-target-block-size: 3rem;
103
+ --rc-button-padding-inline: 0.75rem;
104
+ --rc-button-padding-block: 0;
105
+ --rc-button-radius: 0;
106
+ --rc-button-bg: transparent;
107
+ --rc-button-color: var(--md-sys-color-on-surface, CanvasText);
108
+ --rc-button-border: 0;
109
+ --rc-button-state-layer-bg: var(--md-sys-color-on-surface, CanvasText);
110
+ --rc-button-progress-color: var(--md-sys-color-on-surface, CanvasText);
111
+ }
112
+
113
+ :where(.rc-theme-material, :host(.rc-theme-material))
114
+ rc-adaptive-menu
115
+ > rc-menu-button[data-rc-action-overflowed] {
116
+ display: block;
117
+ min-inline-size: 100%;
118
+ min-block-size: 0;
119
+ --rc-menu-button-trigger-block-size: 3rem;
120
+ --rc-menu-button-icon-size: 100%;
121
+ --rc-menu-button-touch-target-inline-size: 100%;
122
+ --rc-menu-button-touch-target-block-size: 3rem;
123
+ --rc-menu-button-trigger-padding-block: 0;
124
+ --rc-menu-button-trigger-padding-inline: 0.75rem;
125
+ --rc-menu-button-trigger-gap: 0.75rem;
126
+ --rc-menu-button-trigger-radius: 0;
127
+ --rc-menu-button-trigger-border: 0;
128
+ --rc-menu-button-trigger-background: transparent;
129
+ --rc-menu-button-trigger-color: var(--md-sys-color-on-surface, CanvasText);
130
+ --rc-menu-button-trigger-hover-color: var(--md-sys-color-on-surface, CanvasText);
131
+ --rc-menu-button-trigger-open-color: var(--md-sys-color-on-surface, CanvasText);
132
+ }
133
+
134
+ :where(.rc-theme-material, :host(.rc-theme-material))
135
+ rc-adaptive-menu
136
+ > rc-menu-button[data-rc-action-overflowed]
137
+ > [slot='trigger'] {
138
+ justify-content: flex-start;
139
+ inline-size: 100%;
140
+ min-inline-size: 100%;
141
+ padding-inline: 0.75rem;
142
+ }
143
+
144
+ :where(.rc-theme-material, :host(.rc-theme-material))
145
+ rc-adaptive-menu
146
+ > [data-rc-action-overflowed]
147
+ [data-rc-menu-label] {
148
+ font: var(--md-sys-typescale-body-large-weight, 400)
149
+ var(--md-sys-typescale-body-large-size, 1rem) /
150
+ var(--md-sys-typescale-body-large-line-height, 1.5rem)
151
+ var(--md-sys-typescale-body-large-font, inherit);
152
+ letter-spacing: var(--md-sys-typescale-body-large-tracking, 0.03125rem);
153
+ }
154
+
155
+ :where(.rc-theme-material, :host(.rc-theme-material))
156
+ rc-adaptive-menu
157
+ > [data-rc-action-overflowed]
158
+ [data-rc-menu-leading] {
159
+ font-size: 1.5rem;
160
+ line-height: 1.5rem;
161
+ }
162
+ }
@@ -12,19 +12,59 @@
12
12
  box-shadow: var(--rc-shadow-level2, none);
13
13
  }
14
14
 
15
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-app-bar :is(button, [role='button']) {
16
- inline-size: 3rem;
17
- block-size: 3rem;
18
- padding: 0.75rem;
15
+ /*
16
+ * A bare <button>/[role=button] dropped directly into an rc-app-bar's
17
+ * leading or trailing action slot gets full M3 icon-button treatment on
18
+ * its own — MD3 "Small" icon button: 40dp visual container / 24dp icon —
19
+ * without needing rc-button. Scoped to a *direct* child
20
+ * (`>`, not a descendant combinator): a button nested inside an
21
+ * `rc-button`/`rc-menu-button` slotted here is several levels deeper in
22
+ * the light DOM and already has its own correct sizing from that
23
+ * component's own theming; a descendant selector here would reach
24
+ * straight through and fight it.
25
+ */
26
+ :where(.rc-theme-material, :host(.rc-theme-material))
27
+ rc-app-bar
28
+ > :is(button, [role='button']):is([slot='leading'], [slot='trailing']) {
29
+ box-sizing: border-box;
30
+ position: relative;
31
+ display: inline-grid;
32
+ place-items: center;
33
+ inline-size: 2.5rem;
34
+ block-size: 2.5rem;
35
+ padding: 0;
19
36
  border: 0;
20
37
  border-radius: var(--md-sys-shape-corner-full, 999px);
21
38
  background: transparent;
22
39
  color: inherit;
23
40
  }
24
41
 
42
+ /* Accessible touch-target floor, decoupled from the visual size above —
43
+ the same affordance rc-button's own icon-only buttons provide. A
44
+ no-op once the visible button already meets or exceeds it. */
45
+ :where(.rc-theme-material, :host(.rc-theme-material))
46
+ rc-app-bar
47
+ > :is(button, [role='button']):is([slot='leading'], [slot='trailing'])::before {
48
+ content: '';
49
+ position: absolute;
50
+ inset: calc((3rem - max(100%, 2.5rem)) / -2);
51
+ }
52
+
53
+ /* Sizes the button's own content (typically a single icon) to the MD3
54
+ icon-button glyph size, regardless of whether it carries a marker
55
+ attribute — a direct child of an app-bar action button is
56
+ unambiguously its icon. */
57
+ :where(.rc-theme-material, :host(.rc-theme-material))
58
+ rc-app-bar
59
+ > :is(button, [role='button']):is([slot='leading'], [slot='trailing'])
60
+ > * {
61
+ font-size: 1.5rem;
62
+ line-height: 1.5rem;
63
+ }
64
+
25
65
  :where(.rc-theme-material, :host(.rc-theme-material))
26
66
  rc-app-bar
27
- :is(button, [role='button']):hover {
67
+ > :is(button, [role='button']):is([slot='leading'], [slot='trailing']):hover {
28
68
  background: color-mix(in srgb, var(--md-sys-color-on-surface, CanvasText) 8%, transparent);
29
69
  }
30
70
 
@@ -1,6 +1,6 @@
1
1
  @layer rc-theme-material.components {
2
2
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-bottom-sheet {
3
- --rc-bottom-sheet-bg: var(--md-sys-color-surface, Canvas);
3
+ --rc-bottom-sheet-bg: var(--md-sys-color-surface-container-low, Canvas);
4
4
  --rc-bottom-sheet-handle-color: color-mix(
5
5
  in srgb,
6
6
  var(--md-sys-color-on-surface-variant, GrayText) 40%,
@@ -28,7 +28,7 @@
28
28
  overflow: auto;
29
29
  border: 0;
30
30
  border-radius: var(--rc-bottom-sheet-radius, 1.75rem 1.75rem 0 0);
31
- background: var(--rc-bottom-sheet-bg, var(--md-sys-color-surface, Canvas));
31
+ background: var(--rc-bottom-sheet-bg, var(--md-sys-color-surface-container-low, Canvas));
32
32
  color: var(--rc-bottom-sheet-color, var(--md-sys-color-on-surface, CanvasText));
33
33
  box-shadow: var(--rc-bottom-sheet-shadow, var(--rc-shadow-level1, none));
34
34
  font-family: var(--md-sys-typescale-body-medium-font, inherit);
@@ -41,10 +41,13 @@
41
41
  );
42
42
  }
43
43
 
44
+ /* Descendant (not child) combinator: consuming apps may nest the handle
45
+ inside their own peek-content wrapper (e.g. grouped with a summary
46
+ row) rather than placing it as a direct child of dialog. */
44
47
  :where(.rc-theme-material, :host(.rc-theme-material))
45
48
  rc-bottom-sheet
46
49
  > dialog
47
- > [data-rc-bottom-sheet-handle] {
50
+ [data-rc-bottom-sheet-handle] {
48
51
  position: relative;
49
52
  display: block;
50
53
  inline-size: var(--rc-bottom-sheet-handle-target-inline-size, 100%);
@@ -63,7 +66,7 @@
63
66
  :where(.rc-theme-material, :host(.rc-theme-material))
64
67
  rc-bottom-sheet
65
68
  > dialog
66
- > [data-rc-bottom-sheet-handle]::before {
69
+ [data-rc-bottom-sheet-handle]::before {
67
70
  content: '';
68
71
  position: absolute;
69
72
  inset-block-start: 50%;
@@ -78,7 +81,7 @@
78
81
  :where(.rc-theme-material, :host(.rc-theme-material))
79
82
  rc-bottom-sheet
80
83
  > dialog
81
- > [data-rc-bottom-sheet-handle]:focus-visible {
84
+ [data-rc-bottom-sheet-handle]:focus-visible {
82
85
  outline: 0.125rem solid var(--md-sys-color-primary, Highlight);
83
86
  outline-offset: -0.25rem;
84
87
  }
@@ -29,6 +29,98 @@
29
29
  cubic-bezier(0.05, 0.7, 0.1, 1)
30
30
  );
31
31
  --rc-button-progress-color: var(--md-sys-color-on-primary, ButtonText);
32
+ --rc-button-disabled-opacity: var(--rc-disabled-opacity, 0.38);
33
+ }
34
+
35
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button.rc-button--tonal {
36
+ --rc-button-bg: var(--md-sys-color-secondary-container, ButtonFace);
37
+ --rc-button-color: var(--md-sys-color-on-secondary-container, ButtonText);
38
+ --rc-button-state-layer-bg: var(--md-sys-color-on-secondary-container, currentColor);
39
+ --_rc-button-ripple-color: var(--md-sys-color-on-secondary-container, currentColor);
40
+ --rc-button-progress-color: var(--md-sys-color-on-secondary-container, ButtonText);
41
+ }
42
+
43
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button.rc-button--outlined {
44
+ --rc-button-bg: transparent;
45
+ --rc-button-color: var(--md-sys-color-primary, ButtonText);
46
+ --rc-button-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
47
+ --rc-button-state-layer-bg: var(--md-sys-color-primary, currentColor);
48
+ --_rc-button-ripple-color: var(--md-sys-color-primary, currentColor);
49
+ --rc-button-progress-color: var(--md-sys-color-primary, ButtonText);
50
+ }
51
+
52
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button.rc-button--text {
53
+ --rc-button-bg: transparent;
54
+ --rc-button-color: var(--md-sys-color-primary, ButtonText);
55
+ --rc-button-border: 0;
56
+ --rc-button-padding-inline: 0.75rem;
57
+ --rc-button-state-layer-bg: var(--md-sys-color-primary, currentColor);
58
+ --_rc-button-ripple-color: var(--md-sys-color-primary, currentColor);
59
+ --rc-button-progress-color: var(--md-sys-color-primary, ButtonText);
60
+ }
61
+
62
+ :where(.rc-theme-material, :host(.rc-theme-material))
63
+ rc-button.rc-icon-button--standard[icon-only] {
64
+ --rc-button-bg: transparent;
65
+ --rc-button-color: var(--md-sys-color-on-surface-variant, ButtonText);
66
+ --rc-button-border: 0;
67
+ --rc-button-state-layer-bg: var(--md-sys-color-on-surface-variant, currentColor);
68
+ --_rc-button-ripple-color: var(--md-sys-color-on-surface-variant, currentColor);
69
+ --rc-button-progress-color: var(--md-sys-color-on-surface-variant, ButtonText);
70
+ }
71
+
72
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button.rc-icon-button--tonal[icon-only] {
73
+ --rc-button-bg: var(--md-sys-color-secondary-container, ButtonFace);
74
+ --rc-button-color: var(--md-sys-color-on-secondary-container, ButtonText);
75
+ --rc-button-state-layer-bg: var(--md-sys-color-on-secondary-container, currentColor);
76
+ --_rc-button-ripple-color: var(--md-sys-color-on-secondary-container, currentColor);
77
+ --rc-button-progress-color: var(--md-sys-color-on-secondary-container, ButtonText);
78
+ }
79
+
80
+ :where(.rc-theme-material, :host(.rc-theme-material))
81
+ rc-button.rc-icon-button--outlined[icon-only] {
82
+ --rc-button-bg: transparent;
83
+ --rc-button-color: var(--md-sys-color-on-surface-variant, ButtonText);
84
+ --rc-button-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
85
+ --rc-button-state-layer-bg: var(--md-sys-color-on-surface-variant, currentColor);
86
+ --_rc-button-ripple-color: var(--md-sys-color-on-surface-variant, currentColor);
87
+ --rc-button-progress-color: var(--md-sys-color-on-surface-variant, ButtonText);
88
+ }
89
+
90
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button[data-tone='danger'] {
91
+ --rc-button-bg: var(--md-sys-color-error, ButtonFace);
92
+ --rc-button-color: var(--md-sys-color-on-error, ButtonText);
93
+ --rc-button-state-layer-bg: var(--md-sys-color-on-error, currentColor);
94
+ --_rc-button-ripple-color: var(--md-sys-color-on-error, currentColor);
95
+ --rc-button-progress-color: var(--md-sys-color-on-error, ButtonText);
96
+ }
97
+
98
+ :where(.rc-theme-material, :host(.rc-theme-material))
99
+ rc-button:is(
100
+ .rc-button--tonal,
101
+ .rc-button--outlined,
102
+ .rc-button--text,
103
+ .rc-icon-button--standard,
104
+ .rc-icon-button--tonal,
105
+ .rc-icon-button--outlined
106
+ )[data-tone='danger'] {
107
+ --rc-button-bg: transparent;
108
+ --rc-button-color: var(--md-sys-color-error, ButtonText);
109
+ --rc-button-state-layer-bg: var(--md-sys-color-error, currentColor);
110
+ --_rc-button-ripple-color: var(--md-sys-color-error, currentColor);
111
+ --rc-button-progress-color: var(--md-sys-color-error, ButtonText);
112
+ }
113
+
114
+ :where(.rc-theme-material, :host(.rc-theme-material))
115
+ rc-button:is(.rc-button--tonal, .rc-icon-button--tonal)[data-tone='danger'] {
116
+ --rc-button-bg: var(--md-sys-color-error-container, ButtonFace);
117
+ --rc-button-color: var(--md-sys-color-on-error-container, ButtonText);
118
+ --rc-button-state-layer-bg: var(--md-sys-color-on-error-container, currentColor);
119
+ }
120
+
121
+ :where(.rc-theme-material, :host(.rc-theme-material))
122
+ rc-button:is(.rc-button--outlined, .rc-icon-button--outlined)[data-tone='danger'] {
123
+ --rc-button-border: 1px solid var(--md-sys-color-error, ButtonBorder);
32
124
  }
33
125
 
34
126
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-button > button:focus-visible {
@@ -51,7 +143,127 @@
51
143
  }
52
144
 
53
145
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-button[icon-only] {
146
+ /* MD3 expressive "Small" icon button (the default/unmodified size): a
147
+ 40dp square container around a 24dp icon. rc-button's own touch-target
148
+ affordance (min-inline/block-size 3rem, plus the light-DOM hit-slop)
149
+ makes up the difference to the 48dp minimum tap target on its own; no
150
+ theme-level override is needed for that here. */
151
+ --rc-button-icon-size: 2.5rem;
152
+ --rc-icon-button-icon-font-size: 1.5rem;
153
+ }
154
+
155
+ /*
156
+ * MD3 expressive icon-button sizes. Each sets both the square container
157
+ * (`--rc-button-block-size`/`--rc-button-icon-size`, since `icon-only`'s
158
+ * default width equals its height) and the icon glyph size together, so
159
+ * the two stay in the spec's fixed ratio instead of drifting independently.
160
+ * Values: https://m3.material.io/components/icon-buttons/specs (container
161
+ * height / icon size, dp): extra-small 32/20, small 40/24 (above, default),
162
+ * medium 56/24, large 96/32, extra-large 136/40.
163
+ */
164
+ :where(.rc-theme-material, :host(.rc-theme-material))
165
+ rc-button.rc-button--extra-small[icon-only] {
166
+ --rc-button-block-size: 2rem;
167
+ --rc-button-icon-size: 2rem;
168
+ --rc-icon-button-icon-font-size: 1.25rem;
169
+ }
170
+
171
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button.rc-button--medium[icon-only] {
172
+ --rc-button-block-size: 3.5rem;
173
+ --rc-button-icon-size: 3.5rem;
174
+ --rc-icon-button-icon-font-size: 1.5rem;
175
+ }
176
+
177
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button.rc-button--large[icon-only] {
178
+ --rc-button-block-size: 6rem;
179
+ --rc-button-icon-size: 6rem;
180
+ --rc-icon-button-icon-font-size: 2rem;
181
+ }
182
+
183
+ :where(.rc-theme-material, :host(.rc-theme-material))
184
+ rc-button.rc-button--extra-large[icon-only] {
185
+ --rc-button-block-size: 8.5rem;
186
+ --rc-button-icon-size: 8.5rem;
187
+ --rc-icon-button-icon-font-size: 2.5rem;
188
+ }
189
+
190
+ /*
191
+ * Width variants change only the container's inline size; block size (and
192
+ * the icon itself) stay governed by the size class above, or the default
193
+ * "small" size when none is present. `narrow` suits dense/overflow
194
+ * contexts (an app bar's trailing overflow trigger); `wide` suits roomier
195
+ * toolbars that can spare the extra tap-friendly width. Per-size pairing
196
+ * is required because each size's narrow/wide delta is a fixed spec value,
197
+ * not a proportional one.
198
+ */
199
+ /*
200
+ * The overlap tokens below give back exactly what --rc-button-icon-size
201
+ * leaves unclaimed of the 3rem default touch target ((3rem - icon-size) /
202
+ * 2, matching the button's own centered inflation) -- the narrow variant's
203
+ * documented reason for existing is dense/edge contexts, so this is a
204
+ * default here, not left for every consumer to compute and set
205
+ * individually. Trailing-edge only: narrow's own doc comment names an app
206
+ * bar's *trailing* overflow trigger as the canonical case, and defaulting
207
+ * only one side halves the risk of two adjacent narrow buttons' touch
208
+ * targets colliding if a consumer places one where it does have a real
209
+ * neighbor. Medium/large/extra-large narrow variants already meet or
210
+ * exceed the touch target on their own (see each size's own comment
211
+ * above), so they need no overlap default here.
212
+ */
213
+ :where(.rc-theme-material, :host(.rc-theme-material))
214
+ rc-button.rc-button--extra-small.rc-button--narrow[icon-only] {
215
+ --rc-button-icon-size: 1.75rem;
216
+ --rc-button-touch-target-overlap-inline-end: 0.625rem;
217
+ }
218
+
219
+ :where(.rc-theme-material, :host(.rc-theme-material))
220
+ rc-button.rc-button--extra-small.rc-button--wide[icon-only] {
54
221
  --rc-button-icon-size: 2.5rem;
55
- --rc-icon-font-line-height: var(--rc-button-icon-size, 2.5rem);
222
+ }
223
+
224
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button.rc-button--narrow[icon-only] {
225
+ --rc-button-icon-size: 2rem;
226
+ --rc-button-touch-target-overlap-inline-end: 0.5rem;
227
+ }
228
+
229
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-button.rc-button--wide[icon-only] {
230
+ --rc-button-icon-size: 3.25rem;
231
+ }
232
+
233
+ :where(.rc-theme-material, :host(.rc-theme-material))
234
+ rc-button.rc-button--medium.rc-button--narrow[icon-only] {
235
+ --rc-button-icon-size: 3rem;
236
+ /* Already meets the 3rem default touch target on its own; the bare
237
+ .rc-button--narrow[icon-only] rule's overlap default still matches
238
+ here too (class selectors don't exclude each other), so it needs an
239
+ explicit reset. */
240
+ --rc-button-touch-target-overlap-inline-end: 0px;
241
+ }
242
+
243
+ :where(.rc-theme-material, :host(.rc-theme-material))
244
+ rc-button.rc-button--medium.rc-button--wide[icon-only] {
245
+ --rc-button-icon-size: 4.5rem;
246
+ }
247
+
248
+ :where(.rc-theme-material, :host(.rc-theme-material))
249
+ rc-button.rc-button--large.rc-button--narrow[icon-only] {
250
+ --rc-button-icon-size: 4rem;
251
+ --rc-button-touch-target-overlap-inline-end: 0px;
252
+ }
253
+
254
+ :where(.rc-theme-material, :host(.rc-theme-material))
255
+ rc-button.rc-button--large.rc-button--wide[icon-only] {
256
+ --rc-button-icon-size: 8rem;
257
+ }
258
+
259
+ :where(.rc-theme-material, :host(.rc-theme-material))
260
+ rc-button.rc-button--extra-large.rc-button--narrow[icon-only] {
261
+ --rc-button-icon-size: 6.5rem;
262
+ --rc-button-touch-target-overlap-inline-end: 0px;
263
+ }
264
+
265
+ :where(.rc-theme-material, :host(.rc-theme-material))
266
+ rc-button.rc-button--extra-large.rc-button--wide[icon-only] {
267
+ --rc-button-icon-size: 11.5rem;
56
268
  }
57
269
  }
@@ -0,0 +1,23 @@
1
+ @layer rc-theme-material.components {
2
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-carousel {
3
+ --rc-carousel-color: var(--md-sys-color-on-surface, CanvasText);
4
+ --rc-carousel-navigation-button-background: color-mix(
5
+ in srgb,
6
+ var(--md-sys-color-surface, Canvas) 75%,
7
+ transparent
8
+ );
9
+ --rc-carousel-navigation-button-color: var(--md-sys-color-on-surface, CanvasText);
10
+ --rc-carousel-pagination-item-color: color-mix(
11
+ in srgb,
12
+ var(--md-sys-color-on-surface, CanvasText) 40%,
13
+ transparent
14
+ );
15
+ --rc-carousel-pagination-item-active-color: var(--md-sys-color-primary, Highlight);
16
+ }
17
+
18
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-carousel-item {
19
+ --rc-carousel-item-color: var(--md-sys-color-on-surface, CanvasText);
20
+ --rc-carousel-item-background: var(--md-sys-color-surface-container, Canvas);
21
+ --rc-carousel-item-border-radius: var(--md-sys-shape-corner-extra-large, 28px);
22
+ }
23
+ }