RadCN
Overlaysreadycomponentready

Context Menu

A dependency-free contextual menu primitive for right-click and keyboard-triggered action lists with submenus and checked state.

Importimport { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from 'radcn/context-menu'
Preview

Live package example

Render the upstream browser-tools context menu with exact trigger, shortcuts, submenu, checked rows, radio items, and destructive item.

Context Menu Demo

Render the upstream browser-tools context menu with exact trigger, shortcuts, submenu, checked rows, radio items, and destructive item.

Preview
Right click here

React client components and Radix Context Menu map to RadCN dependency-free menu-overlay behavior: right-click and keyboard activation enhance public data hooks while this docs preview keeps content visible for inspection.

import {
  ContextMenu,
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuPortal,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuSeparator,
  ContextMenuShortcut,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from 'radcn/context-menu'

export function ContextMenuDemo() {
  return (
    <ContextMenu>
      <ContextMenuTrigger class="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
        Right click here
      </ContextMenuTrigger>
      <ContextMenuPortal>
        <ContextMenuContent class="w-52" style="width:13rem;min-width:13rem">
          <ContextMenuItem inset textValue="Back">
            Back
            <ContextMenuShortcut>⌘[</ContextMenuShortcut>
          </ContextMenuItem>
          <ContextMenuItem disabled inset textValue="Forward">
            Forward
            <ContextMenuShortcut>⌘]</ContextMenuShortcut>
          </ContextMenuItem>
          <ContextMenuItem inset textValue="Reload">
            Reload
            <ContextMenuShortcut>⌘R</ContextMenuShortcut>
          </ContextMenuItem>
          <ContextMenuSub>
            <ContextMenuSubTrigger inset textValue="More Tools">More Tools</ContextMenuSubTrigger>
            <ContextMenuSubContent class="w-44" style="width:11rem;min-width:11rem">
              <ContextMenuItem textValue="Save Page">Save Page...</ContextMenuItem>
              <ContextMenuItem textValue="Create Shortcut">Create Shortcut...</ContextMenuItem>
              <ContextMenuItem textValue="Name Window">Name Window...</ContextMenuItem>
              <ContextMenuSeparator />
              <ContextMenuItem textValue="Developer Tools">Developer Tools</ContextMenuItem>
              <ContextMenuSeparator />
              <ContextMenuItem textValue="Delete" variant="destructive">Delete</ContextMenuItem>
            </ContextMenuSubContent>
          </ContextMenuSub>
          <ContextMenuSeparator />
          <ContextMenuCheckboxItem checked textValue="Show Bookmarks">Show Bookmarks</ContextMenuCheckboxItem>
          <ContextMenuCheckboxItem textValue="Show Full URLs">Show Full URLs</ContextMenuCheckboxItem>
          <ContextMenuSeparator />
          <ContextMenuRadioGroup value="pedro">
            <ContextMenuLabel inset>People</ContextMenuLabel>
            <ContextMenuRadioItem value="pedro" textValue="Pedro Duarte">Pedro Duarte</ContextMenuRadioItem>
            <ContextMenuRadioItem value="colm" textValue="Colm Tuite">Colm Tuite</ContextMenuRadioItem>
          </ContextMenuRadioGroup>
        </ContextMenuContent>
      </ContextMenuPortal>
    </ContextMenu>
  )
}

Installation

Intended future install command. RadCN is private and not published to npm yet, so this snippet documents the target user-facing API rather than something external consumers can run today.

pnpm add radcn # intended future package
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from 'radcn/context-menu'

Theming

RadCN tokens read the resolved theme from the document. Store the user's preference separately, then resolve system preferences to a concrete light or dark theme before setting package tokens.

<html data-radcn-theme-mode="system" data-radcn-theme="dark">
  ...
</html>

Accessibility

  • ContextMenuTrigger is focusable and enhanced for right-click, ContextMenu key, and Shift+F10 activation.
  • ContextMenuContent renders menu semantics while items expose menuitem, menuitemcheckbox, and menuitemradio roles.
  • Disabled Forward exposes aria-disabled and data-disabled and must not highlight or close the menu when activated.
  • Checkbox and radio rows expose aria-checked and package-owned indicator hooks while the visible text remains ordinary menu text.

Customization

  • Trigger sizing maps from h-[150px] w-[300px] flex centering, rounded, dashed border, and text-sm utilities to class/style on ContextMenuTrigger.
  • Content widths map from w-52 and w-44 to class/style or --radcn-menu-width on ContextMenuContent and ContextMenuSubContent.
  • Item inset maps to inset props and radcn-menu-item--inset / radcn-menu-label--inset package classes.
  • Shortcuts, separators, checked indicators, radio indicators, submenu caret, destructive item styling, and highlight state expose public RadCN hooks and classes.
  • Custom tokens remain available through menu CSS variables such as --radcn-menu-width, --radcn-menu-border, --radcn-menu-bg, --radcn-menu-highlight-bg, and --radcn-menu-indicator-fg.

Remix 3 Notes

  • React client component markers and Radix Context Menu primitives map to dependency-free RadCN menu-overlay enhancement.
  • Radix Portal, Content, Sub, CheckboxItem, RadioGroup, and RadioItem mechanics map to explicit RadCN portal/content/sub/checkbox/radio parts and public data hooks.
  • data-slot maps to data-radcn-context-menu* and shared data-radcn-menu-* hooks.
  • className maps to class, and cn maps to explicit class composition, style, CSS variables, and app CSS.
  • Tailwind sizing, layout, border, typography, animation, focus, and inset utilities map to RadCN classes, inline styles, package CSS, data-state hooks, and tokens.
  • lucide CheckIcon, ChevronRightIcon, and CircleIcon map to package-owned indicator/caret glyphs or app-owned presentation, not lucide-react dependencies.
  • Vendor source remains read-only evidence and is not imported by RadCN.