Components
Context Menu
An imperative right-click context menu with pointer anchoring, grouping and submenus — built on Menu and native popover, opened with a single call
Installation
- $npx litefy@latest add context-menu
- $pnpm dlx litefy@latest add context-menu
- $yarn dlx litefy@latest add context-menu
- $bun --bun litefy@latest add context-menu
Usage
Mount <ContextMenuHost /> once, then call ContextMenu.open() from any element's onContextMenu — no wrapper needed.
Right-click anywhere in this area
Selected: -
"use client";
import { useState, type ReactNode } from "react";
import { ContextMenu, ContextMenuHost, type MenuConfig } from "@/ui";
const items: MenuConfig[] = [
{
group: "Canvas",
items: [{ label: "Copy" }, { label: "Paste" }, { label: "Duplicate" }],
},
{
group: "View",
items: [{ label: "Zoom In" }, { label: "Zoom Out" }, { label: "Reset View" }],
},
];
export default function ContextMenuBasicDemo() {
const [selected, setSelected] = useState<ReactNode>(null);
return (
<div className="flex flex-col items-center gap-3">
<ContextMenuHost />
<div
className="flex size-64 max-w-md select-none items-center justify-center rounded-md border border-dashed text-sm text-muted-foreground"
onContextMenu={(e) => {
e.preventDefault();
ContextMenu.open({
x: e.clientX,
y: e.clientY,
items,
onSelect: (item) => setSelected(item.label),
});
}}
>
Right-click anywhere in this area
</div>
<p className="text-sm text-muted-foreground">Selected: {selected ?? "-"}</p>
</div>
);
}
Custom Styling
Restyle the panel via classNames.content / styles.content passed to open(); menu item capabilities come from the Menu component.
Right-click to open a custom-styled menu
Selected: -
"use client";
import { useState, type ReactNode } from "react";
import { ContextMenu, ContextMenuHost, type MenuConfig } from "@/ui";
const items: MenuConfig[] = [
{ label: "Duplicate" },
{ label: "Archive" },
{ group: "Danger", items: [{ label: "Delete" }] },
];
export default function ContextMenuCustomDemo() {
const [selected, setSelected] = useState<ReactNode>(null);
return (
<div className="flex flex-col items-center gap-3">
<ContextMenuHost />
<div
className="flex size-64 max-w-md select-none items-center justify-center rounded-md border border-dashed border-primary/50 bg-primary/5 text-sm text-muted-foreground"
onContextMenu={(e) => {
e.preventDefault();
ContextMenu.open({
x: e.clientX,
y: e.clientY,
items,
onSelect: (item) => setSelected(item.label),
classNames: { content: "w-56 border-primary/30" },
});
}}
>
Right-click to open a custom-styled menu
</div>
<p className="text-sm text-muted-foreground">Selected: {selected ?? "-"}</p>
</div>
);
}
API Reference
ContextMenuHost
Renders the floating menu panel while ContextMenu.open() is active; mount it once near the app root — it renders nothing until a menu is opened.
| Prop | Type | Default | Description |
|---|---|---|---|
className | ClassNameValue | - | Custom class on the anchor wrapper |
Statics
ContextMenu.open
ContextMenu.open(options: ContextMenuOpenOptions): voidOpens the menu at the given viewport coordinates.
| Option | Type | Default | Description |
|---|---|---|---|
x | number | - | Viewport x coordinate (usually e.clientX) Required |
y | number | - | Viewport y coordinate (usually e.clientY) Required |
items | MenuConfig[] | - | Menu items, flat or grouped — same shape as the Menu component Required |
onSelect | (item: MenuItemConfig) => void | - | Fired when a menu item is activated; the menu closes afterwards |
classNames | { content?: ClassNameValue } | - | Custom classes for the panel |
styles | { content?: React.CSSProperties } | - | Inline styles for the panel; anchor positioning props are managed internally |
ContextMenu.dismiss
ContextMenu.dismiss(): voidCloses the menu programmatically.