Skip to content

feat(react-headless-components-preview): add Popover & positioning#36006

Merged
mainframev merged 29 commits intomicrosoft:masterfrom
mainframev:feat/headless-popover-v2
May 1, 2026
Merged

feat(react-headless-components-preview): add Popover & positioning#36006
mainframev merged 29 commits intomicrosoft:masterfrom
mainframev:feat/headless-popover-v2

Conversation

@mainframev
Copy link
Copy Markdown
Contributor

@mainframev mainframev commented Apr 20, 2026

Adds a headless Popover (Popover, PopoverTrigger, PopoverSurface) to the @fluentui/react-headless-components-preview package, positioned via the native CSS Anchor Positioning API instead of floating-ui

Feature with v9 @fluentui/react-popover

v9 feature Status
open / defaultOpen / onOpenChange
openOnHover + mouseLeaveDelay
openOnContext (right-click, cursor-anchored)
withArrow (+ consumer-owned arrow CSS via [data-placement]) ⚠️ User provides styles for arrow based on data-placement and data-arrow attributes
trapFocus + aria-modal / role="dialog" ❌ Not implemented (TBA)
disableAutoFocus ❌ Not implemented (TBA)
closeOnScroll ❌ Not implemented
closeOnIframeFocus ➖ Side effect of popover="auto"
Nested popovers (per-instance Escape / dismiss)
positioning.position + positioning.align
positioning.offset (number or { mainAxis, crossAxis })
positioning.coverTarget
positioning.fallbackPositions
positioning.autoSize (true / 'width' / 'height') ❌ Not implemented (TBA)
positioning.overflowBoundary ❌ Not implemented (TBA)
positioning.overflowBoundaryPadding ❌ Not implemented (TBA)
positioning.overflowBoundaryRect ❌ Not implemented (TBA)
positioning.matchTargetSize: 'width'
positioning.strategy: 'absolute' | 'fixed'
positioning.pinned
positioning.target (custom anchor)
positioning.positioningRef (imperative setTarget)
flipBoundary ❌ Not implemented (TBA)
arrowPadding ➖ Configurable on user side via styles
shiftToCoverTarget ❌ Not implemented (TBA)
onPositioningEnd ➖ Native API has no "settle" event
disableUpdateOnResize ➖ Native anchor positioning + targeted usage is always-on
useTransform ➖ Native anchor positioning doesn't use transform, no conceptual equivalent

Related Issue(s)

@github-actions
Copy link
Copy Markdown

Pull request demo site: URL

@mainframev mainframev force-pushed the feat/headless-popover-v2 branch from 22f36ba to e9fef9d Compare April 20, 2026 01:46
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 20, 2026

📊 Bundle size report

✅ No changes found

@mainframev mainframev force-pushed the feat/headless-popover-v2 branch 12 times, most recently from 58218ca to c32d139 Compare April 22, 2026 10:30
@mainframev mainframev changed the title WIP: feat(react-headless-components-preview): add Popover & positioning feat(react-headless-components-preview): add Popover & positioning Apr 22, 2026
@mainframev mainframev marked this pull request as ready for review April 22, 2026 10:42
@mainframev mainframev requested review from a team as code owners April 22, 2026 10:42
@mainframev mainframev requested a review from dmytrokirpa April 22, 2026 10:47
@mainframev mainframev force-pushed the feat/headless-popover-v2 branch from c32d139 to 4774cce Compare April 22, 2026 12:21
@mainframev mainframev requested a review from a team as a code owner April 22, 2026 12:21
@mainframev mainframev force-pushed the feat/headless-popover-v2 branch from 4774cce to 0022e71 Compare April 22, 2026 12:57
mainframev added 27 commits May 1, 2026 13:28
Adds a PopoverAuto component that renders its surface with
`popover="auto"` instead of `popover="manual"`, so light dismiss
(Escape, click-outside, popover-stack peer dismissal) is handled by
the browser rather than React.

Implementation:
- Extracts a shared internal hook `useInternalPopover(props, popoverType)`
  in usePopover.ts. Both the existing `usePopover` (manual) and a new
  `usePopoverAuto` are thin wrappers that fix the popoverType.
- Sets the `popover` attribute to the actual mode value when calling
  `showPopover()`.
- In auto mode: disables `useOnClickOutside` / `useOnScrollOutside` and
  attaches a `toggle` event listener on the surface to mirror the
  browser's open/closed state into React and fire onOpenChange.
- Plumbs `popoverType` through PopoverContextValue so PopoverSurface
  can skip its own Escape handler in auto mode (the browser owns it).
- Exports `PopoverAuto` and `usePopoverAuto` from the popover subpath.
- Updates the Nested Storybook story to use PopoverAuto, where browser
  popover-stack semantics keep ancestor surfaces open when a descendant
  popover opens, and dismiss the ancestor chain on outside interaction.

Tests, type-check, lint, and api-report all pass.
@mainframev mainframev force-pushed the feat/headless-popover-v2 branch from 83ac8d8 to 7ac897e Compare May 1, 2026 11:29
@mainframev mainframev removed the request for review from a team May 1, 2026 11:29
@mainframev mainframev merged commit d44cd64 into microsoft:master May 1, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants