Skip to content

fix(react-headless-components-preview): share anchor-name across positioned popovers#36347

Open
micahgodbolt wants to merge 1 commit into
microsoft:masterfrom
micahgodbolt:fix/headless-positioning-shared-anchor-name
Open

fix(react-headless-components-preview): share anchor-name across positioned popovers#36347
micahgodbolt wants to merge 1 commit into
microsoft:masterfrom
micahgodbolt:fix/headless-positioning-shared-anchor-name

Conversation

@micahgodbolt

Copy link
Copy Markdown
Member

Fixes

Part of #36346.

What

usePositioning wrote a unique anchor-name onto the trigger element and overwrote anything already there:

effectiveTarget.style.setProperty('anchor-name', anchorName); // clobbers

When two positioned popovers share one trigger — e.g. a hover Tooltip + a click Menu on the same button — the two usePositioning instances clobber each other's anchor-name. anchor-name is single-valued here, so the last writer wins; the other popover's position-anchor points at a name that no longer exists and falls back to default (static / top‑left) placement.

Rendered proof (menu closed, tooltip visible)

button   anchor-name   = "--popover-anchor-r1"          ← only the MENU's name survives
div[role=tooltip popover=hint]      position-anchor = "--popover-anchor-r2"   ← orphaned
div[role=presentation popover=auto] position-anchor = "--popover-anchor-r1"   ← menu, OK

How

anchor-name accepts a comma-separated list. Each usePositioning instance now appends its own name and removes only its own on cleanup, preserving any author-set or sibling anchors:

const names = readAnchorNames();
if (!names.includes(anchorName)) {
  effectiveTarget.style.setProperty('anchor-name', [...names, anchorName].join(', '));
}
// cleanup removes only this instance's name

Single-popover triggers are unchanged; N popovers per trigger now each resolve their own position-anchor.

Tests

Added two unit tests to usePositioning.test.tsx:

  • two instances on one trigger → anchor-name contains both distinct names
  • a pre-existing author-set anchor-name is preserved

All 19 usePositioning tests pass; Tooltip suite (16) unaffected.

…tioned popovers

usePositioning overwrote the trigger's anchor-name with a unique name per
instance, so two popovers sharing one trigger (e.g. a hover Tooltip and a
click Menu on the same button) clobbered each other — only the last writer
stayed anchored and the other fell back to default placement.

Append this instance's anchor name to the trigger's comma-separated
anchor-name list and remove only our own on cleanup, preserving any
author-set or sibling anchors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@micahgodbolt micahgodbolt requested a review from a team as a code owner June 24, 2026 18:14
@github-actions

Copy link
Copy Markdown

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-headless-components-preview
react-headless-components-preview: entire library
248.544 kB
71.466 kB
248.779 kB
71.541 kB
235 B
75 B

🤖 This report was generated against 19d82d85bda458b0af3fa4e0814bf3232fc78594

@github-actions

Copy link
Copy Markdown

Pull request demo site: URL

@dmytrokirpa

Copy link
Copy Markdown
Contributor

Confidence Score: 85/100

The code changes look correct and well-covered by tests, but merge readiness is currently blocked by failing CI checks.

Findings

Blockers (must fix before merge)

  • CI is failing with two unsuccessful checks: CI/e2e (pull_request) and CI/react-major-versions (pull_request).

Warnings (should address)

  • None.

Info (consider)

Category Breakdown

Category Status Notes
Change file PASS Patch change file present: change/@fluentui-react-headless-components-preview-b16870e3-e158-4967-bf40-1c8256986797.json.
V9 patterns PASS No React.FC usage, no hardcoded style regressions, no slot/style pattern concerns in touched files.
Dep layers PASS No dependency or package layer changes.
SSR safety PASS No unguarded window/document/navigator/storage access introduced.
Testing PASS Source change in packages/react-components/react-headless-components-preview/library/src/hooks/usePositioning/usePositioning.ts is covered by new tests in packages/react-components/react-headless-components-preview/library/src/hooks/usePositioning/usePositioning.test.tsx.
API surface PASS No public export additions/removals detected.
Accessibility PASS No accessibility attribute or interaction regressions detected in this hook-level change.
Security/Quality PASS No eval/new Function/dangerouslySetInnerHTML/ts-ignore issues introduced.
Docs coverage PASS Bug-fix behavior restoration; no additional user-facing or harness-doc updates required.

Recommendation

REQUEST_CHANGES

Code quality is solid and the fix is well-tested, but CI must be green before merge.


Posted via the /review-pr skill.

expect(node.style.getPropertyValue('anchor-name')).toMatch(/^--popover-anchor-/);
});

it('appends to anchor-name so multiple instances can share one trigger', () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also add a e2e test that covers the Menu + Tooltip scenario mentioned in the issue

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.

2 participants