feat(react-headless-components-preview): hybrid usePositioning with lazy CSS Anchor / floating-ui#36124
Draft
dmytrokirpa wants to merge 2 commits into
Conversation
…azy CSS Anchor / floating-ui Replaces the anchor-only `usePositioning` in the headless preview package with a hybrid implementation that picks a positioning strategy at runtime and lazy-loads its chunk: - CSS Anchor Positioning helper when the browser supports it (chunk: `fluentui-anchor-positioning`). - floating-ui-based fallback otherwise (chunk: `fluentui-floating-ui-positioning` + transitive `floating-ui-dom`). Both strategies live in their own modules (`applyAnchorPositioning.ts`, `applyFloatingUIPositioning.ts`) and are dispatched via `lazyApply.ts`. The hook itself stays fully synchronous, always calls the same React hooks, and runs positioning imperatively inside a single layout effect. The container is set to `visibility: hidden` while the chunk is loading (and, on the floating-ui path, while `computePosition` is in flight) to avoid a visual jump before the surface is anchored. The apply helpers clear it once positioning is committed. Other notable changes: - `usePositioning` now returns `arrowRef` (callback ref) alongside `targetRef` / `containerRef`. Floating-UI uses the `arrow` middleware; the CSS Anchor branch positions the arrow as another anchored element via `position-anchor` + `anchor(center)`. - New `preloadPositioning()` helper warms the chunk for whichever strategy this browser will end up using. - `usePlacementObserver.ts` was deleted; its rect-detection logic moved into `applyAnchorPositioning.ts` as a private helper. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📊 Bundle size report
🤖 This report was generated against 7b586d76279e090d7b459bc4c066bd9804e4f2aa |
|
Pull request demo site: URL |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Replaces the anchor-only
usePositioningin@fluentui/react-headless-components-previewwith a hybrid implementation that picks a positioning strategy at runtime and lazy-loads its chunk:fluentui-anchor-positioning.fluentui-floating-ui-positioning(+ transitivefloating-ui-dom).A browser only ever loads the chunk for the path it ends up using.
Architecture
usePositioning.ts— single hook, fully synchronous, always calls the same React hooks. All positioning work happens imperatively inside oneuseIsomorphicLayoutEffect.applyAnchorPositioning.ts— pure imperative helper that writesanchor-name/position-anchor/position-area/position-try-fallbacksetc., plus a placement observer that mirrors the browser-resolved placement back intodata-placementafter flip fires.applyFloatingUIPositioning.ts— pure imperative helper that uses@floating-ui/dom'scomputePosition+autoUpdatewithoffset/flip/shift/size/arrowmiddleware.lazyApply.ts— dispatcher withimport()-driven chunk loading, runtime caching, and cancellation-safe scheduling.Notable details
visibility: hiddenon the container synchronously before scheduling apply; each helper clears it once its first set of coordinates lands.arrowRefcallback alongsidetargetRef/containerRef. Floating-UI uses thearrowmiddleware (mirrors the originalreact-positioningarrow wiring); the CSS Anchor branch positions the arrow as a CSS-anchored element viaposition-anchor+anchor(center)so it tracks the trigger center even after position-try fallbacks.preloadPositioning()— public helper that warms whichever chunk this browser will end up using; safe to call during SSR.usePlacementObserver.tsremoved — its rect-detection logic is now a private helper insideapplyAnchorPositioning.ts.'use no memo'(matches thereact-positioningpackage's hook).Public API surface
@fluentui/react-headless-components-preview/positioningnow exports:usePositioning(options): { targetRef, containerRef, arrowRef }preloadPositioning(): Promise<unknown>(new)POSITIONS,ALIGNMENTS,getPlacementString,resolvePositioningShorthand, types