Skip to content

Commit 5e4dfb0

Browse files
authored
Menu button and popover can have same width (#5465)
* Adding --trigger-width support to Menu * removing example
1 parent 78a49f5 commit 5e4dfb0

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed

packages/react-aria-components/docs/Menu.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,11 +798,11 @@ The [Popover](Popover.html) component can be targeted with the `.react-aria-Popo
798798

799799
<StateTable properties={docs.exports.PopoverRenderProps.properties} />
800800

801-
Within a MenuTrigger, the popover will have the `data-trigger="MenuTrigger"` attribute, which can be used to define menu-specific styles.
801+
Within a MenuTrigger, the popover will have the `data-trigger="MenuTrigger"` attribute, which can be used to define menu-specific styles. In addition, the `--trigger-width` CSS custom property will be set on the popover, which you can use to make the popover match the width of the menu button.
802802

803803
```css render=false
804804
.react-aria-Popover[data-trigger=MenuTrigger] {
805-
/* ... */
805+
width: var(--trigger-width);
806806
}
807807
```
808808

packages/react-aria-components/src/Menu.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ import {AriaMenuProps, mergeProps, useFocusRing, useMenu, useMenuItem, useMenuSe
1515
import {BaseCollection, CollectionProps, ItemRenderProps, useCachedChildren, useCollection, useSSRCollectionNode} from './Collection';
1616
import {MenuTriggerProps as BaseMenuTriggerProps, Node, TreeState, useMenuTriggerState, useTreeState} from 'react-stately';
1717
import {ContextValue, forwardRefType, Provider, RenderProps, SlotProps, StyleProps, useContextProps, useRenderProps, useSlot} from './utils';
18-
import {filterDOMProps, mergeRefs, useObjectRef} from '@react-aria/utils';
18+
import {filterDOMProps, mergeRefs, useObjectRef, useResizeObserver} from '@react-aria/utils';
1919
import {Header} from './Header';
2020
import {Key, LinkDOMProps} from '@react-types/shared';
2121
import {KeyboardContext} from './Keyboard';
2222
import {OverlayTriggerStateContext} from './Dialog';
2323
import {PopoverContext} from './Popover';
2424
import {PressResponder} from '@react-aria/interactions';
25-
import React, {createContext, ForwardedRef, forwardRef, ReactNode, RefObject, useContext, useRef} from 'react';
25+
import React, {createContext, ForwardedRef, forwardRef, ReactNode, RefObject, useCallback, useContext, useRef, useState} from 'react';
2626
import {Separator, SeparatorContext} from './Separator';
2727
import {TextContext} from './Text';
2828

@@ -41,13 +41,30 @@ export function MenuTrigger(props: MenuTriggerProps) {
4141
...props,
4242
type: 'menu'
4343
}, state, ref);
44+
// Allows menu width to match button
45+
let [buttonWidth, setButtonWidth] = useState<string | null>(null);
46+
let onResize = useCallback(() => {
47+
if (ref.current) {
48+
setButtonWidth(ref.current.offsetWidth + 'px');
49+
}
50+
}, [ref]);
51+
52+
useResizeObserver({
53+
ref: ref,
54+
onResize: onResize
55+
});
4456

4557
return (
4658
<Provider
4759
values={[
4860
[MenuContext, menuProps],
4961
[OverlayTriggerStateContext, state],
50-
[PopoverContext, {trigger: 'MenuTrigger', triggerRef: ref, placement: 'bottom start'}]
62+
[PopoverContext, {
63+
trigger: 'MenuTrigger',
64+
triggerRef: ref,
65+
placement: 'bottom start',
66+
style: {'--trigger-width': buttonWidth} as React.CSSProperties
67+
}]
5168
]}>
5269
<PressResponder {...menuTriggerProps} ref={ref} isPressed={state.isOpen}>
5370
{props.children}

0 commit comments

Comments
 (0)