MenuTrigger
The MenuTrigger serves as a wrapper around a Menu and its associated trigger, linking the Menu's open state with the trigger's press state.
install | yarn add @react-spectrum/menu |
---|---|
version | 3.1.0 |
usage | import {MenuTrigger, Menu} from '@react-spectrum/menu' |
Example#
<MenuTrigger>
<ActionButton>Edit</ActionButton>
<Menu>
<Item>Cut</Item>
<Item>Copy</Item>
<Item>Paste</Item>
</Menu>
</MenuTrigger>
<MenuTrigger>
<ActionButton>Edit</ActionButton>
<Menu>
<Item>Cut</Item>
<Item>Copy</Item>
<Item>Paste</Item>
</Menu>
</MenuTrigger>
<MenuTrigger>
<ActionButton>
Edit
</ActionButton>
<Menu>
<Item>Cut</Item>
<Item>Copy</Item>
<Item>Paste</Item>
</Menu>
</MenuTrigger>
Content#
The MenuTrigger accepts exactly two children: the Menu and the element which triggers the opening of the Menu. The trigger element must be the first child passed into the MenuTrigger and should support press events.
Events#
MenuTrigger accepts an onOpenChange
handler which is triggered whenever the Menu is opened or closed.
function Example() {
let [isOpen setIsOpen] = ReactuseState(false);
return (
<Flex gap="size-100" alignItems="center">
<MenuTrigger onOpenChange= setIsOpen>
<ActionButton>Edit</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
<div>Currently open: isOpentoString()</div>
</Flex>
);
}
function Example() {
let [isOpen setIsOpen] = ReactuseState(false);
return (
<Flex gap="size-100" alignItems="center">
<MenuTrigger onOpenChange= setIsOpen>
<ActionButton>Edit</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
<div>Currently open: isOpentoString()</div>
</Flex>
);
}
function Example() {
let [
isOpen
setIsOpen
] = ReactuseState(
false
);
return (
<Flex
gap="size-100"
alignItems="center">
<MenuTrigger
onOpenChange=
setIsOpen
>
<ActionButton>
Edit
</ActionButton>
<Menu>
<Item key="cut">
Cut
</Item>
<Item key="copy">
Copy
</Item>
<Item key="paste">
Paste
</Item>
</Menu>
</MenuTrigger>
<div>
Currently open:' '
isOpentoString()
</div>
</Flex>
);
}
Props#
Name | Type | Default | Description |
children | ReactElement[] | — | The contents of the MenuTrigger - a trigger and a Menu. |
align | Alignment | 'start' | Alignment of the menu relative to the trigger. |
direction | 'bottom' | 'top' | 'bottom' | Where the Menu opens relative to its trigger. |
closeOnSelect | boolean | true | Whether the Menu closes when a selection is made. |
shouldFlip | boolean | true | Whether the menu should automatically flip direction when space is limited. |
isOpen | boolean | — | Whether the overlay is open by default (controlled). |
defaultOpen | boolean | — | Whether the overlay is open by default (uncontrolled). |
Events
Name | Type | Default | Description |
onOpenChange | (
(isOpen: boolean
)) => void | — | Handler that is called when the overlay's open state changes. |
Visual options#
Align and direction#
The align
prop aligns the Menu relative to the trigger and the direction
prop controls the direction the Menu will render.
import More from '@spectrum-icons/workflow/More';
<Flex gap="size-100">
<MenuTrigger align="start">
<ActionButton aria-label="More options">
<More />
</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
<MenuTrigger align="end" direction="top" shouldFlip=false>
<ActionButton>Edit options</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
</Flex>
import More from '@spectrum-icons/workflow/More';
<Flex gap="size-100">
<MenuTrigger align="start">
<ActionButton aria-label="More options">
<More />
</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
<MenuTrigger
align="end"
direction="top"
shouldFlip=false>
<ActionButton>Edit options</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
</Flex>
import More from '@spectrum-icons/workflow/More';
<Flex gap="size-100">
<MenuTrigger align="start">
<ActionButton aria-label="More options">
<More />
</ActionButton>
<Menu>
<Item key="cut">
Cut
</Item>
<Item key="copy">
Copy
</Item>
<Item key="paste">
Paste
</Item>
</Menu>
</MenuTrigger>
<MenuTrigger
align="end"
direction="top"
shouldFlip=false>
<ActionButton>
Edit options
</ActionButton>
<Menu>
<Item key="cut">
Cut
</Item>
<Item key="copy">
Copy
</Item>
<Item key="paste">
Paste
</Item>
</Menu>
</MenuTrigger>
</Flex>
Close on selection#
By default, the Menu closes when an item is selected. To change this, set the closeOnSelect
prop to false
. This might be useful when multiple selection is used. See menu selection for more information.
<MenuTrigger closeOnSelect=false>
<ActionButton>View</ActionButton>
<Menu selectionMode="multiple">
<Item key="side">Side bar</Item>
<Item key="options">Page options</Item>
<Item key="edit">Edit Panel</Item>
</Menu>
</MenuTrigger>
<MenuTrigger closeOnSelect=false>
<ActionButton>View</ActionButton>
<Menu selectionMode="multiple">
<Item key="side">Side bar</Item>
<Item key="options">Page options</Item>
<Item key="edit">Edit Panel</Item>
</Menu>
</MenuTrigger>
<MenuTrigger
closeOnSelect=
false
>
<ActionButton>
View
</ActionButton>
<Menu selectionMode="multiple">
<Item key="side">
Side bar
</Item>
<Item key="options">
Page options
</Item>
<Item key="edit">
Edit Panel
</Item>
</Menu>
</MenuTrigger>
Flipping#
By default, the Menu flips direction automatically upon opening when space is limited. To change this, set the shouldFlip
prop to false
. Try scrolling the viewport close to the edge of the trigger in the example to see this in action.
<Flex gap="size-100">
<MenuTrigger shouldFlip>
<ActionButton aria-label="More options">
<More />
</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
<MenuTrigger shouldFlip=false>
<ActionButton>Edit</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
</Flex>
<Flex gap="size-100">
<MenuTrigger shouldFlip>
<ActionButton aria-label="More options">
<More />
</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
<MenuTrigger shouldFlip=false>
<ActionButton>Edit</ActionButton>
<Menu>
<Item key="cut">Cut</Item>
<Item key="copy">Copy</Item>
<Item key="paste">Paste</Item>
</Menu>
</MenuTrigger>
</Flex>
<Flex gap="size-100">
<MenuTrigger
shouldFlip>
<ActionButton aria-label="More options">
<More />
</ActionButton>
<Menu>
<Item key="cut">
Cut
</Item>
<Item key="copy">
Copy
</Item>
<Item key="paste">
Paste
</Item>
</Menu>
</MenuTrigger>
<MenuTrigger
shouldFlip=false>
<ActionButton>
Edit
</ActionButton>
<Menu>
<Item key="cut">
Cut
</Item>
<Item key="copy">
Copy
</Item>
<Item key="paste">
Paste
</Item>
</Menu>
</MenuTrigger>
</Flex>
Open#
The isOpen
and defaultOpen
props on the MenuTrigger control whether the Menu is open by default.
They apply controlled and uncontrolled behavior on the Menu respectively.
function Example() {
let [open setOpen] = ReactuseState(false);
let [selection setSelection] = ReactuseState('');
return (
<MenuTrigger
isOpen= open
onOpenChange= setOpen
onSelectionChange= setSelection>
<ActionButton>View</ActionButton>
<Menu selectionMode="multiple">
<Item key="side">Side bar</Item>
<Item key="options">Page options</Item>
<Item key="edit">Edit Panel</Item>
</Menu>
</MenuTrigger>
);
}
function Example() {
let [open setOpen] = ReactuseState(false);
let [selection setSelection] = ReactuseState('');
return (
<MenuTrigger
isOpen= open
onOpenChange= setOpen
onSelectionChange= setSelection>
<ActionButton>View</ActionButton>
<Menu selectionMode="multiple">
<Item key="side">Side bar</Item>
<Item key="options">Page options</Item>
<Item key="edit">Edit Panel</Item>
</Menu>
</MenuTrigger>
);
}
function Example() {
let [
open
setOpen
] = ReactuseState(
false
);
let [
selection
setSelection
] = ReactuseState('');
return (
<MenuTrigger
isOpen= open
onOpenChange=
setOpen
onSelectionChange=
setSelection
>
<ActionButton>
View
</ActionButton>
<Menu selectionMode="multiple">
<Item key="side">
Side bar
</Item>
<Item key="options">
Page options
</Item>
<Item key="edit">
Edit Panel
</Item>
</Menu>
</MenuTrigger>
);
}