@rcarls/rc-menu-button 0.0.0-next-20260921045401

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 ADDED
@@ -0,0 +1,165 @@
1
+ # @rcarls/rc-menu-button
2
+
3
+ ## 0.0.0-next-20260921045401
4
+
5
+ ### Minor Changes
6
+
7
+ - 94dc987: `rc-menu-button`'s, `rc-select`'s, and `rc-combobox`'s popup/listbox now fade
8
+ in and out through CSS alone, using `@starting-style` and a discrete
9
+ `display`/`overlay` transition, driven by new `--rc-menu-button-popup-duration`,
10
+ `--rc-select-listbox-duration`, and `--rc-combobox-listbox-duration`
11
+ properties. `showPopover()`/`hidePopover()` (via `openPopup()`/`closePopup()`)
12
+ stay synchronous, and nothing waits on the transition finishing.
13
+
14
+ These animate opacity only, not a scale or slide transform: all three
15
+ position their popup with the shared `AnchorController`, which applies its
16
+ own viewport-clamping `translate` and reads `getBoundingClientRect()` to
17
+ compute the next correction. A second, CSS-driven transform on the same
18
+ element and property would fight that positioning math on every open, not
19
+ only during an edge case.
20
+
21
+ `rc-fab-menu` already had a scale-based entrance for its popup (verified safe
22
+ here: unlike the general `AnchorController` case, this popup isn't
23
+ collision-clamped), but no exit animation at all and no directional easing.
24
+ Both are added: the popup now fades and scales back out on close, and enter
25
+ uses a decelerating curve while exit uses an accelerating one.
26
+
27
+ ### Patch Changes
28
+
29
+ - Updated dependencies [50d5610]
30
+ - Updated dependencies [4341311]
31
+ - @rcarls/rc-common@0.0.0-next-20260921045401
32
+ - @rcarls/rc-menu@0.0.0-next-20260921045401
33
+
34
+ ## 0.6.0
35
+
36
+ ### Minor Changes
37
+
38
+ - 30eb232: Add icon-only activation-area sizing and Material icon-button variants. Align menu
39
+ selection and submenu affordances, and keep anchored popups within the viewport
40
+ across native and fallback positioning.
41
+ - 30eb232: Add `--rc-menu-button-touch-target-overlap-inline-start` and
42
+ `-inline-end` for an `icon-only` trigger, zero by default. A theme or
43
+ consumer sets one to let the accessible touch-target inflation on that
44
+ side overlap into whatever sits just outside the host, such as a toolbar's
45
+ own edge padding, instead of also reserving layout space there: the
46
+ visible trigger shifts flush with that edge while the invisible hit
47
+ region keeps its full accessible size. Mirrors `@rcarls/rc-button`'s own
48
+ touch-target overlap tokens.
49
+
50
+ ### Patch Changes
51
+
52
+ - 7382c71: Add a priority-aware action toolbar that moves original controls into an
53
+ overflow menu. Which actions are promoted is a purely declarative computation
54
+ from `max-shown` and each action's `data-priority`/authored `slot`, with no
55
+ runtime measurement of the toolbar's or its children's rendered size: a
56
+ consumer whose promoted count needs to react to available space owns that
57
+ decision and writes the resulting `max-shown` value down. Include controlled
58
+ and uncontrolled open state, keyboard navigation, light dismissal, and a
59
+ non-Popover fallback.
60
+
61
+ Fix `--rc-adaptive-menu-touch-target-overlap-inline-start`/`-end`: the host's
62
+ own `max-inline-size: 100%` self-referenced a shrink-to-fit ancestor's
63
+ already-margin-reduced auto size (an app bar's own trailing group, for
64
+ example), quietly clamping the host back down and canceling the overlap out
65
+ from under it. The cap now grows by the overlap amount so it only ever bounds
66
+ the host's real content.
67
+
68
+ - 57370e4: Align component metadata, aggregate framework typings, development-time native-child
69
+ validation, controlled menu state, package declarations, and public documentation before the
70
+ next release.
71
+ - Updated dependencies [7382c71]
72
+ - Updated dependencies [6683eb9]
73
+ - Updated dependencies [ee7ba6c]
74
+ - Updated dependencies [30eb232]
75
+ - @rcarls/rc-menu@0.6.0
76
+ - @rcarls/rc-common@0.6.0
77
+
78
+ ## 0.5.0
79
+
80
+ ### Minor Changes
81
+
82
+ - d33b92f: Use the native Popover API for the popup panel instead of a `hidden` attribute
83
+ and `z-index`. Removes `--rc-menu-button-popup-z-index`; stacking is now
84
+ governed by top-layer insertion order.
85
+
86
+ ### Patch Changes
87
+
88
+ - Updated dependencies [4ae2ef0]
89
+ - Updated dependencies [689340c]
90
+ - @rcarls/rc-common@0.5.0
91
+ - @rcarls/rc-menu@0.5.0
92
+
93
+ ## 0.4.2
94
+
95
+ ### Patch Changes
96
+
97
+ - @rcarls/rc-common@0.4.2
98
+ - @rcarls/rc-menu@0.4.2
99
+
100
+ ## 0.4.1
101
+
102
+ ### Patch Changes
103
+
104
+ - @rcarls/rc-common@0.4.1
105
+ - @rcarls/rc-menu@0.4.1
106
+
107
+ ## 0.4.0
108
+
109
+ ### Minor Changes
110
+
111
+ - 3e89095: Replace rc-menu's generated submenu glyph with an author-supplied `indicator`
112
+ slot on rc-menu-button. Keep the decorative indicator inside the trigger bounds,
113
+ reserve label space for it, and expose theme-neutral size, color, and inset
114
+ tokens for Material, Substrate, and application themes.
115
+
116
+ ### Patch Changes
117
+
118
+ - 69e31c1: Document the `open`, `default-open`, and `orientation` attributes in the class
119
+ JSDoc and package README. Only `placement` had an `@attr` tag, so the
120
+ generated ApiTable and README were missing three of the four settable
121
+ attributes.
122
+ - 4cb5551: Fix `defaultOpen` so it no longer reopens the menu after an explicit controlled
123
+ `open = false` write. The setter compared against the live `_open` value
124
+ instead of tracking whether a controlled write had occurred, so a common
125
+ pattern like React always passing `open={false}` left the component thinking
126
+ it was still uncontrolled.
127
+ - Updated dependencies [e57277f]
128
+ - Updated dependencies [ccca8e2]
129
+ - Updated dependencies [037b1b3]
130
+ - Updated dependencies [3e89095]
131
+ - @rcarls/rc-common@0.4.0
132
+ - @rcarls/rc-menu@0.4.0
133
+
134
+ ## 0.3.2
135
+
136
+ ### Patch Changes
137
+
138
+ - Updated dependencies [88b4086]
139
+ - @rcarls/rc-common@0.3.2
140
+ - @rcarls/rc-menu@0.3.2
141
+
142
+ ## 0.3.1
143
+
144
+ ### Patch Changes
145
+
146
+ - @rcarls/rc-common@0.3.1
147
+ - @rcarls/rc-menu@0.3.1
148
+
149
+ ## 0.3.0
150
+
151
+ ### Changed
152
+
153
+ - Normalize trigger styling around inherited menu-button custom properties.
154
+ - Update package metadata, README intro, and docs links.
155
+
156
+ ### Dependencies
157
+
158
+ - Sync internal dependencies to 0.3.0.
159
+
160
+ ## 0.2.0
161
+
162
+ ### Patch Changes
163
+
164
+ - @rcarls/rc-common@0.2.0
165
+ - @rcarls/rc-menu@0.2.0
package/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # `@rcarls/rc-menu-button`
2
+
3
+ Trigger button that opens an `rc-menu` popup, following the [WAI-ARIA Menu Button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/).
4
+
5
+ Docs: [https://richardcarls.github.io/rc-webcomponents/components/rc-menu-button](https://richardcarls.github.io/rc-webcomponents/components/rc-menu-button).
6
+
7
+ Wraps a trigger element and an `rc-menu` popup, wiring ARIA attributes,
8
+ light-dismiss, and keyboard open/close automatically.
9
+
10
+ ---
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @rcarls/rc-menu-button
16
+ ```
17
+
18
+ ## Import
19
+
20
+ ```js
21
+ import '@rcarls/rc-menu-button/define'; // side-effect: registers <rc-menu-button>
22
+ import { RCMenuButton } from '@rcarls/rc-menu-button'; // named class export
23
+ ```
24
+
25
+ `rc-menu-button` depends on `rc-menu`. Ensure both are installed.
26
+
27
+ ---
28
+
29
+ ## Basic usage
30
+
31
+ Place a trigger element in the `trigger` slot and an `rc-menu` in the default slot.
32
+
33
+ ```html
34
+ <rc-menu-button>
35
+ <button slot="trigger">File</button>
36
+ <span slot="indicator" aria-hidden="true">›</span>
37
+
38
+ <rc-menu label="File">
39
+ <button>New</button>
40
+ <button>Open…</button>
41
+ <button>Save</button>
42
+ </rc-menu>
43
+ </rc-menu-button>
44
+ ```
45
+
46
+ The component automatically sets `aria-haspopup="menu"` and `aria-expanded` on
47
+ the trigger, and closes the menu when the user clicks outside or selects an
48
+ item.
49
+
50
+ ---
51
+
52
+ ## API
53
+
54
+ ### Properties / attributes
55
+
56
+ | Property | Attribute | Type | Default | Description |
57
+ | ------------- | -------------- | ----------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
58
+ | `open` | `open` | `boolean` | `false` | Whether the menu popup is visible. Reflects to attribute. Controlled mode: host writes silently. |
59
+ | `defaultOpen` | `default-open` | `boolean` | `false` | Initial open state for uncontrolled mode. Ignored after the first controlled write to `open`. |
60
+ | `orientation` | `orientation` | `'horizontal' \| 'vertical' \| undefined` | `undefined` | Arrow-key axis for opening the menu. Vertical triggers span their allocated menu-row width. When unset, inherited from a parent `rc-menubar` or `[role="menubar"]` element. Falls back to `'horizontal'`. |
61
+ | `placement` | `placement` | `AnchorPlacement` | `'bottom-start'` | Preferred placement of the popup relative to the trigger. Switches to `'right-start'` under vertical orientation unless explicitly overridden. |
62
+ | | `icon-only` | boolean attribute | absent | Hints that the trigger has no visible label so themes can apply icon-button sizing and activation-area geometry. |
63
+
64
+ ### CSS custom properties
65
+
66
+ | Property | Default | Description |
67
+ | ---------------------------------------------------- | ------------------------------------------------ | --------------------------------------------------------------- |
68
+ | `--rc-menu-button-trigger-block-size` | `var(--rc-control-block-size)` | Minimum block size of the trigger |
69
+ | `--rc-menu-button-trigger-padding-block` | `var(--rc-control-padding-block)` | Trigger block-axis padding |
70
+ | `--rc-menu-button-trigger-padding-inline` | `var(--rc-control-padding-inline)` | Trigger inline-axis padding |
71
+ | `--rc-menu-button-trigger-gap` | `var(--rc-item-gap)` | Gap between flex children inside the trigger |
72
+ | `--rc-menu-button-trigger-border` | `var(--rc-border)` | Trigger border |
73
+ | `--rc-menu-button-trigger-radius` | `var(--rc-control-radius)` | Trigger border radius |
74
+ | `--rc-menu-button-trigger-background` | `var(--rc-button-bg)` | Trigger background |
75
+ | `--rc-menu-button-trigger-color` | `var(--rc-button-text)` | Trigger text color |
76
+ | `--rc-menu-button-trigger-transition` | `none` | Trigger state transition |
77
+ | `--rc-menu-button-trigger-hover-background` | `color-mix(in srgb, Highlight 8%, transparent)` | Trigger hover background |
78
+ | `--rc-menu-button-trigger-hover-color` | `inherit` | Trigger hover text color |
79
+ | `--rc-menu-button-trigger-hover-border-color` | `currentColor` | Trigger hover border color |
80
+ | `--rc-menu-button-trigger-open-background` | `color-mix(in srgb, Highlight 12%, transparent)` | Trigger background while the menu is open |
81
+ | `--rc-menu-button-trigger-open-color` | `inherit` | Trigger text color while the menu is open |
82
+ | `--rc-menu-button-trigger-open-border-color` | `currentColor` | Trigger border color while the menu is open |
83
+ | `--rc-menu-button-indicator-size` | `1em` | Inline and block size reserved for the optional indicator |
84
+ | `--rc-menu-button-indicator-color` | `currentColor` | Color of the optional indicator |
85
+ | `--rc-menu-button-indicator-inset` | Trigger inline padding | Indicator distance from the trigger's inline end |
86
+ | `--rc-menu-button-icon-size` | Trigger block size | Visible inline size of an `icon-only` trigger |
87
+ | `--rc-menu-button-touch-target-block-size` | `3rem` | Minimum block size of an `icon-only` trigger's activation area |
88
+ | `--rc-menu-button-touch-target-inline-size` | Activation-area block size | Minimum inline size of an `icon-only` trigger's activation area |
89
+ | `--rc-menu-button-touch-target-overlap-inline-start` | `0px` | Allows touch-target inflation to overlap the leading neighbor |
90
+ | `--rc-menu-button-touch-target-overlap-inline-end` | `0px` | Allows touch-target inflation to overlap the trailing neighbor |
91
+
92
+ ### CSS parts
93
+
94
+ | Part | Element | Description |
95
+ | ------- | ----------- | ------------------------------------------------------- |
96
+ | `root` | Outer `div` | Root wrapper |
97
+ | `popup` | Popup `div` | Container that shows/hides around the slotted `rc-menu` |
98
+
99
+ ### Slots
100
+
101
+ | Slot | Description |
102
+ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
103
+ | `trigger` | The button (or other interactive element) that toggles the menu. Receives `aria-haspopup` and `aria-expanded` automatically. |
104
+ | `indicator` | Optional author-supplied decorative submenu indicator. Rendered at the trigger's inline end with pointer events passed through to the trigger. |
105
+ | _(default)_ | The `rc-menu` to show as the popup. |
106
+
107
+ ### Events
108
+
109
+ | Event | Bubbles | Cancelable | Detail | When |
110
+ | ----------------------- | -------------- | ---------- | ------------------- | -------------------- |
111
+ | `rc-menu-button-toggle` | Yes (composed) | No | `{ open: boolean }` | Menu opens or closes |
112
+
113
+ ### Public methods
114
+
115
+ ```ts
116
+ openMenu(focusTarget?: 'first' | 'last'): void
117
+ // Open the menu. Focuses the first or last item after render.
118
+
119
+ closeMenu(returnFocus?: boolean): void
120
+ // Close the menu. If returnFocus is true (default), restores focus to the trigger.
121
+
122
+ toggleMenu(): void
123
+ // Toggle open/closed.
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Keyboard behavior
129
+
130
+ Keyboard handling depends on the resolved `orientation` (horizontal by
131
+ default, or inherited from a parent menubar).
132
+
133
+ | Key | Condition | Action |
134
+ | ----------------- | ---------------------- | ----------------------------------- |
135
+ | `ArrowDown` | Horizontal orientation | Open menu, focus first item |
136
+ | `ArrowUp` | Horizontal orientation | Open menu, focus last item |
137
+ | `ArrowRight` | Vertical orientation | Open menu, focus first item |
138
+ | `ArrowLeft` | Vertical orientation | Open menu, focus last item |
139
+ | `Enter` / `Space` | Menu closed | Open menu |
140
+ | `Enter` / `Space` | Menu open | Activate focused item, close menu |
141
+ | `Escape` | Menu open | Close menu, return focus to trigger |
142
+
143
+ ---
144
+
145
+ ## ARIA
146
+
147
+ | Attribute | Where | Value |
148
+ | ---------------------- | --------------- | ---------------------------------------------- |
149
+ | `aria-haspopup="menu"` | Trigger element | Set automatically on slot change |
150
+ | `aria-expanded` | Trigger element | `"true"` / `"false"`, kept in sync with `open` |
151
+ | `open` | Host element | Reflected boolean attribute when menu is open |
152
+
153
+ ---
154
+
155
+ ## Notes
156
+
157
+ **Popup positioning** uses `AnchorController`, with native CSS Anchor
158
+ Positioning when available and a viewport-aware fallback otherwise. Set the
159
+ `placement` property or attribute to choose the preferred direction.
160
+
161
+ **Light dismiss** is active at all times. A capture-phase `click` listener on
162
+ `document` closes the menu whenever the click falls outside the component
163
+ boundary (checked via `composedPath()`).
164
+
165
+ ---
166
+
167
+ ## Browser support
168
+
169
+ All modern browsers. Requires Web Components support (Chrome 67+, Firefox 63+, Safari 12.1+).