The padding required to prevent the arrow from reaching the very edge of the popper.
Menu
An accessible dropdown menu for the common dropdown menu button design pattern. Menu uses roving tabIndex for focus management.
The Menu
component is a multipart component. The styling needs to be applied
to each part specifically.
To learn more about styling multipart components, visit the Component Style page.
Anatomy#
- A:
button
- B:
list
- C:
item
- D:
groupTitle
- E:
command
- F:
divider
Theming properties#
The properties that affect the theming of the Menu
component are:
variant
: The visual variant of the component. There is no default applied.size
: The size of the component. There is no default applied.
Theming utilities#
createMultiStyleConfigHelpers
: a function that returns a set of utilities for creating style configs for a multipart component (definePartsStyle
anddefineMultiStyleConfig
).definePartsStyle
: a function used to create multipart style objects.defineMultiStyleConfig
: a function used to define the style configuration for a multipart component.
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)
Customizing the default theme#
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)// define the base component stylesconst baseStyle = definePartsStyle({// define the part you're going to stylebutton: {// this will style the MenuButton componentfontWeight: 'medium',bg: 'teal.500',color: 'gray.200',_hover: {bg: 'teal.600',color: 'white',},},list: {// this will style the MenuList componentpy: '4',borderRadius: 'xl',border: 'none',bg: 'teal.500',},item: {// this will style the MenuItem and MenuItemOption componentscolor: 'gray.200',_hover: {bg: 'teal.600',},_focus: {bg: 'teal.600',},},groupTitle: {// this will style the text defined by the title prop// in the MenuGroup and MenuOptionGroup componentstextTransform: 'uppercase',color: 'white',textAlign: 'center',letterSpacing: 'wider',opacity: '0.7',},command: {// this will style the text defined by the command// prop in the MenuItem and MenuItemOption componentsopacity: '0.8',fontFamily: 'mono',fontSize: 'sm',letterSpacing: 'tighter',pl: '4',},divider: {// this will style the MenuDivider componentmy: '4',borderColor: 'white',borderBottom: '2px dotted',},})// export the base styles in the component themeexport const menuTheme = defineMultiStyleConfig({ baseStyle })
After customizing the input theme, we can import it into our theme file and add
it in the components
property:
import { extendTheme } from '@chakra-ui/react'import { menuTheme } from './components/Menu'const theme = extendTheme({components: {Menu: menuTheme,},})export default theme
This is a crucial step to make sure that any changes we make to the menu theme are applied.
Adding a custom size#
Let's assume we want to include an extra large menu size. Here's how we can do that:
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)// define custom stylesconst lg = defineStyle({fontSize: 'md',my: '1',})const xl = defineStyle({fontSize: 'lg',px: '4',py: '2',})// define custom sizesconst sizes = {// apply custom styles to partsxl: definePartsStyle({ button: xl, item: xl, groupTitle: lg, command: xl }),}// export the sizes in the component themeexport const menuTheme = defineMultiStyleConfig({ sizes })// now we can use the new `xl` size<Menu size="xl" ... />
Every time you add anything new to the theme, you need to run the CLI command to get proper autocomplete in your IDE. You can learn more about the CLI tool here.
Adding a custom variant#
Let's assume we want to include some custom variants to create a pill-shaped menu bar. Here's how we can do that:
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)// define custom variantsconst variants = {roundLeft: {button: {borderLeftRadius: 'full',pl: '6',},},roundRight: {button: {borderRightRadius: 'full',pr: '6',},},}// export the custom variants in the component themeexport const menuTheme = defineMultiStyleConfig({ variants })// now we can use the new `roundLeft` and `roundRight` variants<Menu variant="roundLeft" ... /><Menu variant="roundRight" ... />
Changing the default properties#
Let's assume we want to change the default size and variant of every menu in our app. Here's how we can do that:
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)// define which sizes and variants are applied by defaultconst defaultProps = {// in this example, we will only set a default sizesize: 'xl',}// export the default properties in the component themeexport const menuTheme = defineMultiStyleConfig({ defaultProps })
Showcase#
import { ChakraProvider, Menu, MenuButton, MenuList, MenuItem, MenuItemOption, MenuGroup, MenuOptionGroup, MenuDivider, Box, Center, } from '@chakra-ui/react'; import theme from './theme'; import { ColorModeSwitcher } from './ColorModeSwitcher'; export default function App() { return ( <ChakraProvider theme={theme}> <Box position="relative" h="100vh" p={12}> <Center> <Menu variant="roundLeft"> <MenuButton>File</MenuButton> <MenuList> <MenuItem command="Ctrl + N">New File</MenuItem> <MenuItem command="Ctrl + O">Open File</MenuItem> <MenuDivider /> <MenuGroup title="Save"> <MenuItem command="Ctrl + S">Save</MenuItem> <MenuItem command="Ctrl + Shift + S">Save As...</MenuItem> <MenuItem command="Ctrl + Alt + S">Save All</MenuItem> </MenuGroup> <MenuDivider /> <MenuItem>Exit</MenuItem> </MenuList> </Menu> <Menu> <MenuButton>Edit</MenuButton> <MenuList> <MenuItem command="Ctrl + Z">Undo</MenuItem> <MenuItem command="Ctrl + Y">Redo</MenuItem> <MenuDivider /> <MenuGroup> <MenuItem command="Ctrl + X">Cut</MenuItem> <MenuItem command="Ctrl + C">Copy</MenuItem> <MenuItem command="Ctrl + V">Paste</MenuItem> </MenuGroup> </MenuList> </Menu> <Menu variant="roundRight"> <MenuButton>View</MenuButton> <MenuList> <MenuItem command="Ctrl + F">Full Screen Mode</MenuItem> <MenuItem command="Ctrl + R">Reading Mode</MenuItem> <MenuDivider /> <MenuGroup title="Zoom"> <MenuItem command="Ctrl + 1">Actual Size</MenuItem> <MenuItem command="Ctrl + 2">Fit Width</MenuItem> <MenuItem command="Ctrl + 3">Height</MenuItem> </MenuGroup> <MenuDivider /> <MenuOptionGroup title="Display Size" type="radio" defaultValue={'standard'} > <MenuItemOption value="small" closeOnSelect={false}> Small </MenuItemOption> <MenuItemOption value="standard" closeOnSelect={false}> Standard </MenuItemOption> <MenuItemOption value="large" closeOnSelect={false}> Large </MenuItemOption> </MenuOptionGroup> </MenuList> </Menu> </Center> <ColorModeSwitcher aria-label="toggle theme" position="absolute" bottom={4} left={4} /> </Box> </ChakraProvider> ); }
Props#
Menu Props#
arrowPadding
arrowPadding
number
8
autoSelect
autoSelect
If true
, the first enabled menu item will receive focus and be selected
when the menu opens.
boolean
true
boundary
boundary
The boundary area for the popper. Used within the preventOverflow
modifier
HTMLElement | "clippingParents" | "scrollParent"
clippingParents
closeOnBlur
closeOnBlur
If true
, the menu will close when you click outside
the menu list
boolean
true
closeOnSelect
closeOnSelect
If true
, the menu will close when a menu item is
clicked
boolean
true
computePositionOnMount
computePositionOnMount
boolean
defaultIsOpen
defaultIsOpen
boolean
direction
direction
If rtl
, proper placement positions will be flipped i.e. 'top-right' will
become 'top-left' and vice-verse
"ltr" | "rtl"
eventListeners
eventListeners
If provided, determines whether the popper will reposition itself on scroll
and resize
of the window.
type ONLY_FOR_FORMAT =
| boolean
| { scroll?: boolean | undefined resize?: boolean | undefined }
true
flip
flip
If true
, the popper will change its placement and flip when it's
about to overflow its boundary area.
boolean
true
gutter
gutter
The distance or margin between the reference and popper.
It is used internally to create an offset
modifier.
NB: If you define offset
prop, it'll override the gutter.
number
8
id
id
string
initialFocusRef
initialFocusRef
The ref
of the element that should receive focus when the popover opens.
RefObject<{ focus(): void }>
isLazy
isLazy
Performance 🚀:
If true
, the MenuItem rendering will be deferred
until the menu is open.
boolean
false
isOpen
isOpen
boolean
lazyBehavior
lazyBehavior
Performance 🚀: The lazy behavior of menu's content when not visible. Only works when `isLazy={true}` - "unmount": The menu's content is always unmounted when not open. - "keepMounted": The menu's content initially unmounted, but stays mounted when menu is open.
LazyMode
unmount
matchWidth
matchWidth
If true
, the popper will match the width of the reference at all times.
It's useful for autocomplete
, `date-picker` and select
patterns.
boolean
false
modifiers
modifiers
Array of popper.js modifiers. Check the docs to see the list of possible modifiers you can pass.
Partial<Modifier<string, any>>[]
offset
offset
The main and cross-axis offset to displace popper element from its reference element.
[number, number]
onClose
onClose
() => void
onOpen
onOpen
() => void
placement
placement
The placement of the popper relative to its reference.
PlacementWithLogical
bottom
preventOverflow
preventOverflow
If true
, will prevent the popper from being cut off and ensure
it's visible within the boundary area.
boolean
true
strategy
strategy
The CSS positioning strategy to use.
"fixed" | "absolute"
absolute
MenuButton Props#
MenuButton
composes Box so you can pass all
Box
props to change its style.
MenuList Props#
MenuList
composes Box so you can pass all Box
props to change its style.
motionProps
motionProps
The framer-motion props to animate the menu list
HTMLMotionProps<"div">
rootProps
rootProps
Props for the root element that positions the menu.
HTMLChakraProps<"div">
MenuItem Props#
closeOnSelect
closeOnSelect
Overrides the parent menu's closeOnSelect
prop.
boolean
command
command
Right-aligned label text content, useful for displaying hotkeys.
string
commandSpacing
commandSpacing
The spacing between the command and menu item's label.
ResponsiveValue<string | number | (string & {})>
icon
icon
The icon to render before the menu item's label.
ReactElement<any, string | JSXElementConstructor<any>>
iconSpacing
iconSpacing
The spacing between the icon and menu item's label.
ResponsiveValue<string | number | (string & {})>
isDisabled
isDisabled
If true
, the menuitem will be disabled
boolean
isFocusable
isFocusable
If true
and the menuitem is disabled, it'll
remain keyboard-focusable
boolean
MenuGroup Props#
MenuGroup
composes Box so you can pass all
Box
props to change its style.
MenuOptionGroup Props#
defaultValue
defaultValue
string | string[]
onChange
onChange
(value: string | string[]) => void
type
type
"checkbox" | "radio"
value
value
string | string[]
MenuItemOption Props#
MenuItemOption
composes Box so you can pass all
box props in addition to these:
closeOnSelect
closeOnSelect
Overrides the parent menu's closeOnSelect
prop.
boolean
command
command
Right-aligned label text content, useful for displaying hotkeys.
string
commandSpacing
commandSpacing
The spacing between the command and menu item's label.
ResponsiveValue<string | number | (string & {})>
icon
icon
ReactElement<any, string | JSXElementConstructor<any>>
iconSpacing
iconSpacing
The spacing between the icon and menu item's label.
ResponsiveValue<string | number | (string & {})>
isChecked
isChecked
boolean
isDisabled
isDisabled
If true
, the menuitem will be disabled
boolean
isFocusable
isFocusable
If true
and the menuitem is disabled, it'll
remain keyboard-focusable
boolean
type
type
"checkbox" | "radio"
value
value
string
The Menu
component is a multipart component. The styling needs to be applied
to each part specifically.
To learn more about styling multipart components, visit the Component Style page.
Anatomy#
- A:
button
- B:
list
- C:
item
- D:
groupTitle
- E:
command
- F:
divider
Theming properties#
The properties that affect the theming of the Menu
component are:
variant
: The visual variant of the component. There is no default applied.size
: The size of the component. There is no default applied.
Theming utilities#
createMultiStyleConfigHelpers
: a function that returns a set of utilities for creating style configs for a multipart component (definePartsStyle
anddefineMultiStyleConfig
).definePartsStyle
: a function used to create multipart style objects.defineMultiStyleConfig
: a function used to define the style configuration for a multipart component.
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)
Customizing the default theme#
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)// define the base component stylesconst baseStyle = definePartsStyle({// define the part you're going to stylebutton: {// this will style the MenuButton componentfontWeight: 'medium',bg: 'teal.500',color: 'gray.200',_hover: {bg: 'teal.600',color: 'white',},},list: {// this will style the MenuList componentpy: '4',borderRadius: 'xl',border: 'none',bg: 'teal.500',},item: {// this will style the MenuItem and MenuItemOption componentscolor: 'gray.200',_hover: {bg: 'teal.600',},_focus: {bg: 'teal.600',},},groupTitle: {// this will style the text defined by the title prop// in the MenuGroup and MenuOptionGroup componentstextTransform: 'uppercase',color: 'white',textAlign: 'center',letterSpacing: 'wider',opacity: '0.7',},command: {// this will style the text defined by the command// prop in the MenuItem and MenuItemOption componentsopacity: '0.8',fontFamily: 'mono',fontSize: 'sm',letterSpacing: 'tighter',pl: '4',},divider: {// this will style the MenuDivider componentmy: '4',borderColor: 'white',borderBottom: '2px dotted',},})// export the base styles in the component themeexport const menuTheme = defineMultiStyleConfig({ baseStyle })
After customizing the input theme, we can import it into our theme file and add
it in the components
property:
import { extendTheme } from '@chakra-ui/react'import { menuTheme } from './components/Menu'const theme = extendTheme({components: {Menu: menuTheme,},})export default theme
This is a crucial step to make sure that any changes we make to the menu theme are applied.
Adding a custom size#
Let's assume we want to include an extra large menu size. Here's how we can do that:
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)// define custom stylesconst lg = defineStyle({fontSize: 'md',my: '1',})const xl = defineStyle({fontSize: 'lg',px: '4',py: '2',})// define custom sizesconst sizes = {// apply custom styles to partsxl: definePartsStyle({ button: xl, item: xl, groupTitle: lg, command: xl }),}// export the sizes in the component themeexport const menuTheme = defineMultiStyleConfig({ sizes })// now we can use the new `xl` size<Menu size="xl" ... />
Every time you add anything new to the theme, you need to run the CLI command to get proper autocomplete in your IDE. You can learn more about the CLI tool here.
Adding a custom variant#
Let's assume we want to include some custom variants to create a pill-shaped menu bar. Here's how we can do that:
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)// define custom variantsconst variants = {roundLeft: {button: {borderLeftRadius: 'full',pl: '6',},},roundRight: {button: {borderRightRadius: 'full',pr: '6',},},}// export the custom variants in the component themeexport const menuTheme = defineMultiStyleConfig({ variants })// now we can use the new `roundLeft` and `roundRight` variants<Menu variant="roundLeft" ... /><Menu variant="roundRight" ... />
Changing the default properties#
Let's assume we want to change the default size and variant of every menu in our app. Here's how we can do that:
import { menuAnatomy } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(menuAnatomy.keys)// define which sizes and variants are applied by defaultconst defaultProps = {// in this example, we will only set a default sizesize: 'xl',}// export the default properties in the component themeexport const menuTheme = defineMultiStyleConfig({ defaultProps })
Showcase#
import { ChakraProvider, Menu, MenuButton, MenuList, MenuItem, MenuItemOption, MenuGroup, MenuOptionGroup, MenuDivider, Box, Center, } from '@chakra-ui/react'; import theme from './theme'; import { ColorModeSwitcher } from './ColorModeSwitcher'; export default function App() { return ( <ChakraProvider theme={theme}> <Box position="relative" h="100vh" p={12}> <Center> <Menu variant="roundLeft"> <MenuButton>File</MenuButton> <MenuList> <MenuItem command="Ctrl + N">New File</MenuItem> <MenuItem command="Ctrl + O">Open File</MenuItem> <MenuDivider /> <MenuGroup title="Save"> <MenuItem command="Ctrl + S">Save</MenuItem> <MenuItem command="Ctrl + Shift + S">Save As...</MenuItem> <MenuItem command="Ctrl + Alt + S">Save All</MenuItem> </MenuGroup> <MenuDivider /> <MenuItem>Exit</MenuItem> </MenuList> </Menu> <Menu> <MenuButton>Edit</MenuButton> <MenuList> <MenuItem command="Ctrl + Z">Undo</MenuItem> <MenuItem command="Ctrl + Y">Redo</MenuItem> <MenuDivider /> <MenuGroup> <MenuItem command="Ctrl + X">Cut</MenuItem> <MenuItem command="Ctrl + C">Copy</MenuItem> <MenuItem command="Ctrl + V">Paste</MenuItem> </MenuGroup> </MenuList> </Menu> <Menu variant="roundRight"> <MenuButton>View</MenuButton> <MenuList> <MenuItem command="Ctrl + F">Full Screen Mode</MenuItem> <MenuItem command="Ctrl + R">Reading Mode</MenuItem> <MenuDivider /> <MenuGroup title="Zoom"> <MenuItem command="Ctrl + 1">Actual Size</MenuItem> <MenuItem command="Ctrl + 2">Fit Width</MenuItem> <MenuItem command="Ctrl + 3">Height</MenuItem> </MenuGroup> <MenuDivider /> <MenuOptionGroup title="Display Size" type="radio" defaultValue={'standard'} > <MenuItemOption value="small" closeOnSelect={false}> Small </MenuItemOption> <MenuItemOption value="standard" closeOnSelect={false}> Standard </MenuItemOption> <MenuItemOption value="large" closeOnSelect={false}> Large </MenuItemOption> </MenuOptionGroup> </MenuList> </Menu> </Center> <ColorModeSwitcher aria-label="toggle theme" position="absolute" bottom={4} left={4} /> </Box> </ChakraProvider> ); }