Menu

Combine a list of secondary actions into single interactive area
Import

Usage

import { Menu, Divider, Text } from '@mantine/core';
import { Settings, Search, Photo, MessageCircle, Trash, ArrowsLeftRight } from 'tabler-icons-react';
function Demo() {
return (
<Menu>
<Menu.Label>Application</Menu.Label>
<Menu.Item icon={<Settings size={14} />}>Settings</Menu.Item>
<Menu.Item icon={<MessageCircle size={14} />}>Messages</Menu.Item>
<Menu.Item icon={<Photo size={14} />}>Gallery</Menu.Item>
<Menu.Item
icon={<Search size={14} />}
rightSection={<Text size="xs" color="dimmed">K</Text>}
>
Search
</Menu.Item>
<Divider />
<Menu.Label>Danger zone</Menu.Label>
<Menu.Item icon={<ArrowsLeftRight size={14} />}>Transfer my data</Menu.Item>
<Menu.Item color="red" icon={<Trash size={14} />}>Delete my account</Menu.Item>
</Menu>
);
}

Controlled

import { useDisclosure } from '@mantine/hooks';
import { Menu } from '@mantine/core';
function Demo() {
const [opened, handlers] = useDisclosure(false);
return (
<Menu opened={opened} onOpen={handlers.open} onClose={handlers.close}>
{/* 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:

import { Menu } from '@mantine/core';
function Demo() {
return (
<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
import { Menu, Text } from '@mantine/core';
import { Settings } from 'tabler-icons-react';
function Demo() {
return (
<Menu>
<Menu.Item
icon={<Settings size={16} />}
onClick={() => console.log('Hello')}
rightSection={
<Text size="sm" color="gray">
K
</Text>
}
>
Label
</Menu.Item>
</Menu>
);
}

Disabled item

import { Menu } from '@mantine/core';
import { Search } from 'tabler-icons-react';
function Demo() {
return (
<Menu>
<Menu.Item disabled icon={<Search size={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".

import { Menu, Button } from '@mantine/core';
function Demo() {
return (
<>
<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:

import { Menu } from '@mantine/core';
function Demo() {
return (
<Menu>
{/* Menu items */}
</Menu>
);
}

Change transition

Menu is built with Transition component. You can customize transition, timing function and duration:

import { Menu } from '@mantine/core';
function Demo() {
return (
<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
import { Menu } from '@mantine/core';
function Demo() {
return (
<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-dom Link as Menu.Item root element
// !important: This approach cannot be used with Next.js Link component
<Menu.Item component={Link} to="/hello" />
import { Menu } from '@mantine/core';
import { ExternalLink } from 'tabler-icons-react';
function Demo() {
return (
<Menu>
<Menu.Item component="a" href="https://mantine.dev">
Mantine website
</Menu.Item>
<Menu.Item
icon={<ExternalLink size={14} />}
component="a"
href="https://mantine.dev"
target="_blank"
>
External link
</Menu.Item>
</Menu>
);
}

Menu.Item as Next.js Link

import { Menu } from '@mantine/core';
import { NextLink } from '@mantine/next';
function Demo() {
return (
<Menu>
<Menu.Item component={NextLink} href="/hello">
Hello
</Menu.Item>
</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<HTMLButtonElement>();
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