Accessible, unstyled ContextMenu: opens a menu at the pointer on contextmenu, at the focused element on Shift+F10 or the ContextMenu key, and at the touch point after a long press. Items and submenus are the shared Menu parts re-exported under ContextMenu names.
|
|
| Package |
@vizejs/ui/context-menu |
| Maturity |
stable |
| Own the source |
vize lib pull context-menu |
| Requires |
long-press, menu, press, collection, context, controllable-state, dismissable-layer, focus-scope, id, inert-outside, pointer-grace, portal, positioner, presence, scroll-lock, typeahead |
| Aliases |
right-click menu, contextual menu, long-press menu, shortcut menu |
| Covers |
WAI-ARIA menu pattern, Radix Context Menu, Reka UI Context Menu |
Usage
import { ContextMenu, ContextMenuRoot, ContextMenuTrigger } from "@vizejs/ui/context-menu";
Or copy the source into your project with vize lib pull context-menu (see Source Distribution).
API
Source: src/families/menus/context-menu/context-menu-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned base id. null and undefined select a deterministic fallback. |
open |
boolean |
undefined |
Controlled open state. undefined selects uncontrolled behavior. |
defaultOpen |
boolean |
false |
Initial open state for uncontrolled use; the menu anchors at the viewport origin until a context-menu request supplies a point. |
modal |
boolean |
true |
Make outside content inert and lock document scroll while open. |
dir |
MenuDirection |
undefined |
Reading direction: flips submenu arrow keys and submenu placement. undefined inherits DirectionProvider/LocaleProvider, then "ltr". |
loop |
boolean |
false |
Wrap arrow-key navigation from the last item to the first and back. |
disabled |
boolean |
false |
Ignore context-menu requests so the native browser menu shows instead. |
Events
| Event |
Payload |
Description |
update:open |
[value: boolean] |
Fired with the requested open value (supports v-model:open). |
open-change |
[value: boolean, previous: boolean, nativeEvent: Event | null] |
Fired after any distinct open-state request with the previous value and native event. |
Slots
| Slot |
Slot props |
Description |
default |
MenuSlotState |
ContextMenuTrigger and menu content. Receives the menu open state. |
Source: src/families/menus/context-menu/context-menu-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned base id. null and undefined select a deterministic fallback. |
open |
boolean |
undefined |
Controlled open state. undefined selects uncontrolled behavior. |
defaultOpen |
boolean |
false |
Initial open state for uncontrolled use; the menu anchors at the viewport origin until a context-menu request supplies a point. |
modal |
boolean |
true |
Make outside content inert and lock document scroll while open. |
dir |
MenuDirection |
undefined |
Reading direction: flips submenu arrow keys and submenu placement. undefined inherits DirectionProvider/LocaleProvider, then "ltr". |
loop |
boolean |
false |
Wrap arrow-key navigation from the last item to the first and back. |
disabled |
boolean |
false |
Ignore context-menu requests so the native browser menu shows instead. |
Events
| Event |
Payload |
Description |
update:open |
[value: boolean] |
Fired with the requested open value (supports v-model:open). |
open-change |
[value: boolean, previous: boolean, nativeEvent: Event | null] |
Fired after any distinct open-state request with the previous value and native event. |
Slots
| Slot |
Slot props |
Description |
default |
MenuSlotState |
ContextMenuTrigger and menu content. Receives the menu open state. |
Exposed
| Member |
Type |
Description |
open |
boolean |
Whether the menu content is visible and interactive. |
state |
MenuState |
Stable state token for styling and tests. |
modal |
boolean |
Whether outside content is inert and scroll-locked while open. |
dir |
MenuDirection |
Resolved reading direction. |
id |
string |
Root-owned base id. |
triggerId |
string |
Id wired to the trigger. |
contentId |
string |
Id wired to the content. |
setOpen |
(value: boolean, event?: Event | null) => boolean |
Request an open value; returns whether it changed. |
openMenu |
(entry?: MenuEntryFocus, event?: Event | null) => boolean |
Open the menu and move focus to entry once content mounts. |
close |
(event?: Event | null) => boolean |
Close the whole menu tree. |
toggle |
(event?: Event | null) => boolean |
Toggle the menu. |
openAt |
(point: ContextMenuPoint, event?: Event | null) => boolean |
Open the menu anchored at a viewport point, as a context-menu request would. |
Source: src/families/menus/context-menu/context-menu-trigger.vue
Props
| Prop |
Type |
Default |
Description |
disabled |
boolean |
false |
Let the native browser context menu show for this region. |
longPressDelay |
number |
700 |
Milliseconds a touch must stay down before the menu opens at the touch point. |
Events
| Event |
Payload |
Description |
contextmenu |
[nativeEvent: MouseEvent] |
Fired before a contextmenu request opens the menu; call preventDefault() to skip it. |
Slots
| Slot |
Slot props |
Description |
default |
ContextMenuTriggerSlotState |
Region contents. Receives the menu open state and trigger availability. |
Exposed
| Member |
Type |
Description |
element |
HTMLSpanElement | null |
Rendered trigger region. |
Behavior
@vizejs/ui/context-menu opens the shared menu core (see ../menu/menu.behavior.md) anchored
at a viewport point. context-menu-root.vue owns a virtual anchor and restores focus to
whatever held it before the request; context-menu-trigger.vue is a non-interactive region that
translates contextmenu, Shift+F10, the ContextMenu key, and touch long-press into requests.
Every row is proven by the named test in context-menu.test.ts or context-menu-ssr.test.ts.
| # |
State |
Input |
Outcome |
Proven by |
| C1 |
closed |
contextmenu (right click) |
prevents the native menu, anchors at the pointer, opens data-menu-kind="context-menu" content, focuses the menu |
contextmenu opens at the pointer, prevents the native menu, and focuses the menu |
| C2 |
open |
new request elsewhere |
the outside press closes, the request reopens the same content at the new anchor |
a new request while open re-anchors the same open menu |
| C3 |
closed, focus |
Shift+F10 / ContextMenu key |
anchors at the focused element, focuses the first item; Escape returns focus to the requesting element |
Shift+F10 and the ContextMenu key open at the focused element with the first item focused |
| C4 |
closed |
plain F10 / other keys |
nothing opens |
plain F10 and other keys do not open the menu |
| C5 |
closed, touch |
press held for longPressDelay |
opens at the touch point; shorter taps do nothing |
a touch long press opens at the touch point; short taps do not |
| C6 |
closed, mouse |
press held |
mouse presses never use the long-press path |
mouse presses never trigger the long-press path |
| C7 |
disabled |
contextmenu |
trigger or root disabled lets the native menu show and publishes data-disabled |
disabled triggers and roots let the native menu show |
| C8 |
enabled |
prevented contextmenu emit |
the native menu is kept and nothing opens |
a prevented contextmenu emit keeps the native menu |
| C9 |
open |
select / outside pointer-down |
selection closes; outside pointer-down closes |
selecting closes; outside pointer-down closes without restoring focus |
| C10 |
any |
openAt(point) expose |
opens programmatically with the first item focused |
exposes openAt for programmatic requests |
| C11 |
SSR |
two requests + hydrate |
byte-identical markup, no long-press description leakage, warning-free hydration |
renders identical context-menu markup across SSR requests and hydrates cleanly |