This library is still in development and is available only for internal usage at VTEX.
Skip to main content

Menu

Version: 0.131.0

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

NameDescription
MenuWrapper for the Menu
MenuButtonButton that triggers the menu popover
MenuListMenu's popover
MenuItemRepresents a button rendered inside the MenuList
MenuSeparatorRepresents 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

  • MenuList has role menu.
  • MenuItem has role menuitem.
  • Pressing Enter on MenuButton opens the MenuList and places focus on its first item.
  • When MenuItem has focus, Space and Enter triggers it.

Best Practices

  • You always must set the aria-label property in the MenuList component.
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

NameTypeDescriptionRequiredDefault
stateMenuStateReturnuseMenuState hook return-
childrenReactNodeMenu's composites🚫-
hideOnClickbooleanWhether the Menu popup should hide after a MenuItem is clicked🚫false

All props of admin-ui's Button component.

NameTypeDescriptionRequiredDefault
display`actionsmenu'`Display the dots icon if is actions and caret down if menu🚫menu

Besides the props listed bellow, you can use all the props accepted by the div JSX element.

NameTypeDescriptionRequiredDefault
hideOnClickOutsidebooleanWhether the Menu popup should hide after a click outside the popover or not🚫true

Besides the props listed bellow, you can use all the props accepted by the button JSX element.

NameTypeDescriptionRequiredDefault
toneregular, criticalTone of voice🚫regular
iconReactNodeIcon of the item🚫-

Separator

All props of hr jsx element.

useMenuState

NameTypeDescriptionRequiredDefault
loopbooleanLoops from the last item to the first item and vice-versa.🚫false
visiblebooleanWhether is visible or not🚫false
placementbottom, bottom-start, bottom-end, right, right-start, right-end, auto, auto-start...Menu popover position🚫bottom
baseIdstringID that will serve as a base for all the items IDs.🚫-
gutternumberOffset between the reference and the popover on the main axis.🚫4