Skip to content

ContextMenu

Right-click (or touch long-press) context menu for contextual actions on a region.

<ContextMenu
items={[
{icon: Pencil, label: 'Rename'},
{icon: Copy, label: 'Duplicate'},
{type: 'divider'},
{icon: Trash, label: 'Delete'},
]}>
<div className={styles.target}>
<Text as="span" type="body">
Right-click this area
</Text>
</div>
</ContextMenu>
<ContextMenu
items={[
{icon: Pencil, label: 'Rename'},
{icon: Copy, label: 'Duplicate'},
{type: 'divider'},
{icon: Trash, label: 'Delete'},
]}>
<div className={styles.target}>
<Text as="span" type="body">
Long-press this area on a touch device (or right-click)
</Text>
</div>
</ContextMenu>
<ContextMenu
items={[
{
description: 'Change the file name',
icon: Pencil,
label: 'Rename',
},
{
description: 'Create an identical copy',
icon: Copy,
label: 'Duplicate',
},
{type: 'divider'},
{
description: 'Move to trash',
icon: Trash,
label: 'Delete',
},
]}>
<div className={styles.target}>
<Text as="span" type="body">
Right-click for actions with descriptions
</Text>
</div>
</ContextMenu>
<ContextMenu
menuContent={
<>
<ContextMenuItem
endContent={<Kbd keys="mod+r" />}
icon={Pencil}
label="Rename"
/>
<ContextMenuItem
endContent={<Kbd keys="mod+d" />}
icon={Copy}
label="Duplicate"
/>
<Divider />
<ContextMenuItem
endContent={<Kbd keys="backspace" />}
icon={Trash}
label="Delete"
/>
</>
}>
<div className={styles.target}>
<Text as="span" type="body">
Right-click for actions with shortcuts
</Text>
</div>
</ContextMenu>
<ContextMenu
items={[
{icon: Pencil, label: 'Rename'},
{icon: Copy, isDisabled: true, label: 'Duplicate'},
{type: 'divider'},
{icon: Trash, isDisabled: true, label: 'Delete'},
]}>
<div className={styles.target}>
<Text as="span" type="body">
Right-click — some actions disabled
</Text>
</div>
</ContextMenu>
<ContextMenu
isDisabled
items={[
{icon: Pencil, label: 'Rename'},
{icon: Copy, label: 'Duplicate'},
]}>
<div className={styles.target}>
<Text as="span" type="body">
Right-click falls through to browser menu
</Text>
</div>
</ContextMenu>
(): React.JSX.Element => {
const items = [
{icon: Pencil, label: 'Rename'},
{icon: Copy, label: 'Duplicate'},
{type: 'divider' as const},
{icon: Trash, label: 'Delete'},
];
return (
<div style={{display: 'flex', gap: '2rem'}}>
<ContextMenu items={items} size="sm">
<div className={styles.target}>
<Text as="span" type="body">
Small
</Text>
</div>
</ContextMenu>
<ContextMenu items={items} size="md">
<div className={styles.target}>
<Text as="span" type="body">
Medium
</Text>
</div>
</ContextMenu>
<ContextMenu items={items} size="lg">
<div className={styles.target}>
<Text as="span" type="body">
Large
</Text>
</div>
</ContextMenu>
</div>
);
}
<ContextMenu
items={[
{
items: [
{icon: Pencil, label: 'Rename'},
{icon: Copy, label: 'Duplicate'},
],
title: 'Edit',
type: 'section',
},
{
items: [{icon: Download, label: 'Export'}],
title: 'Share',
type: 'section',
},
]}>
<div className={styles.target}>
<Text as="span" type="body">
Right-click for grouped actions
</Text>
</div>
</ContextMenu>
Scroll to the bottom-right target and right-click it. Scrolling this region again dismisses the menu. If left open, the menu grows after a moment so its edge flipping can be checked at narrow canvas sizes.
Scroll down and right
function PositioningAndScrollExample(): React.JSX.Element {
const [isOpen, setIsOpen] = useState(false);
return (
<div className={styles.positioningExample}>
<Text color="secondary" type="supporting">
Scroll to the bottom-right target and right-click it. Scrolling this
region again dismisses the menu. If left open, the menu grows after a
moment so its edge flipping can be checked at narrow canvas sizes.
</Text>
<div className={styles.scrollRegion}>
<div className={styles.scrollContent}>
<Text color="secondary" type="supporting">
Scroll down and right
</Text>
<div className={styles.edgeTarget}>
<ContextMenu
menuContent={
isOpen ? (
<GrowingMenuContent />
) : (
<ContextMenuItem icon={Pencil} label="Rename" />
)
}
onOpenChange={setIsOpen}>
<div className={styles.target}>
<Text as="span" type="body">
Right-click near the edge
</Text>
</div>
</ContextMenu>
</div>
</div>
</div>
</div>
);
}
function GrowingMenuContent(): React.JSX.Element {
const [hasGrown, setHasGrown] = useState(false);
useEffect(() => {
const timeout = setTimeout(() => setHasGrown(true), 800);
return () => clearTimeout(timeout);
}, []);
return (
<>
<ContextMenuItem icon={Pencil} label="Rename" />
<ContextMenuItem icon={Copy} label="Duplicate" />
{hasGrown ? (
<>
<Divider />
<ContextMenuItem label="Move to project" />
<ContextMenuItem label="Share link" />
<ContextMenuItem icon={Download} label="Export archive" />
<ContextMenuItem icon={Trash} label="Delete" />
</>
) : null}
</>
);
}
<PositioningAndScrollExample />
<ContextMenu
items={[
{icon: Pencil, label: 'Edit'},
{icon: Copy, label: 'Duplicate'},
{type: 'divider'},
{icon: Trash, label: 'Delete'},
]}>
<Card style={{width: 360}}>
<LayoutHeader
endContent={<Badge color="blue" label="Active" />}
title="Project Alpha"
/>
<LayoutContent>
<Text color="secondary" type="supporting">
3 members · Last updated 2 hours ago. Right-click for options.
</Text>
</LayoutContent>
</Card>
</ContextMenu>

Right-click (or touch long-press) context menu for contextual actions on a region.

When Variant 1

PropTypeDefaultDescription
items*ReadonlyArray<ContextMenuOption>
menuContentnever
children*ReactNodeThe region that triggers the context menu on right-click or touch long-press.
classNamestringAdditional CSS class names applied to the menu surface.
data-testidstringTest ID applied to the trigger wrapper.
hasAutoFocusbooleantrueWhether to auto-focus the first menu item on open.
isDisabledbooleanfalseWhether the context menu is disabled.
menuWidthnumber | string160Width of the menu surface.
onOpenChange(isOpen: boolean) => voidCalled when the menu open state changes.
refRef<HTMLDivElement>Ref forwarded to the trigger wrapper.
size"sm" | "md" | "lg"'md'Menu item size.
styleCSSPropertiesInline styles applied to the menu surface.

When Variant 2

PropTypeDefaultDescription
itemsnever
menuContent*ReactNode
children*ReactNodeThe region that triggers the context menu on right-click or touch long-press.
classNamestringAdditional CSS class names applied to the menu surface.
data-testidstringTest ID applied to the trigger wrapper.
hasAutoFocusbooleantrueWhether to auto-focus the first menu item on open.
isDisabledbooleanfalseWhether the context menu is disabled.
menuWidthnumber | string160Width of the menu surface.
onOpenChange(isOpen: boolean) => voidCalled when the menu open state changes.
refRef<HTMLDivElement>Ref forwarded to the trigger wrapper.
size"sm" | "md" | "lg"'md'Menu item size.
styleCSSPropertiesInline styles applied to the menu surface.
PropTypeDefaultDescription
aria-keyshortcutsAriaAttributes['aria-keyshortcuts']Keyboard shortcuts that activate the menu item.
classNamestringAdditional CSS class names applied to the item.
data-testidstringTest ID applied to the item.
descriptionReactNodeSupporting text shown below the label.
endContentReactNodeTrailing content.
iconIconComponentIcon rendered before the label.
isDisabledbooleanfalseWhether the item is disabled.
label*stringItem label.
onClick() => voidCalled when the item is selected.
refRef<HTMLButtonElement>Ref forwarded to the item button.
styleCSSPropertiesInline styles applied to the item.
tooltipReactNodeTooltip content shown when the item is hovered or focused.