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

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.

1 participant