ObjectUIObjectUI
ComponentsOverlay

Context Menu

Display a menu on right-click or long-press

The Context Menu component displays a menu when right-clicking on an element.

Basic Usage

Basic Context Menu

Right-click here

Icons

An item's icon is a kebab-case Lucide icon name, resolved against lucide's runtime icons record — the same surface ui:button, ui:dropdown-menu and the action:* family resolve against. It is read on both arms: a leaf item and a submenu trigger. A name that is not a live key of that record (an unknown or a retired spelling such as edit) renders no glyph, never a fallback glyph and never the literal name as text.

Dividers

An item is either a command or a divider between groups of commands — never both, and a divider never carries a label (objectui#6523). Author a divider as { "separator": true }; the retired { "type": "separator" } spelling is refused at parse time rather than silently ignored.

Schema

import type { SchemaNode } from '@object-ui/types';

interface ContextMenuCommandItem {
  label: string;
  icon?: string;                  // kebab-case Lucide icon name (e.g. "trash")
  shortcut?: string;              // e.g. "Ctrl+C" — a single string, not an array
  disabled?: boolean;
  // RUNTIME SLOT (objectui#6124): a React host supplies it; JSON refuses it
  // by name. Author behaviour as a node type, e.g. an action:button node.
  onClick?: () => void;           // Click handler
  children?: ContextMenuItem[];   // Submenu items — drawn as a nested submenu
}

interface ContextMenuDividerItem {
  separator: true;                // renders as a divider — no label
}

type ContextMenuItem = ContextMenuCommandItem | ContextMenuDividerItem;

interface ContextMenuSchema {
  type: 'context-menu';
  trigger?: SchemaNode | SchemaNode[];  // Trigger element — a placeholder renders when absent
  items: ContextMenuItem[];             // Menu items
  triggerClassName?: string;            // Classes for the right-clickable area
  contentClassName?: string;            // Classes for the menu panel
  modal?: boolean;                      // Forwarded to the Radix root
  className?: string;
}

The item's onClick is a runtime slot a React host supplies through the TypeScript MenuItem interface; it has no JSON spelling, and the validator refuses it by name on the item. The menu schema itself declares no authorable event slot either, so there is no menu-level onSelect.

On this page