Context Menu
A menu of actions that opens at the pointer on right click or long press.
Basic
Right-click here
Show codeHide code
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "@makeplane/propel/components/context-menu";
import { Icon } from "@makeplane/propel/components/icon";
import { Shortcut } from "@makeplane/propel/components/shortcut";
import { ClipboardPaste, Copy, Scissors, Trash2 } from "lucide-react";
export default function BasicDemo() {
return (
<ContextMenu>
<ContextMenuTrigger render={<div />}>Right-click here</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem
tone="neutral"
icon={<Icon icon={Scissors} />}
aria-keyshortcuts="Meta+X"
endContent={<Shortcut keys="⌘X" />}
label="Cut"
/>
<ContextMenuItem
tone="neutral"
icon={<Icon icon={Copy} />}
aria-keyshortcuts="Meta+C"
endContent={<Shortcut keys="⌘C" />}
label="Copy"
/>
<ContextMenuItem
tone="neutral"
icon={<Icon icon={ClipboardPaste} />}
aria-keyshortcuts="Meta+V"
endContent={<Shortcut keys="⌘V" />}
label="Paste"
/>
<ContextMenuSeparator />
<ContextMenuItem tone="danger" icon={<Icon icon={Trash2} />} label="Delete" />
</ContextMenuContent>
</ContextMenu>
);
}Submenu
Nest a ContextMenuSubmenu to reveal more destinations beside the parent menu.
Right-click here
Show codeHide code
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuSubmenu,
ContextMenuSubmenuTrigger,
ContextMenuTrigger,
} from "@makeplane/propel/components/context-menu";
import { Icon } from "@makeplane/propel/components/icon";
import { Copy, FolderInput, PencilLine, Trash2 } from "lucide-react";
export default function SubmenuDemo() {
return (
<ContextMenu>
<ContextMenuTrigger render={<div />}>Right-click here</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem tone="neutral" icon={<Icon icon={PencilLine} />} label="Rename" />
<ContextMenuItem tone="neutral" icon={<Icon icon={Copy} />} label="Duplicate" />
<ContextMenuSubmenu>
<ContextMenuSubmenuTrigger
tone="neutral"
icon={<Icon icon={FolderInput} />}
label="Move to"
/>
<ContextMenuContent>
<ContextMenuItem tone="neutral" label="Mobile app" />
<ContextMenuItem tone="neutral" label="Web app" />
<ContextMenuItem tone="neutral" label="Design system" />
</ContextMenuContent>
</ContextMenuSubmenu>
<ContextMenuSeparator />
<ContextMenuItem tone="danger" icon={<Icon icon={Trash2} />} label="Delete" />
</ContextMenuContent>
</ContextMenu>
);
}Link items
ContextMenuLinkItem renders a real anchor, so a row can navigate while keeping menu-item behavior.
Right-click here
Show codeHide code
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuLinkItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "@makeplane/propel/components/context-menu";
import { Icon } from "@makeplane/propel/components/icon";
import { Shortcut } from "@makeplane/propel/components/shortcut";
import { Copy, ExternalLink, Link2 } from "lucide-react";
export default function LinkItemsDemo() {
return (
<ContextMenu>
<ContextMenuTrigger render={<div />}>Right-click here</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuLinkItem
tone="neutral"
icon={<Icon icon={ExternalLink} />}
href="#work-item"
target="_blank"
rel="noopener noreferrer"
label="Open in new tab"
/>
<ContextMenuLinkItem
tone="neutral"
icon={<Icon icon={Link2} />}
href="#activity"
label="Go to activity"
/>
<ContextMenuSeparator />
<ContextMenuItem
tone="neutral"
icon={<Icon icon={Copy} />}
aria-keyshortcuts="Meta+C"
endContent={<Shortcut keys="⌘C" />}
label="Copy link"
/>
</ContextMenuContent>
</ContextMenu>
);
}Selection rows
Right-click for view options
Show codeHide code
import {
ContextMenu,
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "@makeplane/propel/components/context-menu";
import * as React from "react";
export default function SelectionRowsDemo() {
const [wrap, setWrap] = React.useState(true);
const [sort, setSort] = React.useState("manual");
return (
<ContextMenu>
<ContextMenuTrigger render={<div />}>Right-click for view options</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuCheckboxItem
tone="neutral"
checked={wrap}
onCheckedChange={setWrap}
closeOnClick={false}
label="Wrap titles"
/>
<ContextMenuSeparator />
<ContextMenuRadioGroup value={sort} onValueChange={setSort}>
<ContextMenuRadioItem
tone="neutral"
value="manual"
closeOnClick={false}
label="Manual order"
/>
<ContextMenuRadioItem
tone="neutral"
value="updated"
closeOnClick={false}
label="Last updated"
/>
</ContextMenuRadioGroup>
</ContextMenuContent>
</ContextMenu>
);
}Installation
import {
ContextMenu,
ContextMenuTrigger,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
} from "@makeplane/propel/components/context-menu";
Props
ContextMenu
| Prop | Type | Required | Description |
|---|---|---|---|
| children | ReactNode | PayloadChildRenderFunction<unknown> | No | The content of the popover. This can be a regular React node or a render function that receives the `payload` of the active trigger. |
ContextMenuItem
| Prop | Type | Required | Description |
|---|---|---|---|
| tone | "neutral" | "danger" | Yes | Neutral rows use the standard text hierarchy; `danger` rows use the error palette. |
| icon | ReactNode | No | Leading element before the label, e.g. `<Icon icon={Copy} />`. |
| label | string | Yes | Primary row label. |
| endContent | ReactElement<unknown, string | JSXElementConstructor<any>> | No | Element rendered at the inline end of the row, e.g. `<Shortcut keys="⌘ K" />`. |
| selected | boolean | No | Single-select selected state. |