Menu
Usage
import React from 'react';import { Menu, MenuItem, MenuLabel, Divider, Text } from '@mantine/core';function Demo() {return (<Menu><Menu.Label>Application</Menu.Label><Menu.Item icon={<GearIcon />}>Settings</Menu.Item><Menu.Item icon={<ChatBubbleIcon />}>Messages</Menu.Item><Menu.Item icon={<ImageIcon />}>Gallery</Menu.Item><Menu.Itemicon={<MagnifyingGlassIcon />}rightSection={<Text size="xs" color="gray">⌘K</Text>}>Search</Menu.Item><Divider /><Menu.Label>Danger zone</Menu.Label><Menu.Item icon={<PinRightIcon />}>Transfer my data</Menu.Item>,<Menu.Item color="red" icon={<TrashIcon />}>Delete my account</Menu.Item></Menu>);}
Controlled
To control component opened state provide opened
, onClose
and onOpen
props:
import { useState } from 'react';import { Menu } from '@mantine/core';function Demo() {const [opened, setOpened] = useState(false);return (<Menu opened={opened} onOpen={() => setOpened(true)} onClose={() => setOpened(false)}>{/* Menu items... */}</Menu>);}
Show menu on hover
To show menu on hover set props:
trigger
to hoverdelay
to number in ms (defaults to 0)
In this case menu will use onMouseEnter
and onFocus
events instead of onClick
:
<Menu trigger="hover" delay={500} closeOnScroll={false}>{/* ... menu items */}</Menu>
Menu.Item component
You can use Divider (renders horizontal line) and Menu.Item components inside Menu. Menu.Item renders button and accepts props:
- icon – icon on the left
- children – item label
- rightSection – any element, rendered on the right, for example, Badge or keyboard shortcut
- ...others – Menu.Item produces button element, all other props will be spread to it, for example,
onClick
,style
,className
<Menu.Itemicon={<GearIcon />}onClick={() => console.log('Hello')}rightSection={<Text size="sm" color="gray">⌘K</Text>}>Label</Menu.Item>
Custom control
By default menu button uses ActionIcon with horizontal dots.
You can change it by setting control
and controlRefProp
props:
<Menucontrol={<button type="button">Button control</button>}controlRefProp="ref">{/* Menu items */}</Menu><Menu control={<Button>Mantine Button</Button>}>{/* Menu items */}</Menu>
controlRefProp
is the prop name with which element ref can be accessed.
It defaults to elementRef
as all interactive Mantine components use it to get ref.
For regular html element it will be controlRefProp="ref"
Change menu position
Menu is rendered inside Portal and its position is controlled with the following props:
position
– left, right, bottom, topplacement
– start, center, endgutter
– spacing between menu body and target element in pxwithArrow
– displays arrow, arrow position is calculated byposition
andplacement
props
Note that in most cases you will need to change Transition to match your position:
<Menu>{/* Menu items */}</Menu>
Change transition
Menu is built with Transition component. You can customize transition, timing function and duration:
<Menutransition="rotate-right"transitionDuration={100}transitionTimingFunction="ease">{/* Menu items */}</Menu>
Size and shadow
You can use predefined shadows defined in theme.shadows or your own:
<Menu shadow="sm" /> // -> predefined small shadow<Menu shadow="1px 1px 3px rgba(0, 0, 0, .1)" /> // -> custom shadow
<Menu>{/* Menu items */}</Menu>
Menu has predefined sizes: xs, sm, md, lg, xl. Size prop controls menu width. You can also use number value to set width in px:
<Menu size="sm" /> // -> predefined small width<Menu size={200} /> // -> 200px width
You can get predefined menu sizes by importing MENU_SIZES
:
import { MENU_SIZES } from '@mantine/core';
Prop value | Menu width |
---|---|
xs | 120px |
sm | 160px |
md | 200px |
lg | 240px |
xl | 300px |
Custom component as Menu.Item
By default menu items render as button, to change that set component
prop on Menu.Item component:
// Regular anchor as Menu.Item root element<Menu.Item component="a" href="https://mantine/dev" target="_blank" />// React router link as Menu.Item root element<Menu.Item component={Link} to="/hello" />
<Menu><Menu.Item component="a" href="https://mantine.dev">Mantine website</Menu.Item><Menu.Itemicon={<ExternalLinkIcon />}component="a"href="https://mantine.dev"target="_blank">External link</Menu.Item></Menu>
Menu.Item as Next.js Link
Next Link component requires ref
prop usage, however all Mantine components use elementRef
,
to make Menu.Item and other similar components work with Next Link, create wrapper component in your components folder:
// This component can be reused in every Mantine component which supports component pass throughimport React, { forwardRef } from 'react';import Link from 'next/link';export const NextLink = forwardRef(({ href, ...others }: React.ComponentPropsWithoutRef<typeof Link>,ref: React.ForwardedRef<HTMLAnchorElement>) => (<Link href={href}>{/* eslint-disable-next-line jsx-a11y/anchor-has-content */}<a {...others} ref={ref} /></Link>));
And then pass it to Menu.Item or other component:
<Menu.Item component={NextLink} href="/hello">Next Link menu item</Menu.Item>
Customize behavior
You can control menu behavior with following props:
trapFocus
– traps focus inside menu when it is openedcloseOnScroll
– closes menu when page is scrolled
By default both options are true
to ensure better accessibility, to turn them off set to false
:
<Menu trapFocus={false} closeOnScroll={false} />
Store items separately
Menu does not support fragments, the following example will not work:
// Won't work, will not render itemsconst items = (<><Menu.Item>First</Menu.Item><Menu.Item>Second</Menu.Item></>);<Menu>{items}</Menu>;
In case you want to store items separately use array instead of fragment:
// Works as expectedconst items = [<Menu.Item>First</Menu.Item><Menu.Item>Second</Menu.Item>];<Menu>{items}</Menu>;
Add your styles with styles API
You can customize add styles to any part of Menu with Styles API, for example, change hovered item color:
import { Menu, createStyles } from '@mantine/core';const useStyles = createStyles((theme) => ({itemHovered: {backgroundColor: theme.colors[theme.primaryColor][7],color: theme.white,},}));function Demo() {const classes = useStyles();return (<Menu classNames={classes}>{/* Menu items... */}</Menu>);}
Get element ref
You can get menu control ref by passing elementRef
prop to Menu component:
import { useRef } from 'react';import { Menu } from '@mantine/core';function Demo() {const menuControlRef = useRef();return <Menu elementRef={menuControlRef} />;}
Server side rendering
Component uses use-id hook to generate unique ids and aria- attributes,
provide static menuId
prop to prevent props mismatch:
<Menu /> // -> random id generated both on client and server, props mismatch warning<Menu menuId="my-menu" /> // -> id is static, no mismatches
Accessibility and usability
To make component more accessible for users with screen readers set menuButtonLabel
prop.
Use it in case you chose control which does not include text, for example, default ActionIcon with horizontal dots icon.
Component behavior and properties:
- When menu is opened focus is trapped inside
- When menu is closed focus is moved back to menu control
- Focus inside menu is controlled with up and down arrows, tab key has no effect
- By default when menu item is clicked, menu closes, change it with
closeOnItemClick
prop - Menu is closed when user clicks outside ot presses escape
- Menu control has
aria-haspopup
,aria-expanded
,aria-controls
andaria-label
attributes,aria-label
is defined bymenuButtonLabel
prop - Menu body has
menu
role,aria-orientation
is always set tovertical
- Menu item has
menuitem
role