@rcarls/rc-theme-material 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +600 -0
  2. package/DESIGN.md +1399 -0
  3. package/README.md +138 -5
  4. package/bridge.css +150 -55
  5. package/components/accordion.css +43 -157
  6. package/components/adaptive-menu.css +123 -0
  7. package/components/app-bar.css +49 -7
  8. package/components/bottom-sheet.css +10 -7
  9. package/components/button.css +215 -2
  10. package/components/card.css +2 -0
  11. package/components/carousel.css +23 -0
  12. package/components/chip-group.css +15 -0
  13. package/components/chip.css +12 -1
  14. package/components/combobox.css +68 -14
  15. package/components/dialog.css +77 -15
  16. package/components/disclosure.css +128 -84
  17. package/components/field.css +566 -0
  18. package/components/icons.css +48 -6
  19. package/components/list-item.css +142 -32
  20. package/components/listbox.css +5 -4
  21. package/components/markdown-editor.css +62 -35
  22. package/components/menu-button.css +105 -1
  23. package/components/menu.css +32 -16
  24. package/components/menubar.css +4 -1
  25. package/components/modes.css +36 -17
  26. package/components/navigation-bar.css +3 -5
  27. package/components/navigation-rail.css +5 -7
  28. package/components/popover.css +50 -0
  29. package/components/progress.css +15 -0
  30. package/components/range-slider.css +8 -3
  31. package/components/scroller.css +7 -0
  32. package/components/search-bar.css +12 -2
  33. package/components/segmented-button.css +2 -28
  34. package/components/select.css +106 -14
  35. package/components/splitter.css +4 -1
  36. package/components/switch.css +9 -1
  37. package/components/textarea.css +13 -3
  38. package/components/toolbar.css +2 -1
  39. package/components/tooltip.css +12 -0
  40. package/components/transfer-list.css +5 -1
  41. package/components/virtual-canvas.css +4 -1
  42. package/components/virtual-scroller.css +7 -0
  43. package/components.css +11 -1
  44. package/constraints/material.json +99 -0
  45. package/css-components/button.css +66 -0
  46. package/css-components/card.css +14 -0
  47. package/css-components/chip-group.css +9 -0
  48. package/css-components/chip.css +80 -0
  49. package/css-components/disclosure.css +25 -0
  50. package/css-components/list.css +34 -0
  51. package/css-components/select.css +20 -0
  52. package/css-components/textarea.css +22 -0
  53. package/css-components.css +31 -0
  54. package/defaults.css +329 -14
  55. package/native.css +258 -0
  56. package/package.json +21 -2
  57. package/state-layer.css +5 -1
@@ -1,13 +1,10 @@
1
1
  @layer rc-theme-material.components {
2
2
  :where(.rc-theme-material, :host(.rc-theme-material)) {
3
+ /* Compatibility tokens retained for rc-listbox and embedded selectors. */
3
4
  --rc-list-item-gap: 1rem;
4
5
  --rc-list-item-min-block-size: 3rem;
5
6
  --rc-list-item-padding-block: 0;
6
7
  --rc-list-item-padding-inline: 1rem;
7
- --rc-list-item-divider: 0;
8
- --rc-list-item-bg: transparent;
9
- --rc-list-item-color: var(--md-sys-color-on-surface, CanvasText);
10
- --rc-list-item-supporting-color: var(--md-sys-color-on-surface-variant, CanvasText);
11
8
  --rc-list-item-hover-bg: color-mix(
12
9
  in srgb,
13
10
  var(--md-sys-color-on-surface, CanvasText)
@@ -25,53 +22,166 @@
25
22
  --rc-list-item-disabled-opacity: var(--md-sys-state-disabled-state-layer-opacity, 0.38);
26
23
  }
27
24
 
28
- :where(.rc-theme-material, :host(.rc-theme-material)) .rc-list {
29
- list-style: none;
30
- margin: 0;
31
- padding: 0;
25
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-list {
26
+ --rc-list-padding-inline: 1rem;
27
+ --rc-list-leading-gap: 1rem;
28
+ --rc-list-trailing-gap: 1rem;
29
+ --rc-list-row-gap: 0;
30
+ --rc-list-item-min-block-size: 3.5rem;
31
+ --rc-list-item-padding-block: 0.5rem;
32
+ --rc-list-item-color: var(--md-sys-color-on-surface, CanvasText);
33
+ --rc-list-item-background: transparent;
34
+ --rc-list-item-border-radius: 0;
35
+ --rc-list-item-selected-color: var(--md-sys-color-on-secondary-container, HighlightText);
36
+ --rc-list-item-selected-background: var(--md-sys-color-secondary-container, Highlight);
37
+ --rc-list-item-divider: 1px solid var(--md-sys-color-outline-variant, GrayText);
38
+ --rc-list-item-state-layer-color: var(--md-sys-color-on-surface, CanvasText);
39
+ --rc-list-item-hover-state-layer-opacity: var(--md-sys-state-hover-state-layer-opacity, 0.08);
40
+ --rc-list-item-focus-state-layer-opacity: var(--md-sys-state-focus-state-layer-opacity, 0.1);
41
+ --rc-list-item-pressed-state-layer-opacity: var(
42
+ --md-sys-state-pressed-state-layer-opacity,
43
+ 0.12
44
+ );
45
+ --rc-list-item-disabled-opacity: var(--md-sys-state-disabled-state-layer-opacity, 0.38);
46
+ --rc-list-item-transition-duration: var(--rc-motion-effects-duration-fast, 150ms);
47
+ --rc-list-item-transition-easing: var(--md-sys-motion-easing-standard, ease);
48
+ --rc-list-item-details-color: var(--md-sys-color-on-surface-variant, CanvasText);
49
+ --rc-list-item-details-duration: var(--md-sys-motion-duration-short2, 100ms);
50
+ --rc-list-item-dragged-background: var(--md-sys-color-surface-container-high, Canvas);
51
+ --rc-list-item-dragged-box-shadow: var(--rc-shadow-level4, var(--rc-shadow, none));
52
+ --rc-list-item-dragged-state-layer-opacity: var(
53
+ --md-sys-state-dragged-state-layer-opacity,
54
+ 0.16
55
+ );
56
+ --rc-list-item-reorder-duration: var(--md-sys-motion-duration-medium1, 250ms);
57
+ --rc-list-item-reorder-easing: var(--md-sys-motion-easing-standard, ease);
32
58
  }
33
59
 
34
- :where(.rc-theme-material, :host(.rc-theme-material)) .rc-list-item {
35
- display: flex;
36
- align-items: center;
37
- gap: var(--rc-list-item-gap);
38
- min-block-size: var(--rc-list-item-min-block-size);
39
- padding: var(--rc-list-item-padding-block) var(--rc-list-item-padding-inline);
40
- border-block-end: var(--rc-list-item-divider);
41
- background: var(--rc-list-item-bg);
42
- color: var(--rc-list-item-color);
60
+ /*
61
+ * A plain native reorder handle reads as a standard icon button: a 48px
62
+ * target in on-surface-variant. Handles wrapped in rc-button keep that
63
+ * component's own presentation.
64
+ */
65
+ :where(.rc-theme-material, :host(.rc-theme-material))
66
+ rc-list[reorderable]
67
+ :not(rc-button)
68
+ > button[data-rc-reorder-handle] {
69
+ display: inline-grid;
70
+ place-items: center;
43
71
  box-sizing: border-box;
72
+ min-inline-size: 3rem;
73
+ min-block-size: 3rem;
74
+ padding: 0;
75
+ border: 0;
76
+ border-radius: var(--md-sys-shape-corner-full, 50%);
77
+ background: transparent;
78
+ color: var(--md-sys-color-on-surface-variant, CanvasText);
79
+ font: inherit;
44
80
  }
45
81
 
46
- :where(.rc-theme-material, :host(.rc-theme-material)) .rc-list-item__start,
47
- :where(.rc-theme-material, :host(.rc-theme-material)) .rc-list-item__trailing,
48
- :where(.rc-theme-material, :host(.rc-theme-material)) .rc-list-item__end {
49
- display: inline-flex;
50
- align-items: center;
51
- flex-shrink: 0;
82
+ :where(.rc-theme-material, :host(.rc-theme-material))
83
+ rc-list[reorderable]
84
+ :not(rc-button)
85
+ > button[data-rc-reorder-handle]:hover {
86
+ background: color-mix(
87
+ in srgb,
88
+ currentColor calc(var(--md-sys-state-hover-state-layer-opacity, 0.08) * 100%),
89
+ transparent
90
+ );
91
+ }
92
+
93
+ /* Expanded details read as list supporting text. */
94
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-list-item::part(details) {
95
+ font-family: var(--md-sys-typescale-body-medium-font, inherit);
96
+ font-size: var(--md-sys-typescale-body-medium-size, 0.875rem);
97
+ font-weight: var(--md-sys-typescale-body-medium-weight, 400);
98
+ line-height: var(--md-sys-typescale-body-medium-line-height, 1.25rem);
99
+ }
100
+
101
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-list[variant='segmented'] {
102
+ --rc-list-row-gap: 0.125rem;
103
+ }
104
+
105
+ /* Dividers separate visible rows; they do not trail the final row. */
106
+ :where(.rc-theme-material, :host(.rc-theme-material))
107
+ rc-list
108
+ > rc-list-item:is([data-rc-list-position='last'], [data-rc-list-position='only']) {
109
+ --rc-list-item-divider: 0;
110
+ }
111
+
112
+ :where(.rc-theme-material, :host(.rc-theme-material))
113
+ rc-list[variant='segmented']
114
+ > rc-list-item {
115
+ --rc-list-item-min-block-size: 3.5rem;
116
+ --rc-list-item-padding-block: 0.625rem;
117
+ --rc-list-item-background: var(--md-sys-color-surface-container-low, Canvas);
118
+ --rc-list-item-divider: 0;
119
+ --rc-list-item-border-radius: var(--md-sys-shape-corner-extra-small, 0.25rem);
120
+ }
121
+
122
+ :where(.rc-theme-material, :host(.rc-theme-material))
123
+ rc-list[variant='segmented']
124
+ > rc-list-item[data-rc-list-position='only'] {
125
+ --rc-list-item-border-radius: var(--md-sys-shape-corner-extra-large, 1.75rem);
126
+ }
127
+
128
+ :where(.rc-theme-material, :host(.rc-theme-material))
129
+ rc-list[variant='segmented']
130
+ > rc-list-item[data-rc-list-position='first'] {
131
+ --rc-list-item-border-radius: var(--md-sys-shape-corner-extra-large, 1.75rem)
132
+ var(--md-sys-shape-corner-extra-large, 1.75rem)
133
+ var(--md-sys-shape-corner-extra-small, 0.25rem)
134
+ var(--md-sys-shape-corner-extra-small, 0.25rem);
52
135
  }
53
136
 
54
- :where(.rc-theme-material, :host(.rc-theme-material)) .rc-list-item__body {
55
- display: flex;
56
- flex: 1 1 auto;
57
- flex-direction: column;
58
- min-inline-size: 0;
137
+ :where(.rc-theme-material, :host(.rc-theme-material))
138
+ rc-list[variant='segmented']
139
+ > rc-list-item[data-rc-list-position='last'] {
140
+ --rc-list-item-border-radius: var(--md-sys-shape-corner-extra-small, 0.25rem)
141
+ var(--md-sys-shape-corner-extra-small, 0.25rem)
142
+ var(--md-sys-shape-corner-extra-large, 1.75rem)
143
+ var(--md-sys-shape-corner-extra-large, 1.75rem);
59
144
  }
60
145
 
61
- :where(.rc-theme-material, :host(.rc-theme-material)) .rc-list-item__headline {
62
- color: var(--rc-list-item-color);
146
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-list-item::part(content) {
63
147
  font-family: var(--md-sys-typescale-body-large-font, inherit);
64
148
  font-size: var(--md-sys-typescale-body-large-size, 1rem);
149
+ font-weight: var(--md-sys-typescale-body-large-weight, 400);
65
150
  line-height: var(--md-sys-typescale-body-large-line-height, 1.5rem);
66
151
  }
67
152
 
68
- :where(.rc-theme-material, :host(.rc-theme-material)) .rc-list-item__supporting {
69
- color: var(--rc-list-item-supporting-color);
153
+ :where(.rc-theme-material, :host(.rc-theme-material))
154
+ rc-list-item
155
+ > :where([data-rc-list-supporting], small) {
156
+ display: block;
157
+ color: var(--md-sys-color-on-surface-variant, CanvasText);
70
158
  font-family: var(--md-sys-typescale-body-medium-font, inherit);
71
159
  font-size: var(--md-sys-typescale-body-medium-size, 0.875rem);
160
+ font-weight: var(--md-sys-typescale-body-medium-weight, 400);
72
161
  line-height: var(--md-sys-typescale-body-medium-line-height, 1.25rem);
73
162
  }
74
163
 
164
+ :where(.rc-theme-material, :host(.rc-theme-material))
165
+ rc-list-item
166
+ > [slot='leading'][data-rc-list-leading] {
167
+ display: inline-flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ inline-size: 1.5rem;
171
+ block-size: 1.5rem;
172
+ font-size: 1.5rem;
173
+ line-height: 1.5rem;
174
+ }
175
+
176
+ :where(.rc-theme-material, :host(.rc-theme-material))
177
+ rc-list-item
178
+ > :is(input[type='checkbox'], input[type='radio'])[slot='leading'] {
179
+ inline-size: 1.125rem;
180
+ block-size: 1.125rem;
181
+ margin: 0;
182
+ accent-color: var(--md-sys-color-primary, Highlight);
183
+ }
184
+
75
185
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-listbox,
76
186
  :where(.rc-theme-material, :host(.rc-theme-material)) [part~='listbox'] {
77
187
  --rc-listbox-option-gap: var(--rc-list-item-gap);
@@ -8,15 +8,16 @@
8
8
  0 2px 6px 2px rgba(0, 0, 0, 0.15);
9
9
  padding-block: 0.5rem;
10
10
  overflow-y: auto;
11
+ overflow-block: auto;
11
12
  color: var(--md-sys-color-on-surface, CanvasText);
12
- font-family: var(--md-sys-typescale-body-large-font, inherit);
13
- font-size: var(--md-sys-typescale-body-large-size, 1rem);
14
- line-height: var(--md-sys-typescale-body-large-line-height, 1.5rem);
15
13
  --rc-listbox-option-gap: var(--rc-list-item-gap, 0.75rem);
16
14
  --rc-listbox-option-min-block-size: 3rem;
17
15
  --rc-listbox-option-padding-block: 0;
18
16
  --rc-listbox-option-padding-inline: 0.75rem;
19
- --rc-listbox-option-transition: background-color 150ms ease, color 150ms ease;
17
+ --rc-listbox-option-transition:
18
+ background-color var(--rc-motion-effects-duration-fast, 150ms)
19
+ var(--rc-motion-effects-easing-fast, ease),
20
+ color var(--rc-motion-effects-duration-fast, 150ms) var(--rc-motion-effects-easing-fast, ease);
20
21
  --rc-listbox-hover-bg: color-mix(
21
22
  in srgb,
22
23
  var(--md-sys-color-on-surface, CanvasText) 8%,
@@ -1,42 +1,69 @@
1
1
  @layer rc-theme-material.components {
2
2
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-markdown-editor {
3
- --rme-background: var(--md-sys-color-surface, Canvas);
4
- --rme-color: var(--md-sys-color-on-surface, CanvasText);
5
- --rme-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
6
- --rme-border-radius: 0 0 var(--md-sys-shape-corner-small, 0.5rem)
3
+ --rc-markdown-editor-background: var(--md-sys-color-surface, Canvas);
4
+ --rc-markdown-editor-color: var(--md-sys-color-on-surface, CanvasText);
5
+ --rc-markdown-editor-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
6
+ --rc-markdown-editor-border-radius: 0 0 var(--md-sys-shape-corner-small, 0.5rem)
7
7
  var(--md-sys-shape-corner-small, 0.5rem);
8
- --rme-focus-outline: 2px solid var(--md-sys-color-primary, Highlight);
9
- --rme-padding: 1rem;
10
- --rme-toolbar-gap: 0.25rem;
11
- --rme-toolbar-button-size: 2.5rem;
12
- --rme-toolbar-padding: 0.25rem;
13
- --rme-toolbar-radius: var(--md-sys-shape-corner-small, 0.5rem)
8
+ --rc-markdown-editor-focus-outline: 2px solid var(--md-sys-color-primary, Highlight);
9
+ --rc-markdown-editor-padding: 1rem;
10
+ --rc-markdown-editor-toolbar-gap: 0.25rem;
11
+ --rc-markdown-editor-toolbar-button-size: 2.5rem;
12
+ --rc-markdown-editor-toolbar-padding: 0.25rem;
13
+ --rc-markdown-editor-toolbar-radius: var(--md-sys-shape-corner-small, 0.5rem)
14
14
  var(--md-sys-shape-corner-small, 0.5rem) 0 0;
15
- --rme-toolbar-background: var(--md-sys-color-surface-container, Canvas);
16
- --rme-toolbar-color: var(--md-sys-color-on-surface, CanvasText);
17
- --rme-toolbar-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
18
- --rme-toolbar-button-color: var(--md-sys-color-on-surface-variant, ButtonText);
19
- --rme-toolbar-button-border: 0;
20
- --rme-toolbar-button-radius: var(--md-sys-shape-corner-full, 999px);
21
- --rme-toolbar-button-active-background: var(--md-sys-color-secondary-container, Highlight);
22
- --rme-toolbar-button-active-color: var(--md-sys-color-on-secondary-container, HighlightText);
23
- --rme-toolbar-button-active-border: 0;
24
- --rme-toolbar-button-hover-opacity: var(--md-sys-state-hover-state-layer-opacity, 0.08);
25
- --rme-toolbar-button-focus-opacity: var(--md-sys-state-focus-state-layer-opacity, 0.12);
26
- --rme-toolbar-button-pressed-opacity: var(--md-sys-state-pressed-state-layer-opacity, 0.12);
27
- --rme-toolbar-focus-outline: 2px solid var(--md-sys-color-primary, Highlight);
28
- --rme-toolbar-focus-outline-offset: 1px;
29
- --rme-toolbar-select-background: var(--md-sys-color-surface-container-highest, Field);
30
- --rme-toolbar-select-color: var(--md-sys-color-on-surface, FieldText);
31
- --rme-toolbar-select-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
32
- --rme-toolbar-select-radius: var(--md-sys-shape-corner-extra-small, 0.25rem);
33
- --rme-toolbar-select-active-background: var(--md-sys-color-secondary-container, Highlight);
34
- --rme-toolbar-select-active-color: var(--md-sys-color-on-secondary-container, HighlightText);
35
- --rme-toolbar-select-active-border-color: var(--md-sys-color-primary, Highlight);
36
- --rme-toolbar-input-background: var(--md-sys-color-surface-container-highest, Field);
37
- --rme-toolbar-input-color: var(--md-sys-color-on-surface, FieldText);
38
- --rme-toolbar-input-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
39
- --rme-toolbar-input-radius: var(--md-sys-shape-corner-extra-small, 0.25rem);
15
+ --rc-markdown-editor-toolbar-background: var(--md-sys-color-surface-container, Canvas);
16
+ --rc-markdown-editor-toolbar-color: var(--md-sys-color-on-surface, CanvasText);
17
+ --rc-markdown-editor-toolbar-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
18
+ --rc-markdown-editor-toolbar-button-color: var(--md-sys-color-on-surface-variant, ButtonText);
19
+ --rc-markdown-editor-toolbar-button-border: 0;
20
+ --rc-markdown-editor-toolbar-button-radius: var(--md-sys-shape-corner-full, 999px);
21
+ --rc-markdown-editor-toolbar-button-active-background: var(
22
+ --md-sys-color-secondary-container,
23
+ Highlight
24
+ );
25
+ --rc-markdown-editor-toolbar-button-active-color: var(
26
+ --md-sys-color-on-secondary-container,
27
+ HighlightText
28
+ );
29
+ --rc-markdown-editor-toolbar-button-active-border: 0;
30
+ --rc-markdown-editor-toolbar-button-hover-opacity: var(
31
+ --md-sys-state-hover-state-layer-opacity,
32
+ 0.08
33
+ );
34
+ --rc-markdown-editor-toolbar-button-focus-opacity: var(
35
+ --md-sys-state-focus-state-layer-opacity,
36
+ 0.12
37
+ );
38
+ --rc-markdown-editor-toolbar-button-pressed-opacity: var(
39
+ --md-sys-state-pressed-state-layer-opacity,
40
+ 0.12
41
+ );
42
+ --rc-markdown-editor-toolbar-focus-outline: 2px solid var(--md-sys-color-primary, Highlight);
43
+ --rc-markdown-editor-toolbar-focus-outline-offset: 1px;
44
+ --rc-markdown-editor-toolbar-select-background: var(
45
+ --md-sys-color-surface-container-highest,
46
+ Field
47
+ );
48
+ --rc-markdown-editor-toolbar-select-color: var(--md-sys-color-on-surface, FieldText);
49
+ --rc-markdown-editor-toolbar-select-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
50
+ --rc-markdown-editor-toolbar-select-radius: var(--md-sys-shape-corner-extra-small, 0.25rem);
51
+ --rc-markdown-editor-toolbar-select-active-background: var(
52
+ --md-sys-color-secondary-container,
53
+ Highlight
54
+ );
55
+ --rc-markdown-editor-toolbar-select-active-color: var(
56
+ --md-sys-color-on-secondary-container,
57
+ HighlightText
58
+ );
59
+ --rc-markdown-editor-toolbar-select-active-border-color: var(--md-sys-color-primary, Highlight);
60
+ --rc-markdown-editor-toolbar-input-background: var(
61
+ --md-sys-color-surface-container-highest,
62
+ Field
63
+ );
64
+ --rc-markdown-editor-toolbar-input-color: var(--md-sys-color-on-surface, FieldText);
65
+ --rc-markdown-editor-toolbar-input-border: 1px solid var(--md-sys-color-outline, ButtonBorder);
66
+ --rc-markdown-editor-toolbar-input-radius: var(--md-sys-shape-corner-extra-small, 0.25rem);
40
67
  }
41
68
 
42
69
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-markdown-editor::part(rich-view) {
@@ -7,7 +7,10 @@
7
7
  --rc-menu-button-trigger-border: 0;
8
8
  --rc-menu-button-trigger-background: transparent;
9
9
  --rc-menu-button-trigger-color: var(--md-sys-color-primary, ButtonText);
10
- --rc-menu-button-trigger-transition: background-color 150ms ease, color 150ms ease;
10
+ --rc-menu-button-trigger-transition:
11
+ background-color var(--rc-motion-effects-duration-fast, 150ms)
12
+ var(--rc-motion-effects-easing-fast, ease),
13
+ color var(--rc-motion-effects-duration-fast, 150ms) var(--rc-motion-effects-easing-fast, ease);
11
14
  --rc-menu-button-trigger-hover-background: color-mix(
12
15
  in srgb,
13
16
  var(--md-sys-color-primary, Highlight) 8%,
@@ -19,4 +22,105 @@
19
22
  --rc-menu-button-indicator-size: 1.5rem;
20
23
  --rc-menu-button-indicator-color: var(--md-sys-color-on-surface-variant, CanvasText);
21
24
  }
25
+
26
+ /*
27
+ * MD3 "Small" icon button sizing (40dp square trigger / 24dp icon) for an
28
+ * icon-only rc-menu-button trigger — e.g. an app bar's overflow button.
29
+ * rc-menu-button's own touch-target affordance (min-inline/block-size
30
+ * 3rem on the trigger wrapper, plus the light-DOM hit-slop) makes up the
31
+ * difference to the 48dp minimum tap target on its own.
32
+ * https://m3.material.io/components/icon-buttons/specs
33
+ */
34
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu-button[icon-only] {
35
+ --rc-menu-button-trigger-block-size: 2.5rem;
36
+ --rc-menu-button-trigger-padding-block: 0;
37
+ --rc-menu-button-trigger-padding-inline: 0;
38
+ --rc-menu-button-trigger-gap: 0;
39
+ --rc-menu-button-icon-size: 2.5rem;
40
+ }
41
+
42
+ /* Adaptive overflow keeps the authored menu label in the trigger, so the
43
+ shared label marker is the one direct child that is not icon content. */
44
+ :where(.rc-theme-material, :host(.rc-theme-material))
45
+ rc-menu-button[icon-only]
46
+ > [slot='trigger']
47
+ > :not([data-rc-menu-label]) {
48
+ font-size: var(--rc-icon-button-icon-font-size, 1.5rem);
49
+ line-height: var(--rc-icon-button-icon-font-size, 1.5rem) !important;
50
+ }
51
+
52
+ /*
53
+ * Narrow width: trims the trigger's inline size (32dp, the MD3 "Small"
54
+ * narrow-width spec value) without changing its height. Suits a dense
55
+ * context that already has an unambiguous, self-labeling icon and no
56
+ * neighbors it needs to align widths with — an app bar's trailing
57
+ * overflow trigger is the canonical case, so this also defaults the
58
+ * trailing-edge overlap token: (3rem default touch target - 2rem icon
59
+ * size) / 2, giving back exactly what the touch target would otherwise
60
+ * reserve past the visible trigger. Trailing-edge only, matching the
61
+ * "trailing overflow trigger" framing above -- see rc-button's own
62
+ * narrow-variant comment for why only one side defaults.
63
+ */
64
+ :where(.rc-theme-material, :host(.rc-theme-material))
65
+ rc-menu-button.rc-menu-button--narrow[icon-only] {
66
+ --rc-menu-button-icon-size: 2rem;
67
+ --rc-menu-button-touch-target-overlap-inline-end: 0.5rem;
68
+ }
69
+
70
+ /*
71
+ * A submenu trigger (a cascading menu item that opens a nested rc-menu)
72
+ * is still an rc-menu-button underneath, but MD3 treats it as a menu row
73
+ * with a trailing disclosure chevron — not as its own standalone pill
74
+ * control. The base rule above (and rc-menu-button's own defaults) style
75
+ * it as the latter: a primary-colored, pill-shaped, independently-padded
76
+ * trigger, layered on top of whatever geometry rc-menu's own item CSS
77
+ * (menu.css / rc-base) tries to apply to the same element by virtue of
78
+ * its role="menuitem" — hence the mismatched shape and the icon sitting
79
+ * at a different inset than its sibling rows.
80
+ *
81
+ * The consumer marks this case the same way rc-menu itself expects a
82
+ * cascading item to be marked (role="menuitem" — see menu.css and
83
+ * rc-menu's own light-DOM CSS), so key every geometry/color token here
84
+ * off rc-menu's own item, hover, and active tokens (--rc-menu-item-...,
85
+ * --rc-menu-hover-..., --rc-menu-active-...) instead of hand-matching
86
+ * values that could drift out of sync with a sibling plain-button item
87
+ * later.
88
+ * https://m3.material.io/components/menus/specs
89
+ */
90
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu-button[role='menuitem'] {
91
+ font-family: var(--md-sys-typescale-body-large-font, inherit);
92
+ font-size: var(--md-sys-typescale-body-large-size, 1rem);
93
+ font-weight: 400;
94
+
95
+ --rc-menu-button-trigger-block-size: var(--rc-menu-item-min-block-size, 3rem);
96
+ --rc-menu-button-trigger-padding-block: var(--rc-menu-item-padding-block, 0);
97
+ --rc-menu-button-trigger-padding-inline: var(--rc-menu-item-padding-inline, 0.75rem);
98
+ --rc-menu-button-trigger-gap: var(--rc-menu-item-gap, 0.75rem);
99
+ --rc-menu-button-trigger-radius: 0;
100
+ --rc-menu-button-trigger-border: 0;
101
+ --rc-menu-button-trigger-background: transparent;
102
+ --rc-menu-button-trigger-color: inherit;
103
+ --rc-menu-button-trigger-hover-background: var(--rc-menu-hover-bg);
104
+ --rc-menu-button-trigger-hover-color: var(--rc-menu-hover-color, inherit);
105
+ --rc-menu-button-trigger-open-background: var(--rc-menu-active-bg);
106
+ --rc-menu-button-trigger-open-color: var(--rc-menu-active-color, inherit);
107
+ }
108
+
109
+ /*
110
+ * rc-menu's own light-DOM CSS (rc-base, an even-higher-priority layer
111
+ * than this one — it's registered at custom-element-connect time,
112
+ * after every static stylesheet) matches *any* role="menuitem" element
113
+ * for its generic item padding, which includes this host itself, not
114
+ * just plain-button items. Left alone, that stacks on top of the
115
+ * trigger-inline padding bridged above: the host absorbs one
116
+ * --rc-menu-item-padding-inline, then the trigger button absorbs
117
+ * another, doubling the icon's inset versus a sibling row. The host
118
+ * itself isn't a visible surface — all padding belongs on the one
119
+ * real, visible trigger button — so it needs to contribute zero here,
120
+ * which (since rc-base doesn't mark its own padding !important) is
121
+ * only reachable with !important of our own.
122
+ */
123
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu-button[role='menuitem'] {
124
+ padding-inline: 0 !important;
125
+ }
22
126
  }
@@ -1,24 +1,19 @@
1
1
  @layer rc-theme-material.components {
2
- /* Container + token overrides ------------------------------------------- */
3
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu {
4
- background: var(--md-menu-container-color, var(--md-sys-color-surface-container, Canvas));
5
- border: none;
6
- border-radius: var(--md-menu-container-shape, 4px);
7
- box-shadow:
8
- 0 1px 2px rgba(0, 0, 0, 0.3),
9
- 0 2px 6px 2px rgba(0, 0, 0, 0.15);
10
- padding-block: 0.5rem;
11
- color: var(--md-sys-color-on-surface, CanvasText);
12
- font-family: var(--md-sys-typescale-body-large-font, inherit);
13
- font-size: var(--md-sys-typescale-body-large-size, 1rem);
14
- line-height: var(--md-sys-typescale-body-large-line-height, 1.5rem);
15
-
2
+ /*
3
+ * Token overrides. The container comes from the bridge's --rc-popup-* and
4
+ * --rc-item-* tokens. Declared on the theme root rather than on rc-menu so
5
+ * menus rendered inside other shadow roots inherit the same values.
6
+ */
7
+ :where(.rc-theme-material, :host(.rc-theme-material)) {
16
8
  /* Item geometry — M3 menu item: 48dp height, 12dp h-padding, 12dp gap */
17
9
  --rc-menu-item-min-block-size: 3rem;
18
10
  --rc-menu-item-padding-block: 0;
19
11
  --rc-menu-item-padding-inline: 0.75rem;
20
12
  --rc-menu-item-gap: 0.75rem;
21
- --rc-menu-item-transition: background-color 150ms ease, color 150ms ease;
13
+ --rc-menu-item-transition:
14
+ background-color var(--rc-motion-effects-duration-fast, 150ms)
15
+ var(--rc-motion-effects-easing-fast, ease),
16
+ color var(--rc-motion-effects-duration-fast, 150ms) var(--rc-motion-effects-easing-fast, ease);
22
17
 
23
18
  /* State layers derived from on-surface (M3: 8% hover, 12% keyboard cursor) */
24
19
  --rc-menu-hover-bg: color-mix(
@@ -34,7 +29,7 @@
34
29
  );
35
30
  --rc-menu-active-color: var(--md-sys-color-on-surface, CanvasText);
36
31
 
37
- /* Check/radio indicator — M3 leading icon slot is 24dp wide */
32
+ /* Check/radio indicator — M3 trailing indicator column is 24dp wide */
38
33
  --rc-menu-check-size: 1.5rem;
39
34
  --rc-menu-check-color: var(--md-sys-color-primary, Highlight);
40
35
 
@@ -58,12 +53,33 @@
58
53
  outline: none;
59
54
  }
60
55
 
56
+ /*
57
+ * M3 baseline menu items are rectangular full-width rows (unlike a
58
+ * standalone rc-button, which is a pill) — rc-menu's own structural CSS
59
+ * intentionally leaves shape undecided (it's a themed concern), so claim
60
+ * it explicitly here rather than leaving items to whatever shape a
61
+ * consumer's own incidental button styling might otherwise supply.
62
+ */
63
+ :where(.rc-theme-material, :host(.rc-theme-material))
64
+ rc-menu
65
+ :is([role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio']) {
66
+ border-radius: 0;
67
+ }
68
+
61
69
  /* Current item (navigation active / selected radio row) gets secondary-container */
62
70
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu [aria-current='true'] {
63
71
  background: var(--md-sys-color-secondary-container, Highlight);
64
72
  color: var(--md-sys-color-on-secondary-container, HighlightText);
65
73
  }
66
74
 
75
+ /* M3 single-choice menus use the same trailing check affordance as other
76
+ * selected menu rows; role=menuitemradio continues to carry semantics. */
77
+ :where(.rc-theme-material, :host(.rc-theme-material))
78
+ rc-menu
79
+ [role='menuitemradio'][aria-checked='true']::after {
80
+ content: '✓';
81
+ }
82
+
67
83
  /* Section / group labels (optional, for menu segmentation) -------------- */
68
84
  /* Add [data-group-label] as first child of role="group" for a visible heading. */
69
85
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu [data-group-label] {
@@ -11,7 +11,10 @@
11
11
  --rc-menubar-item-radius: var(--md-sys-shape-corner-full, 999px);
12
12
  --rc-menubar-item-background: transparent;
13
13
  --rc-menubar-item-color: var(--md-sys-color-primary, CanvasText);
14
- --rc-menubar-item-transition: background-color 150ms ease, color 150ms ease;
14
+ --rc-menubar-item-transition:
15
+ background-color var(--rc-motion-effects-duration-fast, 150ms)
16
+ var(--rc-motion-effects-easing-fast, ease),
17
+ color var(--rc-motion-effects-duration-fast, 150ms) var(--rc-motion-effects-easing-fast, ease);
15
18
  --rc-menubar-item-hover-background: color-mix(
16
19
  in srgb,
17
20
  var(--md-sys-color-primary, Highlight) 8%,
@@ -1,30 +1,49 @@
1
1
  @layer rc-theme-material.components {
2
+ /*
3
+ * The vestibular harm reduced motion guards against is movement across the
4
+ * visual field: a cross-fade or a color change doesn't trigger it, so
5
+ * removing every transition (the previous *, !important sweep) over-
6
+ * corrected, and it also silently removed the ones that aid comprehension.
7
+ * Spatial motion still goes to zero; effects motion is kept but shortened,
8
+ * which the spatial/effects split makes expressible for the first time.
9
+ * Values are read as custom properties rather than reasserted with
10
+ * !important, so this only reaches whatever already consumes the shared
11
+ * motion tokens or the Material duration primitives. Components that
12
+ * still handle prefers-reduced-motion with their own blunt sweep are
13
+ * refined in their own component styles; this file no longer
14
+ * compensates for that with a second, theme-wide !important override.
15
+ */
2
16
  @media (prefers-reduced-motion: reduce) {
3
- :where(.rc-theme-material, :host(.rc-theme-material)) *,
4
- :where(.rc-theme-material, :host(.rc-theme-material)) *::before,
5
- :where(.rc-theme-material, :host(.rc-theme-material)) *::after {
6
- transition-duration: 0s !important;
7
- animation-duration: 0s !important;
17
+ :where(.rc-theme-material, :host(.rc-theme-material)) {
18
+ --rc-motion-spatial-duration-fast: 0ms;
19
+ --rc-motion-spatial-duration-default: 0ms;
20
+ --rc-motion-spatial-duration-slow: 0ms;
21
+ --rc-motion-effects-duration-fast: 50ms;
22
+ --rc-motion-effects-duration-default: 70ms;
23
+ --rc-motion-effects-duration-slow: 100ms;
24
+ --rc-motion-duration: var(--rc-motion-effects-duration-default);
8
25
  }
9
26
  }
10
27
 
11
28
  @media (forced-colors: active) {
12
- :where(.rc-theme-material, :host(.rc-theme-material)) :is(
13
- rc-select,
14
- rc-combobox,
15
- rc-search-bar,
16
- rc-textarea,
17
- rc-markdown-editor,
18
- rc-menu,
19
- rc-menubar,
20
- rc-toolbar,
21
- rc-dialog > dialog
22
- ) {
29
+ :where(.rc-theme-material, :host(.rc-theme-material))
30
+ :is(
31
+ rc-select,
32
+ rc-combobox,
33
+ rc-search-bar,
34
+ rc-textarea,
35
+ rc-markdown-editor,
36
+ rc-menu,
37
+ rc-menubar,
38
+ rc-toolbar,
39
+ rc-dialog > dialog
40
+ ) {
23
41
  forced-color-adjust: auto;
24
42
  box-shadow: none;
25
43
  }
26
44
 
27
- :where(.rc-theme-material, :host(.rc-theme-material)) :is(button, [role='button'], [role^='menuitem']):focus-visible {
45
+ :where(.rc-theme-material, :host(.rc-theme-material))
46
+ :is(button, [role='button'], [role^='menuitem']):focus-visible {
28
47
  outline: 2px solid Highlight;
29
48
  }
30
49
  }
@@ -15,11 +15,9 @@
15
15
  --rc-navigation-bar-indicator-bg: var(--md-sys-color-secondary-container, Highlight);
16
16
  --rc-navigation-bar-indicator-border: 0;
17
17
  --rc-navigation-bar-indicator-radius: var(--md-sys-shape-corner-full, 9999px);
18
- --rc-navigation-bar-indicator-duration: var(--md-sys-motion-duration-short3, 150ms);
19
- --rc-navigation-bar-indicator-easing: var(
20
- --md-sys-motion-easing-standard,
21
- cubic-bezier(0.2, 0, 0, 1)
22
- );
18
+ /* The indicator resizes to the selected item's box, which is spatial motion. */
19
+ --rc-navigation-bar-indicator-duration: var(--rc-motion-spatial-duration-fast, 300ms);
20
+ --rc-navigation-bar-indicator-easing: var(--rc-motion-spatial-easing-fast, ease);
23
21
  --rc-icon-font-line-height: 2rem;
24
22
  --rc-navigation-bar-focus-ring: 2px solid var(--md-sys-color-primary, Highlight);
25
23
  --rc-navigation-bar-focus-ring-offset: 2px;
@@ -22,13 +22,11 @@
22
22
  --rc-navigation-rail-indicator-radius: var(--md-sys-shape-corner-full, 9999px);
23
23
  --rc-navigation-rail-toggle-size: 3rem;
24
24
  --rc-navigation-rail-toggle-inline-offset: 1rem;
25
- --rc-navigation-rail-duration: var(--md-sys-motion-duration-medium2, 300ms);
26
- --rc-navigation-rail-easing: var(--md-sys-motion-easing-emphasized, cubic-bezier(0.2, 0, 0, 1));
27
- --rc-navigation-rail-indicator-duration: var(--md-sys-motion-duration-short3, 150ms);
28
- --rc-navigation-rail-indicator-easing: var(
29
- --md-sys-motion-easing-standard,
30
- cubic-bezier(0.2, 0, 0, 1)
31
- );
25
+ --rc-navigation-rail-duration: var(--rc-motion-spatial-duration-fast, 300ms);
26
+ --rc-navigation-rail-easing: var(--rc-motion-spatial-easing-fast, ease);
27
+ /* The indicator resizes to the selected item's box, which is spatial motion. */
28
+ --rc-navigation-rail-indicator-duration: var(--rc-motion-spatial-duration-fast, 300ms);
29
+ --rc-navigation-rail-indicator-easing: var(--rc-motion-spatial-easing-fast, ease);
32
30
  --rc-icon-font-line-height: 2rem;
33
31
  --rc-navigation-rail-focus-ring: 2px solid var(--md-sys-color-primary, Highlight);
34
32
  --rc-navigation-rail-focus-ring-offset: 2px;