@rcarls/rc-theme-material 0.2.0 → 0.3.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.
@@ -1,24 +1,108 @@
1
1
  @layer rc-theme-material.components {
2
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu :is(button, [role='menuitem'], [role='menuitemradio'], [role='menuitemcheckbox']) {
3
- min-block-size: 3rem;
4
- border: 0;
5
- background: transparent;
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;
6
11
  color: var(--md-sys-color-on-surface, CanvasText);
7
- font: inherit;
8
- transition: background-color 150ms ease;
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
+
16
+ /* Item geometry — M3 menu item: 48dp height, 12dp h-padding, 12dp gap */
17
+ --rc-menu-item-min-block-size: 3rem;
18
+ --rc-menu-item-padding-block: 0;
19
+ --rc-menu-item-padding-inline: 0.75rem;
20
+ --rc-menu-item-gap: 0.75rem;
21
+ --rc-menu-item-transition: background-color 150ms ease, color 150ms ease;
22
+
23
+ /* State layers derived from on-surface (M3: 8% hover, 12% keyboard cursor) */
24
+ --rc-menu-hover-bg: color-mix(
25
+ in srgb,
26
+ var(--md-sys-color-on-surface, CanvasText) 8%,
27
+ transparent
28
+ );
29
+ --rc-menu-hover-color: var(--md-sys-color-on-surface, CanvasText);
30
+ --rc-menu-active-bg: color-mix(
31
+ in srgb,
32
+ var(--md-sys-color-on-surface, CanvasText) 12%,
33
+ transparent
34
+ );
35
+ --rc-menu-active-color: var(--md-sys-color-on-surface, CanvasText);
36
+
37
+ /* Check/radio indicator — M3 leading icon slot is 24dp wide */
38
+ --rc-menu-check-size: 1.5rem;
39
+ --rc-menu-check-color: var(--md-sys-color-primary, Highlight);
40
+
41
+ /* Trailing shortcut labels (label-large) */
42
+ --rc-menu-shortcut-size: var(--md-sys-typescale-label-large-size, 0.875rem);
43
+ --rc-menu-shortcut-color: var(--md-sys-color-on-surface-variant, GrayText);
44
+ --rc-menu-submenu-indicator-size: 1.25rem;
45
+ --rc-menu-submenu-indicator-color: var(--md-sys-color-on-surface-variant, CanvasText);
46
+
47
+ /* Dividers: outline-variant, full-width by default */
48
+ --rc-menu-separator-border: 1px solid var(--md-sys-color-outline-variant, ButtonBorder);
49
+ --rc-menu-separator-margin-block: 0.5rem;
50
+
51
+ /* Disabled: M3 uses 38% opacity on on-surface */
52
+ --rc-menu-disabled-color: var(--md-sys-color-on-surface, CanvasText);
53
+ --rc-menu-disabled-opacity: 0.38;
54
+
55
+ /* Section label color */
56
+ --rc-menu-group-label-color: var(--md-sys-color-on-surface-variant, GrayText);
9
57
  }
10
58
 
11
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu :is(button, [role='menuitem'], [role='menuitemradio'], [role='menuitemcheckbox']):hover {
12
- background: color-mix(in srgb, var(--md-sys-color-on-surface, CanvasText) 8%, transparent);
59
+ /* M3 uses the state-layer cursor, not a container focus ring ------------- */
60
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu:focus-visible {
61
+ outline: none;
13
62
  }
14
63
 
15
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu :is([aria-checked='true'], [aria-current='true']) {
64
+ /* Current item (navigation active / selected radio row) gets secondary-container */
65
+ :where(.rc-theme-material, :host(.rc-theme-material))
66
+ rc-menu [aria-current='true'] {
16
67
  background: var(--md-sys-color-secondary-container, Highlight);
17
68
  color: var(--md-sys-color-on-secondary-container, HighlightText);
18
69
  }
19
70
 
20
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu :is(button, [role^='menuitem']):focus-visible {
21
- outline: 2px solid var(--md-sys-color-primary, Highlight);
22
- outline-offset: -2px;
71
+ /* Section / group labels (optional, for menu segmentation) -------------- */
72
+ /* Add [data-group-label] as first child of role="group" for a visible heading. */
73
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu [data-group-label] {
74
+ padding-block-start: 0.75rem;
75
+ padding-block-end: 0.25rem;
76
+ font-family: var(--md-sys-typescale-label-small-font, inherit);
77
+ font-size: var(--md-sys-typescale-label-small-size, 0.6875rem);
78
+ font-weight: var(--md-sys-typescale-label-small-weight, 500);
79
+ letter-spacing: 0.05em;
80
+ text-transform: uppercase;
81
+ }
82
+
83
+ /* Inset dividers within groups ------------------------------------------ */
84
+ /* Separators inside role="group" are inset by the item padding on both sides.
85
+ This matches the M3 spec for grouped menus (e.g. radio group segments). */
86
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu [role='group'] > hr,
87
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-menu [role='group'] > [role='separator'] {
88
+ --rc-menu-separator-margin-inline: var(--rc-menu-item-padding-inline, 0.75rem);
23
89
  }
24
90
  }
91
+
92
+ /*
93
+ * Theming notes for rc-menu-button variants:
94
+ *
95
+ * The trigger button in rc-menu-button is already styled via
96
+ * rc-theme-material/components/menu-button.css. If you need a different
97
+ * trigger surface (filled, tonal, outlined) wrap the trigger <button> in
98
+ * the appropriate M3 button variant class rather than overriding menu.css.
99
+ *
100
+ * For a plain/text trigger (the default), the existing menu-button.css
101
+ * sets primary-colored text with an 8% hover state layer.
102
+ *
103
+ * For an outlined variant:
104
+ * rc-menu-button > [slot='trigger'] { border: 1px solid var(--md-sys-color-outline); }
105
+ *
106
+ * For a filled variant:
107
+ * rc-menu-button > [slot='trigger'] { background: var(--md-sys-color-primary); color: var(--md-sys-color-on-primary); }
108
+ */
@@ -1,9 +1,24 @@
1
1
  @layer rc-theme-material.components {
2
2
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-menubar::part(root) {
3
- box-shadow: var(--md-sys-elevation-level0, none);
3
+ box-shadow: var(--rc-shadow-level0, none);
4
4
  }
5
5
 
6
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-menubar rc-menu-button > :is(button, [role='button'])[slot='trigger'] {
7
- padding-inline: 1rem;
6
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-menubar {
7
+ --rc-menubar-item-block-size: 2.5rem;
8
+ --rc-menubar-item-padding-block: 0.5rem;
9
+ --rc-menubar-item-padding-inline: 1rem;
10
+ --rc-menubar-item-border: 0;
11
+ --rc-menubar-item-radius: var(--md-sys-shape-corner-full, 999px);
12
+ --rc-menubar-item-background: transparent;
13
+ --rc-menubar-item-color: var(--md-sys-color-primary, CanvasText);
14
+ --rc-menubar-item-transition: background-color 150ms ease, color 150ms ease;
15
+ --rc-menubar-item-hover-background: color-mix(
16
+ in srgb,
17
+ var(--md-sys-color-primary, Highlight) 8%,
18
+ transparent
19
+ );
20
+ --rc-menubar-item-hover-color: var(--md-sys-color-primary, CanvasText);
21
+ --rc-menubar-item-open-background: var(--md-sys-color-secondary-container, ButtonFace);
22
+ --rc-menubar-item-open-color: var(--md-sys-color-on-secondary-container, ButtonText);
8
23
  }
9
24
  }
@@ -1,16 +1,22 @@
1
1
  @layer rc-theme-material.components {
2
2
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-search-bar::part(root) {
3
3
  box-sizing: border-box;
4
- box-shadow: var(--md-sys-elevation-level0, none);
5
- transition: box-shadow 200ms ease, background-color 200ms ease;
4
+ transition:
5
+ box-shadow 200ms ease,
6
+ background-color 200ms ease;
6
7
  }
7
8
 
8
9
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-search-bar:hover::part(root) {
9
- background: color-mix(in srgb, var(--md-sys-color-on-surface, CanvasText) 4%, var(--md-sys-color-surface-container-high, Field));
10
+ background: color-mix(
11
+ in srgb,
12
+ var(--md-sys-color-on-surface, CanvasText) 8%,
13
+ var(--md-sys-color-surface-container-high, Field)
14
+ );
10
15
  }
11
16
 
12
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-search-bar[data-focus-visible]::part(root) {
13
- box-shadow: var(--md-sys-elevation-level1, none);
17
+ :where(.rc-theme-material, :host(.rc-theme-material))
18
+ rc-search-bar[data-interaction-mode='keyboard']::part(root):focus-within {
19
+ box-shadow: var(--rc-shadow-level2, none);
14
20
  }
15
21
 
16
22
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-search-bar::part(clear) {
@@ -18,6 +24,10 @@
18
24
  }
19
25
 
20
26
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-search-bar::part(clear):hover {
21
- background: color-mix(in srgb, var(--md-sys-color-on-surface-variant, CanvasText) 8%, transparent);
27
+ background: color-mix(
28
+ in srgb,
29
+ var(--md-sys-color-on-surface-variant, CanvasText) 8%,
30
+ transparent
31
+ );
22
32
  }
23
33
  }
@@ -28,7 +28,69 @@
28
28
  color: var(--md-sys-color-on-surface-variant, CanvasText);
29
29
  }
30
30
 
31
+ /*
32
+ * Propagate Material styles to the embedded rc-listbox host. rc-listbox renders
33
+ * options into its own light DOM inside rc-select's shadow root, so inherited
34
+ * custom properties are the stable styling contract for option rows.
35
+ */
31
36
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-select::part(listbox) {
32
37
  background: var(--md-menu-container-color, var(--md-sys-color-surface-container, Canvas));
38
+ color: var(--md-sys-color-on-surface, CanvasText);
39
+ font-family: var(--md-sys-typescale-body-large-font, inherit);
40
+ font-size: var(--md-sys-typescale-body-large-size, 1rem);
41
+ line-height: var(--md-sys-typescale-body-large-line-height, 1.5rem);
42
+ padding-block: 0.5rem;
43
+ border-radius: var(--md-menu-container-shape, var(--md-sys-shape-corner-extra-small, 0.25rem));
44
+
45
+ /* Option sizing — inherited by li[role='option'] via rc-listbox's rc-base layer */
46
+ --rc-listbox-option-gap: 0.75rem;
47
+ --rc-listbox-option-min-block-size: 3rem;
48
+ --rc-listbox-option-padding-block: 0;
49
+ --rc-listbox-option-padding-inline: 0.75rem;
50
+ --rc-listbox-option-transition: background-color 150ms ease, color 150ms ease;
51
+
52
+ /* M3 hover/focus state layers use on-surface, not the selected container role. */
53
+ --rc-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, CanvasText) 8%, transparent);
54
+ --rc-highlight-text: var(--md-sys-color-on-surface, CanvasText);
55
+ --rc-listbox-hover-bg: color-mix(
56
+ in srgb,
57
+ var(--md-sys-color-on-surface, CanvasText) 8%,
58
+ transparent
59
+ );
60
+ --rc-listbox-hover-color: var(--md-sys-color-on-surface, CanvasText);
61
+ --rc-listbox-active-bg: color-mix(
62
+ in srgb,
63
+ var(--md-sys-color-on-surface, CanvasText) 12%,
64
+ transparent
65
+ );
66
+ --rc-listbox-active-color: var(--md-sys-color-on-surface, CanvasText);
67
+
68
+ --rc-listbox-selected-bg: var(--md-sys-color-secondary-container, Highlight);
69
+ --rc-listbox-selected-color: var(--md-sys-color-on-secondary-container, HighlightText);
70
+ --rc-listbox-disabled-opacity: var(--md-sys-state-disabled-state-layer-opacity, 0.38);
71
+
72
+ /* M3 menus use background state layer for keyboard focus, not an outline ring */
73
+ --rc-focus-ring: none;
74
+ }
75
+
76
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-select::part(toggle-indicator) {
77
+ color: var(
78
+ --md-outlined-select-text-field-trailing-icon-color,
79
+ var(--md-sys-color-on-surface-variant, CanvasText)
80
+ );
81
+ transition: color 150ms ease, transform 150ms ease;
82
+ }
83
+
84
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-select[open]::part(toggle-indicator) {
85
+ transform: rotate(180deg);
86
+ color: var(
87
+ --md-outlined-select-text-field-focus-trailing-icon-color,
88
+ var(--md-sys-color-primary, Highlight)
89
+ );
90
+ }
91
+
92
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-select[disabled]::part(trigger) {
93
+ opacity: var(--md-sys-state-disabled-container-opacity, 0.38);
94
+ pointer-events: none;
33
95
  }
34
96
  }
@@ -1,18 +1,32 @@
1
1
  @layer rc-theme-material.components {
2
2
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-splitter {
3
- --rc-splitter-separator-size: 0.5rem;
3
+ /* 24px wide strip — meets WCAG 2.5.8 touch target in the cross axis */
4
+ --rc-splitter-separator-size: 1.5rem;
4
5
  --rc-splitter-separator-color: var(--md-sys-color-surface-container, Canvas);
5
- --rc-splitter-keyline: 1px solid var(--md-sys-color-outline-variant, ButtonBorder);
6
- --rc-splitter-handle-color: var(--md-sys-color-on-surface-variant, ButtonBorder);
7
- --rc-splitter-separator-handle-size: 3rem;
8
- }
9
-
10
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-splitter::part(separator-handle) {
11
- border-radius: var(--md-sys-shape-corner-full, 999px);
12
- transition: background-color 150ms ease;
13
- }
6
+ /* No keyline border; surface color provides enough contrast */
7
+ --rc-splitter-keyline: none;
8
+ --rc-splitter-separator-border-inline-start: none;
9
+ --rc-splitter-separator-border-inline-end: none;
10
+ --rc-splitter-separator-border-block-start: none;
11
+ --rc-splitter-separator-border-block-end: none;
14
12
 
15
- :where(.rc-theme-material, :host(.rc-theme-material)) rc-splitter::part(separator-handle):hover {
16
- background-color: color-mix(in srgb, var(--md-sys-color-primary, Highlight) 8%, transparent);
13
+ /* M3 drag indicator: 32px × 4px rounded pill, like a bottom-sheet handle */
14
+ --rc-splitter-separator-handle-size: 2rem;
15
+ --rc-splitter-handle-thickness: 4px;
16
+ --rc-splitter-handle-border-radius: 999px;
17
+ /* Disable the default dot grip; use a solid pill fill instead */
18
+ --rc-splitter-handle-pattern: none;
19
+ --rc-splitter-handle-fill: color-mix(
20
+ in srgb,
21
+ var(--md-sys-color-on-surface-variant, ButtonBorder) 40%,
22
+ transparent
23
+ );
24
+ /* Hover state layer on the pill only, not the full strip */
25
+ --rc-splitter-handle-hover-fill: color-mix(
26
+ in srgb,
27
+ var(--md-sys-color-primary, Highlight) 8%,
28
+ transparent
29
+ );
30
+ --rc-splitter-handle-transition: 150ms var(--md-sys-motion-easing-standard, ease);
17
31
  }
18
32
  }
@@ -3,6 +3,21 @@
3
3
  --rc-transfer-list-gap: 1rem;
4
4
  --rc-transfer-list-panel-gap: 0.5rem;
5
5
  --rc-transfer-list-listbox-border: 1px solid var(--md-sys-color-outline-variant, ButtonBorder);
6
+ --rc-transfer-list-listbox-bg: var(--md-sys-color-surface, Canvas);
7
+ --rc-transfer-list-option-gap: 0.75rem;
8
+ --rc-transfer-list-option-padding-block: 0;
9
+ --rc-transfer-list-option-padding-inline: 0.75rem;
10
+ --rc-transfer-list-option-hover-bg: color-mix(
11
+ in srgb,
12
+ var(--md-sys-color-on-surface, CanvasText) 8%,
13
+ transparent
14
+ );
15
+ --rc-transfer-list-option-hover-color: var(--md-sys-color-on-surface, CanvasText);
16
+ --rc-transfer-list-option-selected-bg: var(--md-sys-color-secondary-container, Highlight);
17
+ --rc-transfer-list-option-selected-color: var(
18
+ --md-sys-color-on-secondary-container,
19
+ HighlightText
20
+ );
6
21
  }
7
22
 
8
23
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-transfer-list::part(panel) {
@@ -16,11 +31,35 @@
16
31
  font-weight: 500;
17
32
  }
18
33
 
34
+ :where(.rc-theme-material, :host(.rc-theme-material)) rc-transfer-list::part(listbox) {
35
+ border-radius: var(--md-sys-shape-corner-small, 0.25rem);
36
+ --rc-listbox-option-gap: 0.75rem;
37
+ --rc-listbox-option-min-block-size: 3rem;
38
+ --rc-listbox-option-padding-block: 0;
39
+ --rc-listbox-option-padding-inline: 0.75rem;
40
+ --rc-listbox-option-transition: background-color 150ms ease, color 150ms ease;
41
+ --rc-listbox-hover-bg: color-mix(
42
+ in srgb,
43
+ var(--md-sys-color-on-surface, CanvasText) 8%,
44
+ transparent
45
+ );
46
+ --rc-listbox-hover-color: var(--md-sys-color-on-surface, CanvasText);
47
+ --rc-listbox-active-bg: color-mix(
48
+ in srgb,
49
+ var(--md-sys-color-on-surface, CanvasText) 12%,
50
+ transparent
51
+ );
52
+ --rc-listbox-active-color: var(--md-sys-color-on-surface, CanvasText);
53
+ --rc-listbox-selected-bg: var(--md-sys-color-secondary-container, Highlight);
54
+ --rc-listbox-selected-color: var(--md-sys-color-on-secondary-container, HighlightText);
55
+ --rc-listbox-disabled-opacity: var(--md-sys-state-disabled-state-layer-opacity, 0.38);
56
+ }
57
+
19
58
  :where(.rc-theme-material, :host(.rc-theme-material)) rc-transfer-list::part(button) {
20
59
  min-block-size: 2.5rem;
21
60
  padding-inline: 1rem;
22
61
  border: 0;
23
- border-radius: var(--md-sys-shape-corner-full, 999px);
62
+ border-radius: var(--md-sys-shape-corner-medium, 0.75rem);
24
63
  background: var(--md-sys-color-secondary-container, ButtonFace);
25
64
  color: var(--md-sys-color-on-secondary-container, ButtonText);
26
65
  }
package/components.css CHANGED
@@ -7,6 +7,7 @@
7
7
  @import './components/textarea.css';
8
8
  @import './components/markdown-editor.css';
9
9
  @import './components/transfer-list.css';
10
+ @import './components/fab.css';
10
11
  @import './components/app-bar.css';
11
12
  @import './components/menu.css';
12
13
  @import './components/menu-button.css';