Menu

Combine a list of secondary actions into single interactive area
Import

Usage

import { Menu, Divider, Text } from '@mantine/core';
import { GearIcon, ChatBubbleIcon, ImageIcon, MagnifyingGlassIcon, TrashIcon, PinRightIcon } from '@modulz/radix-icons';
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.Item
icon={<MagnifyingGlassIcon />}
rightSection={<Text size="xs" color="dimmed">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 hover
  • delay 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}>
{/* ... menu items */}
</Menu>

Menu.Item component

Menu.Item renders button and accepts following props:

  • icon – icon on the left
  • children – item label
  • rightSection – react node, rendered on the right, for example, Badge or keyboard shortcut
  • disabled – disables item
  • ...others – Menu.Item produces button element, all other props will be spread to it, for example, onClick, style, sx, className
<Menu.Item
icon={<GearIcon />}
onClick={() => console.log('Hello')}
rightSection={
<Text size="sm" color="gray">
K
</Text>
}
>
Label
</Menu.Item>

Disabled item

<Menu>
<Menu.Item disabled icon={<MagnifyingGlassIcon width={14} height={14} />}>
Search
</Menu.Item>
{/* ...other items */}
</Menu>

Custom control

By default, menu button uses ActionIcon with horizontal dots. You can change it by setting control and controlRefProp props. controlRefProp is a prop name with which element ref can be accessed. It defaults to ref, to change that set controlRefProp="customRefProp".

<Menu control={<button type="button">Button control</button>}>
{/* Menu items */}
</Menu>
<Menu control={<Button>Mantine Button</Button>}>
{/* Menu items */}
</Menu>

Custom control with component

Change menu position

Menu is rendered inside Portal and its position is controlled with the following props:

  • position – left, right, bottom, top
  • placement – start, center, end
  • gutter – spacing between menu body and target element in px
  • withArrow – displays arrow, arrow position is calculated by position and placement 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:

<Menu
transition="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
Size
xs
sm
md
lg
xl
Shadow
xs
sm
md
lg
xl
<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

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.Item
icon={<ExternalLinkIcon />}
component="a"
href="https://mantine.dev"
target="_blank"
>
External link
</Menu.Item>
</Menu>

Store items separately

Menu does not support fragments, the following example will not work:

// Won't work, will not render items
const 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 expected
const 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 control element ref

import { useRef } from 'react';
import { Menu } from '@mantine/core';
function Demo() {
const menuControlRef = useRef();
return <Menu ref={menuControlRef} />;
}

Accessibility and usability

To make component more accessible for users with screen readers set menuButtonLabel prop. Set it in case you use a 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 or presses escape
  • Menu control has aria-haspopup, aria-expanded, aria-controls and aria-label attributes, aria-label is defined by menuButtonLabel prop
  • Menu body has menu role, aria-orientation is always set to vertical
  • Menu item has menuitem role
Build fully functional accessible web applications faster than ever
Feedback
Your feedback is most valuable contribution to the project, please share how you use Mantine, what features are missing and what is done good
Leave feedback