Skip to content

Replace react-positioning runtime with parity engine - #36951

Draft
Dmytro Kirpa (dmytrokirpa) wants to merge 9 commits into
masterfrom
dmytrokirpa-upstream-positioning-engine
Draft

Dmytro Kirpa (dmytrokirpa) wants to merge 9 commits into
masterfrom
dmytrokirpa-upstream-positioning-engine

Conversation

@dmytrokirpa

@dmytrokirpa Dmytro Kirpa (dmytrokirpa) commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Previous Behavior

@fluentui/react-positioning used the Floating UI engine at runtime and had no repeatable browser benchmark comparing the positioning workload against that implementation.

New Behavior

Replaces the runtime positioning engine with a standalone parity engine, preserving the existing public hook semantics and pinned lower-stack geometry/lifecycle contracts. Adds a 15,000-byte minified bundle gate, a paired Electron benchmark against the immutable lower-PR Floating UI implementation, and a bounded raster comparison target. The benchmark reports workload-specific medians, p95s, and paired ratios without machine-dependent pass/fail thresholds.

The lower stack's fractional-layout correction uses an engine-free sibling reference based on committed literal baseline styles; the baseline file remains unchanged. Negative controls confirm that sub-layout-step inline-style drift and rectangle displacement are still detected. A scoped ::-webkit-scrollbar rule keeps scroll fixtures consistent in the older Chromium bundled with Cypress 13, without disabling scrolling.

Validation on this host after syncing lower-stack commit 85dedaeb3d1938cac02e60cb49104b77d3301c11:

  • NX_DAEMON=false yarn nx run react-positioning:build — passed.
  • NX_DAEMON=false yarn nx run react-positioning:test — passed (24 suites, 219 tests).
  • NX_DAEMON=false yarn nx run react-positioning:lint — passed.
  • NX_DAEMON=false yarn nx run react-positioning:type-check — passed.
  • NX_DAEMON=false yarn nx format:check --files=packages/react-components/react-positioning/library/scripts/positioning-raster.mjs — passed.
  • NX_DAEMON=false yarn nx format:check --files=packages/react-components/react-positioning/library/README.md,packages/react-components/react-positioning/library/src/usePositioning.geometry.cy.tsx — passed.
  • NX_DAEMON=false yarn nx run react-positioning:test-bundle-size — passed.
  • NX_DAEMON=false yarn nx run react-positioning:bundle-size --skip-nx-cache — passed at 14,996 / 15,000 minified bytes.
  • NX_DAEMON=false yarn nx run react-positioning:e2e --spec=src/usePositioning.geometry.cy.tsx --browser=electron --config=retries=0 — passed (143/143 browser cases).
  • NX_DAEMON=false yarn nx run react-positioning:test-raster — passed (143/143 contract tests for both implementations; 142 raster comparisons with zero differing pixels). The unchanged oracle is 788e3b739fe79246a2f8850d1c575cf4018fd744.
  • POSITIONING_BENCH_SEED=36870 NX_DAEMON=false yarn nx run react-positioning:benchmark — passed against lower-stack oracle fca219991ed9e907b01274bd89ac1431e51c573a. On this single Electron 33.2.1 / Chrome 130 run, replacement/oracle median paired ratios were 0.722x initialization, 0.565x imperative updates, 0.394x scroll, and 0.394x resize; p95 paired ratios were 0.733x, 0.667x, 0.417x, and 0.412x respectively. This is one-host comparative evidence, not a universal no-regression claim.
  • React 17 RIT was not rerun in this upper checkout because its isolated tmp/rit/react-17/node_modules dependencies are absent; the target stops during its prepare step. The lower-stack owner reports 150/150 cases passing in the React 17 / Cypress 13 run after the scrollbar fix.

Related Issue(s)

  • No linked issue; this is the engine PR stacked on the positioning contracts PR.

@dmytrokirpa
Dmytro Kirpa (dmytrokirpa) added this pull request to stack #36952 October 20, 2026 09:34
@dmytrokirpa
Dmytro Kirpa (dmytrokirpa) marked this pull request as draft October 20, 2026 09:46
@github-actions

Copy link
Copy Markdown

Pull request demo site: URL

@dmytrokirpa
Dmytro Kirpa (dmytrokirpa) removed this pull request from stack #36952 October 23, 2026 17:11
@dmytrokirpa
Dmytro Kirpa (dmytrokirpa) changed the base branch from dmytrokirpa-upstream-positioning-contracts to master October 23, 2026 17:11
@github-actions

Copy link
Copy Markdown

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-charts
AreaChart
402.942 kB
125.854 kB
389.114 kB
121.356 kB
-13.828 kB
-4.498 kB
react-charts
DeclarativeChart
756.223 kB
221.658 kB
742.395 kB
217.006 kB
-13.828 kB
-4.652 kB
react-charts
DonutChart
313.421 kB
96.687 kB
299.593 kB
92.188 kB
-13.828 kB
-4.499 kB
react-charts
FunnelChart
304.836 kB
93.372 kB
291.008 kB
88.908 kB
-13.828 kB
-4.464 kB
react-charts
GanttChart
385.85 kB
120.344 kB
372.022 kB
115.791 kB
-13.828 kB
-4.553 kB
react-charts
GaugeChart
313.382 kB
96.231 kB
299.554 kB
91.736 kB
-13.828 kB
-4.495 kB
react-charts
GroupedVerticalBarChart
394.163 kB
123.176 kB
380.335 kB
118.602 kB
-13.828 kB
-4.574 kB
react-charts
HeatMapChart
388.057 kB
121.294 kB
374.229 kB
116.802 kB
-13.828 kB
-4.492 kB
react-charts
HorizontalBarChart
293.131 kB
89.081 kB
279.303 kB
84.417 kB
-13.828 kB
-4.664 kB
react-charts
Legends
232.566 kB
69.71 kB
218.726 kB
65.141 kB
-13.84 kB
-4.569 kB
react-charts
LineChart
414.183 kB
129.026 kB
400.355 kB
124.428 kB
-13.828 kB
-4.598 kB
react-charts
PolarChart
341.319 kB
106.588 kB
327.491 kB
101.972 kB
-13.828 kB
-4.616 kB
react-charts
SankeyChart
209.067 kB
67.203 kB
195.239 kB
62.711 kB
-13.828 kB
-4.492 kB
react-charts
ScatterChart
393.396 kB
123.028 kB
379.568 kB
118.456 kB
-13.828 kB
-4.572 kB
react-charts
VerticalBarChart
430.382 kB
128.028 kB
416.554 kB
123.536 kB
-13.828 kB
-4.492 kB
react-charts
VerticalStackedBarChart
399.949 kB
124.471 kB
386.121 kB
119.896 kB
-13.828 kB
-4.575 kB
react-combobox
Combobox (including child components)
137.042 kB
44.29 kB
123.2 kB
39.537 kB
-13.842 kB
-4.753 kB
react-combobox
Dropdown (including child components)
135.723 kB
43.711 kB
121.881 kB
38.984 kB
-13.842 kB
-4.727 kB
react-components
react-components: all base hooks
219.615 kB
68.539 kB
205.787 kB
63.936 kB
-13.828 kB
-4.603 kB
react-components
react-components: Accordion, Button, FluentProvider, Image, Menu, Popover
223.278 kB
67.379 kB
209.448 kB
62.739 kB
-13.83 kB
-4.64 kB
react-components
react-components: entire library
1.283 MB
322.23 kB
1.269 MB
317.201 kB
-13.826 kB
-5.029 kB
react-datepicker-compat
DatePicker Compat
216.641 kB
64.398 kB
202.797 kB
59.838 kB
-13.844 kB
-4.56 kB
react-menu
Menu (including children components)
156.704 kB
49.751 kB
143.035 kB
45.299 kB
-13.669 kB
-4.452 kB
react-menu
Menu (including selectable components)
159.869 kB
50.385 kB
146.2 kB
45.922 kB
-13.669 kB
-4.463 kB
react-popover
Popover
122.078 kB
39.348 kB
108.382 kB
34.956 kB
-13.696 kB
-4.392 kB
react-positioning
usePositioning
29.156 kB
10.251 kB
14.992 kB
5.68 kB
-14.164 kB
-4.571 kB
react-tag-picker
@fluentui/react-tag-picker - package
171.164 kB
53.355 kB
157.324 kB
48.816 kB
-13.84 kB
-4.539 kB
react-teaching-popover
TeachingPopover
97.048 kB
30.59 kB
83.354 kB
26.157 kB
-13.694 kB
-4.433 kB
react-timepicker-compat
TimePicker
139.754 kB
45.561 kB
125.912 kB
40.803 kB
-13.842 kB
-4.758 kB
react-tooltip
Tooltip
54.989 kB
19.528 kB
41.361 kB
15.068 kB
-13.628 kB
-4.46 kB
Unchanged fixtures
Package & Exports Size (minified/GZIP)
react-avatar
Avatar
49.166 kB
15.658 kB
react-avatar
AvatarGroup
14.126 kB
5.692 kB
react-avatar
AvatarGroupItem
58.643 kB
18.172 kB
react-breadcrumb
@fluentui/react-breadcrumb - package
103.23 kB
29.071 kB
react-charts
HorizontalBarChartWithAxis
63 B
83 B
react-charts
Sparkline
79.774 kB
26.585 kB
react-checkbox
Checkbox
31.71 kB
11.289 kB
react-components
react-components: Button, FluentProvider & webLightTheme
68.214 kB
19.863 kB
react-components
react-components: FluentProvider & webLightTheme
41.444 kB
13.893 kB
react-dialog
Dialog (including children components)
86.865 kB
26.93 kB
react-field
Field
23.331 kB
8.683 kB
react-headless-components-preview
react-headless-components-preview: entire library
269.204 kB
80.184 kB
react-headless-components-preview
react-headless-components-preview: Calendar
42.084 kB
13.907 kB
react-headless-components-preview
@fluentui/react-headless-components-preview/tag-picker
50.254 kB
16.375 kB
react-headless-components-preview
@fluentui/react-headless-components-preview/teaching-popover
33.766 kB
11.09 kB
react-input
Input
26.594 kB
8.782 kB
react-list
List
71.03 kB
21.795 kB
react-list
ListItem
95.718 kB
29.156 kB
react-overflow
hooks only
10.203 kB
3.696 kB
react-persona
Persona
56.119 kB
17.602 kB
react-portal-compat
PortalCompatProvider
5.198 kB
2.104 kB
react-positioning
useSafeZoneArea
13.461 kB
5.425 kB
react-progress
ProgressBar
20.566 kB
7.98 kB
react-radio
Radio
28.38 kB
9.229 kB
react-radio
RadioGroup
14.286 kB
5.757 kB
react-range-slider-preview
RangeSlider
39.889 kB
13.475 kB
react-select
Select
27.184 kB
9.835 kB
react-slider
Slider
33.727 kB
11.61 kB
react-spinbutton
SpinButton
34.735 kB
11.44 kB
react-swatch-picker
@fluentui/react-swatch-picker - package
89.202 kB
26.275 kB
react-switch
Switch
34.378 kB
10.933 kB
react-table
DataGrid
143.634 kB
42.543 kB
react-table
Table (Primitives only)
38.903 kB
13.017 kB
react-table
Table as DataGrid
119.146 kB
33.785 kB
react-table
Table (Selection only)
67.409 kB
19.301 kB
react-table
Table (Sort only)
66.072 kB
18.926 kB
react-tags
InteractionTag
13.986 kB
5.531 kB
react-tags
Tag
30.614 kB
9.763 kB
react-tags
TagGroup
69.63 kB
21.545 kB
react-textarea
Textarea
24.959 kB
9.052 kB
react-tree
FlatTree
132.701 kB
39.468 kB
react-tree
PersonaFlatTree
134.558 kB
39.973 kB
react-tree
PersonaTree
130.645 kB
38.769 kB
react-tree
Tree
128.788 kB
38.287 kB
🤖 This report was generated against 6d3e9d686434d69ac8fc9ca4c4a93f3afaa3d676

@@ -0,0 +1,6 @@
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🕵🏾‍♀️ visual changes to review in the Visual Change Report

vr-tests-react-components/Avatar Converged 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/Avatar Converged.badgeMask - RTL.normal.chromium.png 6 Changed
vr-tests-react-components/Avatar Converged.badgeMask.normal.chromium.png 6 Changed
vr-tests-react-components/Positioning 2 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/Positioning.Positioning end.updated 2 times.chromium.png 49 Changed
vr-tests-react-components/Positioning.Positioning end.chromium.png 878 Changed
vr-tests-react-components/ProgressBar converged 3 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - Dark Mode.default.chromium.png 106 Changed
vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - High Contrast.default.chromium.png 100 Changed
vr-tests-react-components/ProgressBar converged.Indeterminate + thickness.default.chromium.png 126 Changed
vr-tests-react-components/TagPicker 1 screenshots
Image Name Diff(in Pixels) Image Type
vr-tests-react-components/TagPicker.disabled - Dark Mode.chromium.png 658 Changed

There were 1 duplicate changes discarded. Check the build logs for more information.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant