The default is anchorMode="pointer", so the menu follows the mouse coordinates. Use anchorMode="reference" when the menu should behave more like a Popover/Dropdown and attach to the trigger area.
<!-- Follow mouse / provided coordinates. Good for standard context menus. -->
<TxContextMenu anchor-mode="pointer" />
<!-- Follow the trigger area. Good for dropdown-like menus. -->
<TxContextMenu anchor-mode="reference" />
TxContextMenuSubmenu nests another panel inside the menu, at any depth. Hovering the trigger row expands it; pointer travel between the parent and child panels never closes the chain by mistake, nor does a diagonal path across sibling rows expand them, and selecting an item inside the child closes the whole chain following the root menu's closeOnSelect.
- Use
TxContextMenu when you need trigger handling, coordinates, viewport collision handling, and open state in one component. - Use
TxContextMenuPanel inside TxPopover for secondary menus or dropdown-like surfaces that should reuse ContextMenu item behavior without another trigger layer. - Prefer
trigger="manual" with explicit x / y for editor shortcuts, command surfaces, canvas nodes, and any trigger that is not a native right-click or simple click. - Keep
anchorMode="pointer" for real context menus; switch to reference only when the menu should align to the whole trigger element. - For teleported submenus, set
outsideGuard on the child TxContextMenuPanel; otherwise the parent outside-click logic can treat submenu clicks as external. - Use
closeOnSelect=false only for parent submenu rows or multi-step actions. Normal menu commands should close after selection. - The default
activationFeedback=true clears the highlight for 90 ms, confirms with the existing active state for 90 ms, then emits select and closes. Reduced motion skips it automatically; disable it at the root, panel, or item when the host already provides stronger immediate feedback. - Keep destructive actions visually explicit with
danger; use color only for semantic product colors that are already part of the design system.
| Prop | Type | Default | Description |
|---|
modelValue | boolean | undefined | undefined | Controlled open state; leave undefined for internal uncontrolled state. |
x | number | 0 | Controlled/manual anchor X coordinate. |
y | number | 0 | Controlled/manual anchor Y coordinate. |
width | number | 220 | Menu width in pixels; 0 keeps automatic width. |
minWidth | number | 0 | Minimum width. |
maxWidth | number | 360 | Maximum width; 0 means unlimited. |
maxHeight | number | 420 | Maximum height; also constrained by available viewport height. |
unlimitedHeight | boolean | false | Disables height limiting. |
disabled | boolean | false | Disables triggers and opening. |
eager | boolean | false | Mounts menu content before first open. |
trigger | 'contextmenu' | 'click' | 'both' | 'manual' | 'contextmenu' | Trigger mode. manual opens only through external state/coordinates. |
anchorMode | 'pointer' | 'reference' | 'pointer' | Anchor mode. pointer follows the mouse / provided coordinates; reference follows the trigger area. |
preventDefault | boolean | true | Prevents the browser native context menu on right-click. |
placement | BaseAnchorPlacement | 'bottom-start' | Initial placement relative to the coordinate point. Supports top/bottom/left/right and start/end variants. |
offset | number | 2 | Distance from the coordinate point. |
closeOnEsc | boolean | true | Closes the menu on Escape. |
closeOnClickOutside | boolean | true | Closes the menu on pointer events outside the menu. |
closeOnTriggerPointerDown | boolean | true | Closes when users click the trigger area after the menu is open; automatically ignored for click / both trigger modes to avoid closing immediately after opening. |
closeOnAnyPointerDown | boolean | false | Closes on any non-menu pointer down, including the trigger area and the rest of the page. |
closeOnSelect | boolean | true | Closes the menu after an item is selected. |
activationFeedback | boolean | true | Runs a 90 ms clear + 90 ms confirmation before select and close for closing commands; reduced motion skips it. |
showArrow | boolean | false | Shows an arrow pointing to the coordinate anchor. |
arrowSize | number | 10 | Arrow size. |
animation | BaseAnchorAnimationOptions | {} | Enter/leave animation. Supports transfer, boom, opacity, and none. |
keepAliveContent | boolean | true | Preserves content state after close. |
panelVariant | 'solid' | 'dashed' | 'plain' | 'solid' | Panel border style. |
panelBackground | 'pure' | 'mask' | 'blur' | 'glass' | 'refraction' | 'refraction' | Panel background effect. |
panelShadow | 'none' | 'soft' | 'medium' | 'medium' | Panel shadow. |
panelRadius | number | 14 | Panel radius. |
panelPadding | number | 6 | Panel padding. |
panelCard | BaseAnchorPanelCardProps | - | Advanced visual props forwarded to the internal TxCard. |
| Event | Params | Description |
|---|
update:modelValue | boolean | Emitted when open state changes. |
open | { x: number; y: number } | Emitted when the menu opens with the active anchor coordinates. |
close | - | Emitted when the menu closes. |
| Name | Type | Description |
|---|
openAt | (target?: { x: number; y: number } | MouseEvent | PointerEvent) => void | Opens the menu at a point or event coordinate. |
openFromEvent | (event: MouseEvent | PointerEvent) => void | Opens from a mouse/pointer event. |
close | () => void | Closes the menu. |
updatePosition | () => void | Manually refreshes Floating UI placement. |
| Prop | Type | Default | Description |
|---|
width | number | string | - | Panel width. |
minWidth | number | string | - | Minimum width. |
maxWidth | number | string | - | Maximum width. |
maxHeight | number | string | - | Maximum height. |
closeOnSelect | boolean | true | Whether child items close the panel after selection. |
activationFeedback | boolean | true | Pre-close confirmation inherited by child items; individual items may override it. |
close | () => void | - | Close callback injected into child items. |
dense | boolean | false | Uses tighter item spacing. |
outsideGuard | boolean | false | Marks the panel as a protected ContextMenu layer for teleported submenus. |
role | 'menu' | 'listbox' | 'none' | 'menu' | Panel ARIA role, which also drives keyboard navigation: menu/listbox enable arrow keys, Home/End, and focusFirstItem, with child items set to role="menuitem" (menu) or role="option" (listbox) accordingly; none opts out of keyboard navigation (no focusable items, so focusFirstItem is a no-op). |
ariaLabel | string | - | ARIA label. |
| Name | Type | Description |
|---|
focusFirstItem | () => void | Moves keyboard focus to the first enabled item in the panel. Only needed when you embed a standalone TxContextMenuPanel inside TxPopover / a custom overlay: call it after the panel opens to send focus into the menu for keyboard navigation. TxContextMenu calls it automatically on open; a bare panel does not. When role is none the panel has no navigable items, so the call is a no-op. |
| Prop | Type | Default | Description |
|---|
disabled | boolean | false | Disables selection and clickability. |
danger | boolean | false | Applies danger styling to the label. |
color | string | - | Custom label color. CSS variables are supported. |
shortcut | string | - | Shortcut hint rendered on the right. |
submenu | boolean | false | Shows a submenu arrow. |
closeOnSelect | boolean | - | Overrides parent closeOnSelect. |
activationFeedback | boolean | - | Overrides inherited confirmation feedback; unset follows the nearest TxContextMenuPanel. |
| Event | Params | Description |
|---|
select | - | Emitted when an enabled item is selected. Closing items with feedback enabled emit after the 180 ms confirmation; bypass paths emit immediately. |
| Prop | Type | Default | Description |
|---|
disabled | boolean | false | Disables the trigger row; the child panel no longer opens. |
placement | BaseAnchorPlacement | 'right-start' | Positions the child panel relative to the trigger row. |
offset | number | 4 | Distance in pixels between the trigger row and the child panel. |
width | number | 0 | Fixed child panel width; 0 sizes to content bounded by minWidth. |
minWidth | number | 160 | Minimum child panel width in pixels. |
maxHeight | number | 420 | Maximum child panel height in pixels. |
unlimitedHeight | boolean | false | Disables the child panel max-height constraint. |
animation | BaseAnchorAnimationOptions | {} | Anchor animation config for the child panel. |
panelCard | BaseAnchorPanelCardProps | - | Low-level card props forwarded to the child panel. |
panelVariant | 'solid' | 'dashed' | 'plain' | 'solid' | Visual border variant of the child panel. |
panelBackground | 'pure' | 'mask' | 'blur' | 'glass' | 'refraction' | 'refraction' | Background treatment of the child panel. |
panelShadow | 'none' | 'soft' | 'medium' | 'medium' | Shadow strength of the child panel. |
panelRadius | number | 14 | Child panel corner radius in pixels. |
panelPadding | number | 6 | Child panel padding in pixels. |
| Prop | Type | Default | Description |
|---|
dashed | boolean | false | Uses a dashed separator. |
inset | boolean | false | Adds left inset to align with icon/nested content. |
| Slot | Props | Description |
|---|
trigger | - | Custom trigger element. The default slot is used as fallback trigger content. |
default | - | Fallback trigger content when trigger is not provided. |
menu | - | Menu content rendered inside the internal TxContextMenuPanel. |
| Slot | Props | Description |
|---|
default | - | Menu items, dividers, or nested overlay content. |
| Slot | Props | Description |
|---|
default | - | Main item label. |
avatar | - | Leading icon/avatar content forwarded to TxCardItem. |
description | - | Secondary description text forwarded to TxCardItem. |
right | - | Replaces the generated shortcut/submenu area. |
| Slot | Props | Description |
|---|
default | - | Main trigger row label. |
right | - | Trailing metadata on the trigger row, rendered before the submenu chevron. |
menu | - | Child panel content, usually TxContextMenuItem rows or nested TxContextMenuSubmenu. |
TxContextMenuDivider does not expose slots.
- Placement:
TxContextMenu positions itself through TxBaseAnchor with Floating UI flip + shift + size, flipping/shifting near viewport edges and constraining max height to the available viewport. - Anchor:
anchorMode="pointer" (default) follows the mouse / provided coordinates and updates the virtual anchor to the latest position on repeated right-clicks; anchorMode="reference" follows the trigger area, more like a Dropdown. - Trigger:
trigger supports contextmenu / click / both / manual; manual disables internal event handling and opens only through v-model + x/y, for button clicks, editor shortcuts, and canvas node menus. - Close: Escape, outside click, and item selection close by default;
closeOnSelect=false parent-submenu or multi-step rows select immediately without blinking. - Confirmation:
activationFeedback is enabled by default. The item clears its current hover/focus highlight, reuses TxCardItem's active style to confirm, then runs the business action and closes. Root configuration reaches nested submenus, panels/items may override it, and prefers-reduced-motion: reduce adds no delay. - Submenus: prefer
TxContextMenuSubmenu — it ships hover expansion, the safe triangle (sibling submenu rows crossed on a diagonal path to the child panel do not expand; resting on one for about 100ms switches to it), keyboard traversal, outside-click exemption, and whole-chain close; TxContextMenuPanel can still be embedded manually in TxPopover / a custom overlay, in which case a teleported child panel must set outsideGuard, otherwise the parent treats the submenu click as an outside click and closes. - Animation: handled directly by
BaseAnchor — transfer / boom / opacity / none.
- Source:
packages/tuffex/packages/components/src/context-menu/src/TxContextMenu.vue confirms controlled/uncontrolled open state, pointer/reference virtual anchors, trigger modes, outside-click handling, BaseAnchor forwarding, and root activationFeedback. - Source:
packages/tuffex/packages/components/src/context-menu/src/TxContextMenuPanel.vue confirms panel layout, closeOnSelect / activationFeedback / close injection, dense, outsideGuard, role, and ariaLabel behavior. - Source:
packages/tuffex/packages/components/src/context-menu/src/TxContextMenuItem.vue confirms disabled, danger, custom color, shortcut, submenu, per-item closeOnSelect / activationFeedback, item slots, and pre-close confirmation. - Source:
packages/tuffex/packages/components/src/context-menu/src/TxContextMenuSubmenu.vue confirms hover expansion, keyboard traversal, root close/confirmation context passthrough, and automatic outsideGuard; its closeOnSelect=false trigger never runs feedback. - Shared behavior:
packages/tuffex/packages/utils/menu-activation-feedback.ts owns the 90 ms clear / 90 ms confirm state machine, reduced-motion bypass, duplicate suppression, and unmount cleanup. - Type contracts:
packages/tuffex/packages/components/src/context-menu/src/types.ts exports trigger, anchor, panel visual enums, confirmation props, and open-target shapes. - Verified coverage: Coverage:
packages/tuffex/packages/components/src/context-menu/__tests__/context-menu.test.ts covers controlled width, right-click/coordinate opening, Escape and pointerdown close guards, pointer/reference anchors, pointer and keyboard confirmation timing, duplicate suppression, root/panel/item opt-out, reduced motion, unmount cleanup, closeOnSelect=false, nested root close, and shortcut/color/submenu rendering.
查看源码packages/tuffex/packages/components/src/context-menu/index.ts