Skip to content

fix(react-menu): let setTarget win for context menus - #36486

Draft
AKnassa wants to merge 1 commit into
microsoft:masterfrom
AKnassa:ak-issue-31727-menu-imperative-context-target
Draft

fix(react-menu): let setTarget win for context menus#36486
AKnassa wants to merge 1 commit into
microsoft:masterfrom
AKnassa:ak-issue-31727-menu-imperative-context-target

Conversation

@AKnassa

@AKnassa AKnassa commented Aug 1, 2026

Copy link
Copy Markdown

Previous Behavior

When a Menu opens as a context menu (openOnContext), it always anchors to the mouse point — even when an app explicitly asks for a different anchor with positioningRef.setTarget(). For example, anchoring a Shift+F10 context menu to the focused row: the user's choice was silently overwritten, because the menu re-applied its own stored mouse position after the app's call.

New Behavior

The app's setTarget() call wins, the way the API promises. The menu now sets its mouse-point anchor imperatively (instead of through a state-driven option that kept re-applying itself), and onOpenChange fires after the menu's own anchor is set — so anything the app does in that callback takes precedence. Plain right-click context menus behave exactly as before, and an explicit positioning.target prop still beats everything. No public API changes.

This is the fix direction a maintainer endorsed in the issue discussion.

What changed

  • useMenu sets the context-menu anchor through an internal positioning ref (merged with the user's ref); the stored state stays in sync because it's public API.
  • onOpenChange now fires after the internal anchor is set.
  • New unit tests (the app's anchor wins; mouse anchoring still works; the trigger is restored on close) and new Cypress browser tests that reproduced the bug with real geometry before the fix — the menu rendered at the click point instead of the requested anchor.
  • A change file for the release notes.

Full react-menu suite (496 tests), react-positioning suite (199), and the Menu Cypress spec (69) are all green. The same latent pattern exists in Popover and the headless Menu copy — noted as follow-ups, not touched here.

Related Issue(s)

For openOnContext menus, useMenu stored the right-click mouse
position in state and passed it as the positioning target option.
usePositioning re-syncs that option into its override ref in a
layout effect at commit time, so a user's imperative
positioningRef.setTarget() (e.g. anchoring a Shift+F10 context menu
to the focused row) was always clobbered.

Set the context target imperatively instead, through an internal
positioning ref merged with the user's, and stop passing the
state-driven target option (the state stays in sync because
MenuState.contextTarget is public). An explicit positioning.target
from props still wins. onOpenChange now fires after the internal
context target is set, so a setTarget call inside it takes
precedence - the ordering endorsed in the issue discussion.

Covered by new jsdom tests (imperative target wins; mouse anchoring
preserved; trigger restored on close) and Cypress geometry tests
that reproduced the bug in a real browser before the fix. Full
react-menu (496) and react-positioning (199) suites green. The same
latent pattern exists in react-popover and the headless Menu copy -
follow-up candidates.

Fixes microsoft#31727
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: imperative set target on context menu does not work

1 participant