Menu
Accessible dropdown Menu component that follows the WAI-ARIA Menu.
Usage
import {
Menu,
MenuList,
MenuButton,
MenuItem,
useMenuState,
MenuSeparator,
} from '@vtex/admin-ui'
function Example() {
const state = useMenuState()
return (
<Menu state={state}>
<MenuButton>Post options</MenuButton>
<MenuList aria-label="actions" state={state}>
<MenuItem icon={<IconArrowLineDown />}>Download</MenuItem>
<MenuItem icon={<IconLink />}>Link to</MenuItem>
<MenuSeparator />
<MenuItem icon={<IconHeart />}>Favorite</MenuItem>
</MenuList>
</Menu>
)
}
Composition
| Name | Description |
|---|---|
| Menu | Wrapper for the Menu |
| MenuButton | Button that triggers the menu popover |
| MenuList | Menu's popover |
| MenuItem | Represents a button rendered inside the MenuList |
| MenuSeparator | Represents an hr used to separate the menu popover into sections |
Examples
Hide on click
Hide the Menu popover after a MenuItem is clicked.
function Example() {
const state = useMenuState()
return (
<Menu state={state} hideOnClick>
<MenuButton>Post options</MenuButton>
<MenuList aria-label="actions" state={state}>
<MenuItem icon={<IconArrowLineDown />}>Download</MenuItem>
<MenuItem disabled icon={<IconLink />}>
Disabled Link
</MenuItem>
<MenuSeparator />
<MenuItem icon={<IconHeart />}>Favorite</MenuItem>
</MenuList>
</Menu>
)
}
Action
Set the MenuButton icon by using the display property
function Example() {
const state = useMenuState()
return (
<Menu state={state} hideOnClick>
<MenuButton display="actions" variant="text" />
<MenuList aria-label="actions" state={state}>
<MenuItem icon={<IconArrowLineDown />}>Download</MenuItem>
<MenuItem disabled icon={<IconLink />}>
Disabled Link
</MenuItem>
<MenuSeparator />
<MenuItem icon={<IconHeart />}>Favorite</MenuItem>
</MenuList>
</Menu>
)
}
Placement
Set the position of Menu's popover
function Example() {
const state = useMenuState({ placement: 'right' })
return (
<Menu state={state} hideOnClick>
<MenuButton display="actions" variant="text" />
<MenuList aria-label="actions" state={state}>
<MenuItem icon={<IconArrowLineDown />}>Download</MenuItem>
<MenuItem disabled icon={<IconLink />}>
Disabled Link
</MenuItem>
<MenuSeparator />
<MenuItem icon={<IconHeart />}>Favorite</MenuItem>
</MenuList>
</Menu>
)
}
Initial Focus
Select a MenuItem to be focused when the popover is opened
function Example() {
const state = useMenuState()
const ref = React.useRef()
React.useEffect(() => {
if (state.visible) {
ref.current.focus()
}
}, [state.visible])
return (
<Menu state={state}>
<MenuButton>Post options</MenuButton>
<MenuList aria-label="actions" state={state}>
<MenuItem icon={<IconArrowLineDown />}>Download</MenuItem>
<MenuItem ref={ref} icon={<IconLink />}>
Link to
</MenuItem>
<MenuSeparator />
<MenuItem icon={<IconHeart />}>Favorite</MenuItem>
</MenuList>
</Menu>
)
}
Accessibility
MenuListhas rolemenu.MenuItemhas rolemenuitem.- Pressing Enter on
MenuButtonopens theMenuListand places focus on its first item. - When
MenuItemhas focus, Space and Enter triggers it.
Best Practices
- You always must set the
aria-labelproperty in theMenuListcomponent.
function Example() {
const state = useMenuState()
return (
<Menu state={state} hideOnClick>
<MenuButton display="actions" variant="text" />
<MenuList aria-label="actions" state={state}>
<MenuItem icon={<IconImport />}>Download</MenuItem>
<MenuItem disabled icon={<IconLink />}>
Disabled Link
</MenuItem>
<MenuSeparator />
<MenuItem icon={<IconFavorite />}>Favorite</MenuItem>
</MenuList>
</Menu>
)
}
Keyboard Navigation
- ↓ moves focus to the next `MenuItem`.
- ↑ moves focus to the previous `MenuItem`.
Props
Menu
| Name | Type | Description | Required | Default |
|---|---|---|---|---|
| state | MenuStateReturn | useMenuState hook return | ✅ | - |
| children | ReactNode | Menu's composites | 🚫 | - |
| hideOnClick | boolean | Whether the Menu popup should hide after a MenuItem is clicked | 🚫 | false |
MenuButton
All props of admin-ui's Button component.
| Name | Type | Description | Required | Default | |
|---|---|---|---|---|---|
| display | `actions | menu'` | Display the dots icon if is actions and caret down if menu | 🚫 | menu |
MenuList
Besides the props listed bellow, you can use all the props accepted by the div JSX element.
| Name | Type | Description | Required | Default |
|---|---|---|---|---|
| hideOnClickOutside | boolean | Whether the Menu popup should hide after a click outside the popover or not | 🚫 | true |
MenuItem
Besides the props listed bellow, you can use all the props accepted by the button JSX element.
| Name | Type | Description | Required | Default |
|---|---|---|---|---|
| tone | regular, critical | Tone of voice | 🚫 | regular |
| icon | ReactNode | Icon of the item | 🚫 | - |
Separator
All props of hr jsx element.
useMenuState
| Name | Type | Description | Required | Default |
|---|---|---|---|---|
| loop | boolean | Loops from the last item to the first item and vice-versa. | 🚫 | false |
| visible | boolean | Whether is visible or not | 🚫 | false |
| placement | bottom, bottom-start, bottom-end, right, right-start, right-end, auto, auto-start... | Menu popover position | 🚫 | bottom |
| baseId | string | ID that will serve as a base for all the items IDs. | 🚫 | - |
| gutter | number | Offset between the reference and the popover on the main axis. | 🚫 | 4 |