Context Menu

ui-context-menu replaces the browser's context menu inside ui-context-menu-trigger. A right-click (or the context menu key) on the trigger opens ui-context-menu-content, a popover="auto" menu, at the pointer position and focuses the first enabled item. The items are the same ui-menu-* parts used by Dropdown Menu. The arrow keys move between them, Enter or Space chooses one, and choosing fires select and closes the menu. Escape and a click outside close it too.

Previewindex.html
Right click here
Back ⌘[ Forward ⌘] Reload ⌘R Show Bookmarks People Pedro Duarte Colm Tuite
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Context Menu demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-area {
      display: grid;
      place-content: center;
      box-sizing: border-box;
      width: min(100%, calc(var(--spacing) * 72));
      height: calc(var(--spacing) * 36);
      border: 1px dashed var(--border);
      border-radius: var(--radius-md);
      font-size: var(--text-sm);
      color: var(--muted-foreground);
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/context-menu.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/dropdown-menu.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/toaster.html"></import-element>
  <ui-toaster></ui-toaster>

  <ui-context-menu onselect="document.dispatchEvent(new CustomEvent('toast', { detail: { title: 'Chose ' + event.detail.value } }))">
    <ui-context-menu-trigger><div class="demo-area">Right click here</div></ui-context-menu-trigger>
    <ui-context-menu-content>
      <ui-menu-item value="back">Back <ui-menu-shortcut>⌘[</ui-menu-shortcut></ui-menu-item>
      <ui-menu-item value="forward" disabled>Forward <ui-menu-shortcut>⌘]</ui-menu-shortcut></ui-menu-item>
      <ui-menu-item value="reload">Reload <ui-menu-shortcut>⌘R</ui-menu-shortcut></ui-menu-item>
      <ui-menu-separator></ui-menu-separator>
      <ui-menu-checkbox-item value="bookmarks" checked>Show Bookmarks</ui-menu-checkbox-item>
      <ui-menu-separator></ui-menu-separator>
      <ui-menu-label>People</ui-menu-label>
      <ui-menu-radio-group value="pedro">
        <ui-menu-radio-item value="pedro">Pedro Duarte</ui-menu-radio-item>
        <ui-menu-radio-item value="colm">Colm Tuite</ui-menu-radio-item>
      </ui-menu-radio-group>
    </ui-context-menu-content>
  </ui-context-menu>
</body>
</html>

Examples

Handle the selection

select bubbles from the chosen item, and event.detail.value is its value.

Previewindex.htmlcontext-menu-file-demo.html
Open Rename Delete
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Context Menu demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/context-menu.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/dropdown-menu.html"></import-element>

  <import-element from="./context-menu-file-demo.html"></import-element>
  <context-menu-file-demo></context-menu-file-demo>
</body>
</html>
<custom-element name="context-menu-file-demo">
  <script>
    const file = useState({ name: "report.pdf", log: "Right click the file." });

    const ACTIONS = {
      open: (name) => `Opened ${name}.`,
      rename: (name) => `Renaming ${name}.`,
      delete: (name) => `Deleted ${name}.`,
    };

    function act(event) {
      file.log = ACTIONS[event.detail.value](file.name);
    }
  </script>

  <style>
    :host {
      display: grid;
      justify-items: center;
      gap: calc(var(--spacing) * 3);
      font-size: var(--text-sm);
    }
    .file {
      display: flex;
      align-items: center;
      gap: calc(var(--spacing) * 2);
      padding: calc(var(--spacing) * 3) calc(var(--spacing) * 4);
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
    }
    svg {
      width: calc(var(--spacing) * 4);
      height: calc(var(--spacing) * 4);
    }
    output {
      color: var(--muted-foreground);
    }
  </style>

  <ui-context-menu onselect="act(event)">
    <ui-context-menu-trigger>
      <div class="file">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M14 3H6v18h12V7Z" /><path d="M14 3v4h4" /></svg>
        <slot name="#file.name"></slot>
      </div>
    </ui-context-menu-trigger>
    <ui-context-menu-content>
      <ui-menu-item value="open">Open</ui-menu-item>
      <ui-menu-item value="rename">Rename</ui-menu-item>
      <ui-menu-separator></ui-menu-separator>
      <ui-menu-item value="delete" variant="destructive">Delete</ui-menu-item>
    </ui-context-menu-content>
  </ui-context-menu>
  <output><slot name="#file.log"></slot></output>
</custom-element>

API

Parts

Part Slot Renders
ui-context-menu Its parts, with no box of its own.
ui-context-menu-trigger (default) A block around the area. A contextmenu event inside it opens the menu at the pointer.
ui-context-menu-content (default) A bordered popover="auto" panel with role="menu", positioned at the pointer with position: fixed.
ui-menu-* (default) Items, labels, groups, separators and shortcuts. See Dropdown Menu.

None of the parts has attributes of its own. See Dropdown Menu for the item attributes (value, disabled, variant, checked).

Events

Event Element Detail Description
select ui-menu-item, ui-menu-radio-item { value } Fired when an enabled item is chosen. Bubbles to ui-context-menu. The menu closes afterwards.
select ui-menu-checkbox-item { value, checked } Same, with the new checked state.

CSS parts

Element Part Description
ui-context-menu-trigger trigger The wrapper that listens for contextmenu.
ui-context-menu-content menu The focusgroup wrapper around the items.

Accessibility

Edit this page on GitHub · View as Markdown