Context menu
A context menu opens at the pointer on right-click — and from the keyboard via
the ContextMenu key or Shift+F10 on the focused region. The panel reuses the
Menu markup (.re-menu__panel /
.re-menu__item); only the positioning differs (fixed, at the pointer, above
modals). With no JS the native browser context menu is the fallback —
enhanceContextMenu only preventDefaults the event once it’s wired.
import { enhanceContextMenu } from "@relements/core/behaviors/context-menu";enhanceContextMenu(document);Mark the trigger region with data-re-context-menu="<panel-id>" and make it
focusable (tabindex="0") so keyboard invocation works.
Right-click (or focus + press the Menu key / Shift+F10) anywhere in this region.
<div class="re-context-region" data-re-context-menu="ctx-1" tabindex="0">
Right-click (or focus + press the Menu key / Shift+F10) anywhere in this region.
</div>
<div
id="ctx-1"
class="re-menu__panel re-context-menu__panel"
role="menu"
aria-label="Row actions"
hidden
>
<button class="re-menu__item" role="menuitem" type="button" data-value="open">Open</button>
<button class="re-menu__item" role="menuitem" type="button" data-value="rename">
Rename
</button>
<button class="re-menu__item" role="menuitem" type="button" data-value="duplicate">
Duplicate
</button>
<div class="re-menu__separator" role="separator"></div>
<button class="re-menu__item" role="menuitem" type="button" data-value="delete">
Delete
</button>
</div> - Dispatches
re-select(bubbles, cancelable;detail = { item, value, originalEvent }) on the region —preventDefault()keeps the menu open. - The panel is
position: fixedatz-index: var(--re-z-dialog), so a context menu opened inside a modal sits above it. - The Popover API (top layer) is used as a bonus on browsers that support it; the fixed-position path is canonical (and what runs on the support floor).
Accessibility
Section titled “Accessibility”- Keyboard — open the menu with right-click, the ContextMenu key, or
Shift+F10 while the region is focused; opening moves focus to the first
item. Within the menu: Arrow Up / Arrow Down move between items and wrap,
Home / End jump to first / last, and first-character typeahead focuses
the next matching item. Escape and Tab both close the menu and return
focus to the region; Enter / Space activate the focused
<button>. - Focus — items are native buttons with a 2px inset
:focus-visiblering (the panel isposition: fixed, so an inset ring stays visible against the panel edge); the region itself shows a focus ring when tabbed to. Closing via Escape, Tab, or selection returns focus to the region so native Tab order resumes from a defined point. - Semantics — the panel is
role="menu"with anaria-label; each item isrole="menuitem", and the divider isrole="separator". OnceenhanceContextMenuwires a region it gainsaria-haspopup="menu"andaria-controlspointing at the panel, so assistive tech announces that a menu is available. - Notes — with no JS the custom menu never opens and the native browser
context menu is the fallback; the behavior only
preventDefaults thecontextmenuevent once it’s wired. See the accessibility guide and the shared Menu markup it reuses.