Skip to content

fix(react-headless-components-preview): dismiss Popover on focus exit by default - #36929

Open
Paul Mardling (PaulGMardling) wants to merge 13 commits into
microsoft:masterfrom
PaulGMardling:paulgmardling-39630-headless-focus-dismissal
Open

Paul Mardling (PaulGMardling) wants to merge 13 commits into
microsoft:masterfrom
PaulGMardling:paulgmardling-39630-headless-focus-dismissal

Conversation

@PaulGMardling

@PaulGMardling Paul Mardling (PaulGMardling) commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Previous Behavior

Non-modal headless Popover stays open after Tab moves focus outside.

New Behavior

When you Tab out of a non-modal Popover, it now closes and leaves focus on the control you moved to. Moving focus between the trigger, popup, or content belonging to either keeps it open, including content in portals, shadow roots, and iframes. Hovering over the trigger, popup, or its linked content also keeps it open.

No new props are needed. Controlled Popovers still decide whether to accept a close request, and modal Popovers work as before.

For iframe focus changes we can't detect directly, we check every 100 ms while needed. A quick move out and back between checks can still be missed.

Related Issue(s)

  • References ADO 39630; closure requires TCS verification.
  • Downstream: no dedicated Fluent Modern integration PR has been verified for 39630. Release uptake and downstream verification are still needed.
  • Related InfoLabel work, not the 39630 integration: #36953 and 1JS PR 5862255 address 39558.
Validation

At 2522d104b8: three test files consolidated without removing cases; production unchanged from 57963a1093.

Command Result
yarn nx run react-headless-components-preview:test --runTestsByPath src/components/Popover/Popover.test.tsx --runInBand --skip-nx-cache 51 passed (Node 22)
yarn nx run react-headless-components-preview:e2e --spec src/components/Popover/Popover.cy.tsx,src/components/Popover/PopoverFocus.cy.tsx,src/components/Popover/PopoverLifecycle.cy.tsx,src/components/TeachingPopover/TeachingPopover.cy.tsx,src/components/InfoLabel/InfoLabel.cy.tsx --browser chrome --config retries=0 --skip-nx-cache 148 passed, 3 existing pending
yarn nx run react-headless-components-preview:test-rit--17--e2e --command='yarn run -T rit --project-id portal-focus-fixes --react 17 --run e2e --verbose' --excludeTaskDependencies --skip-nx-cache 114 passed, 4 existing pending
yarn nx run react-headless-components-preview:test-rit--18--e2e --command='yarn run -T rit --project-id portal-focus-fixes --react 18 --run e2e --verbose' --excludeTaskDependencies --skip-nx-cache 117 passed, 4 existing pending
yarn nx run react-headless-components-preview:type-check --excludeTaskDependencies Passed
yarn nx run react-headless-components-preview:lint Passed

At 9cde4434ae, the story-only CI repairs also passed yarn nx run react-headless-components-preview-stories:test-ssr --skip-nx-cache, yarn nx run-many -p react-headless-components-preview-stories -t test-rit--17--type-check,test-rit--18--type-check --excludeTaskDependencies --skip-nx-cache (after no-install preparation), and yarn nx run react-headless-components-preview-stories:lint. Both Portal stories retained their URLs and passed Chrome keyboard/hover checks with no runtime errors. Fresh hosted CI is pending.

RIT used prepared local scaffolds selecting the three Popover specs. Normal commit hooks passed. Latest-head hosted CI and Windows/Narrator/TCS verification remain outstanding; the earlier hosted Drawer chunk-load failure has not been established as unrelated.

Reproduction and fix verification

Open the non-modal Popover focus-exit repro

  1. Move keyboard focus into the preview, Tab to Open popover, and press Enter.
  2. From Inside, press Tab to After popover.
  3. Pass: popup closes, requested state becomes false, and focus stays on After popover. Deployed behavior observed on 23 October 2026: focus moved, but the popup stayed open.

This editable link runs the deployed playground, not the PR build; deployments can change.

Against the fix: from an initialized task checkout at 2522d104b8, run yarn nx run react-headless-components-preview-stories:storybook --port=44123 --ci --no-open. Move keyboard focus into each preview; do not click external Portal controls, which can invoke native light dismiss.

Story Steps and pass condition
Hover Hover Hover me, focus Inside hover popover, return the pointer to the popup, then Tab. After hover popover keeps focus; popup remains visible until pointer leave.
Iframe Focus Before frame; Tab through Toggle iframe popover, Inside iframe popover, then After frame. Final Tab closes the popup without returning focus.
Portal hover Hover the trigger, then Portalled hover content. Focus that button by keyboard and Tab with the pointer still. After portalled hover content receives focus; both panels stay visible until pointer leave.
Trigger Portal Focus Portalled trigger control, press Enter, then Tab once. Popup closes; Outside shadow sibling keeps focus.

Fixtures: packages/react-components/react-headless-components-preview/stories/src/Popover/ (PopoverOpenOnHover, PopoverInFrame, PopoverHoverWithPortal, PopoverTriggerPortal).

Verified 26 October 2026 in Chrome 155 at 57963a1093; test consolidation preserved production behavior; both Portal stories were rechecked in Chrome 155 at 9cde4434ae after their SSR/React 17 compatibility repair. Baselines 92e88b4e9e (first two stories) and e9260d0c3f (Portal stories) respectively hid hovered content or missed dismissal. Baseline checks used component-source bundles in memory, not historical Storybook builds. Evidence covers browser focus/visibility, not screen-reader speech.

…t dismissal

Preserve destination focus when a non-modal Popover's logical focus boundary is exited. Keep the behavior opt-in and honor controlled state, native closing, and existing modal semantics.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-charts
AreaChart
402.942 kB
125.854 kB
402.933 kB
125.855 kB
-9 B
1 B
react-charts
DeclarativeChart
756.223 kB
221.658 kB
756.214 kB
221.659 kB
-9 B
1 B
react-charts
DonutChart
313.421 kB
96.687 kB
313.412 kB
96.688 kB
-9 B
1 B
react-charts
FunnelChart
304.836 kB
93.372 kB
304.827 kB
93.373 kB
-9 B
1 B
react-charts
GanttChart
385.85 kB
120.344 kB
385.84 kB
120.344 kB
-10 B
react-charts
GaugeChart
313.382 kB
96.231 kB
313.373 kB
96.234 kB
-9 B
3 B
react-charts
GroupedVerticalBarChart
394.163 kB
123.176 kB
394.154 kB
123.176 kB
-9 B
react-charts
HeatMapChart
388.057 kB
121.294 kB
388.048 kB
121.295 kB
-9 B
1 B
react-charts
HorizontalBarChart
293.131 kB
89.081 kB
293.122 kB
89.081 kB
-9 B
react-charts
Legends
232.566 kB
69.71 kB
232.556 kB
69.71 kB
-10 B
react-charts
LineChart
414.183 kB
129.026 kB
414.174 kB
129.026 kB
-9 B
react-charts
PolarChart
341.319 kB
106.588 kB
341.31 kB
106.588 kB
-9 B
react-charts
SankeyChart
209.067 kB
67.203 kB
209.058 kB
67.203 kB
-9 B
react-charts
ScatterChart
393.396 kB
123.028 kB
393.387 kB
123.028 kB
-9 B
react-charts
VerticalBarChart
430.382 kB
128.028 kB
430.373 kB
128.03 kB
-9 B
2 B
react-charts
VerticalStackedBarChart
399.949 kB
124.471 kB
399.94 kB
124.47 kB
-9 B
-1 B
react-combobox
Combobox (including child components)
137.042 kB
44.29 kB
137.032 kB
44.287 kB
-10 B
-3 B
react-combobox
Dropdown (including child components)
135.723 kB
43.711 kB
135.713 kB
43.711 kB
-10 B
react-components
react-components: Accordion, Button, FluentProvider, Image, Menu, Popover
223.278 kB
67.379 kB
223.268 kB
67.379 kB
-10 B
react-components
react-components: entire library
1.283 MB
322.23 kB
1.283 MB
322.229 kB
-9 B
-1 B
react-datepicker-compat
DatePicker Compat
216.641 kB
64.398 kB
216.625 kB
64.408 kB
-16 B
10 B
react-headless-components-preview
react-headless-components-preview: entire library
269.204 kB
80.184 kB
272.187 kB
81.389 kB
2.983 kB
1.205 kB
react-headless-components-preview
@fluentui/react-headless-components-preview/teaching-popover
33.766 kB
11.09 kB
37.138 kB
12.501 kB
3.372 kB
1.411 kB
react-menu
Menu (including children components)
156.704 kB
49.751 kB
156.694 kB
49.751 kB
-10 B
react-menu
Menu (including selectable components)
159.869 kB
50.385 kB
159.859 kB
50.381 kB
-10 B
-4 B
react-popover
Popover
122.078 kB
39.348 kB
122.068 kB
39.35 kB
-10 B
2 B
react-portal
Portal
13.959 kB
5.447 kB
14.066 kB
5.464 kB
107 B
17 B
react-tag-picker
@fluentui/react-tag-picker - package
171.164 kB
53.355 kB
171.154 kB
53.356 kB
-10 B
1 B
react-timepicker-compat
TimePicker
139.754 kB
45.561 kB
139.744 kB
45.561 kB
-10 B
react-toast
Toast (including Toaster)
90.483 kB
28.281 kB
90.474 kB
28.281 kB
-9 B
react-tooltip
Tooltip
54.989 kB
19.528 kB
54.979 kB
19.529 kB
-10 B
1 B
Unchanged fixtures
Package & Exports Size (minified/GZIP)
global-context
createContext
510 B
326 B
global-context
createContextSelector
531 B
334 B
keyboard-key
keyboard-key package
3.927 kB
1.99 kB
keyboard-keys
Multiple keyCodes
50 B
70 B
keyboard-keys
Multiple keys
87 B
94 B
keyboard-keys
Single key
44 B
64 B
keyboard-keys
Single keyCode
39 B
59 B
priority-overflow
createOverflowManager
5.416 kB
2.191 kB
react
ActivityItem
71.827 kB
23.603 kB
react
Announced
39.065 kB
13.523 kB
react
Autofill
15.557 kB
4.803 kB
react
Breadcrumb
201.081 kB
59.91 kB
react
Button
194.713 kB
56.19 kB
react
ButtonGrid
179.546 kB
54.199 kB
react
Calendar
121.593 kB
37.09 kB
react
Callout
84.756 kB
27.836 kB
react
Check
53.774 kB
18.079 kB
react
Checkbox
60.527 kB
20.13 kB
react
ChoiceGroup
66.038 kB
21.703 kB
react
ChoiceGroupOption
59.333 kB
19.594 kB
react
Coachmark
93.132 kB
29.567 kB
react
Color
7.94 kB
3.172 kB
react
ColorPicker
135.394 kB
42.386 kB
react
ComboBox
250.892 kB
71.805 kB
react
CommandBar
202.143 kB
59.685 kB
react
ContextualMenu
154.579 kB
47.83 kB
react
DatePicker
183.523 kB
56.145 kB
react
DateTimeUtilities
5.447 kB
1.917 kB
react
DetailsList
230.308 kB
66.152 kB
react
Dialog
210.376 kB
62.633 kB
react
Divider
20.182 kB
7.074 kB
react
DocumentCard
216.129 kB
63.993 kB
react
DragDrop
8.546 kB
2.789 kB
react
DraggableZone
34.867 kB
11.718 kB
react
Dropdown
233.381 kB
68.269 kB
react
ExtendedPicker
97.386 kB
28.087 kB
react
Fabric
42.305 kB
14.594 kB
react
Facepile
209.694 kB
62.698 kB
react
FloatingPicker
241.15 kB
68.562 kB
react
FocusTrapZone
17.462 kB
6.12 kB
react
FocusZone
55.696 kB
17.674 kB
react
Grid
179.546 kB
54.199 kB
react
GroupedList
135.516 kB
40.954 kB
react
GroupedListV2
123.14 kB
38.026 kB
react
HoverCard
97.22 kB
30.948 kB
react
Icon
52.459 kB
17.507 kB
react
Icons
66.918 kB
24.615 kB
react
Image
47.469 kB
15.914 kB
react
Keytip
81.786 kB
26.887 kB
react
KeytipData
14.546 kB
4.828 kB
react
KeytipLayer
103.529 kB
32.149 kB
react
Keytips
106.3 kB
33.156 kB
react
Label
38.911 kB
13.484 kB
react
Layer
48.647 kB
16.599 kB
react
Link
40.245 kB
13.906 kB
react
List
39.953 kB
12.657 kB
react
MarqueeSelection
75.078 kB
22.66 kB
react
MessageBar
189.694 kB
56.635 kB
react
Modal
94.148 kB
30.451 kB
react
Nav
187.163 kB
56.028 kB
react
OverflowSet
33.922 kB
11.493 kB
react
Overlay
41.474 kB
14.324 kB
react
Panel
200.622 kB
59.618 kB
react
Persona
115.043 kB
36.722 kB
react
PersonaCoin
115.043 kB
36.722 kB
react
PersonaPresence
58.644 kB
19.613 kB
react
Pickers
298.149 kB
83.358 kB
react
Pivot
188.02 kB
56.764 kB
react
Popup
12.427 kB
4.226 kB
react
Positioning
23.45 kB
7.878 kB
react
PositioningContainer
73.984 kB
23.94 kB
react
ProgressIndicator
40.064 kB
13.768 kB
react
Rating
82.626 kB
26.36 kB
react
Fluent UI React (entire library)
1.018 MB
283.771 kB
react
ResizeGroup
13.467 kB
4.42 kB
react
ResponsiveMode
8.271 kB
3.006 kB
react
ScrollablePane
56.088 kB
17.955 kB
react
SearchBox
187.934 kB
56.206 kB
react
SelectableOption
927 B
479 B
react
SelectedItemsList
231.646 kB
67.506 kB
react
Selection
43.019 kB
12.515 kB
react
Separator
35.952 kB
12.359 kB
react
Shimmer
49.795 kB
16.486 kB
react
ShimmeredDetailsList
241.04 kB
68.863 kB
react
Slider
58.19 kB
19.443 kB
react
SpinButton
191.6 kB
57.301 kB
react
Spinner
42.344 kB
14.701 kB
react
Stack
42.643 kB
14.594 kB
react
Sticky
33.164 kB
10.726 kB
react
Styling
46.665 kB
15.362 kB
react
SwatchColorPicker
189.899 kB
57.734 kB
react
TeachingBubble
204.91 kB
60.62 kB
react
Text
37.475 kB
13.004 kB
react
TextField
81.327 kB
25.554 kB
react
Theme
44.125 kB
14.405 kB
react
ThemeGenerator
12.525 kB
4.15 kB
react
TimePicker
240.706 kB
69.592 kB
react
Toggle
46.766 kB
16.205 kB
react
Tooltip
87.56 kB
28.389 kB
react
Utilities
83.437 kB
25.4 kB
react
Viewport
24.462 kB
7.84 kB
react
WeeklyDayPicker
101.844 kB
31.918 kB
react
WindowProvider
1.262 kB
614 B
react-accordion
Accordion (including children components)
87.834 kB
27.741 kB
react-aria
ARIA - useARIAButtonProps
1.35 kB
631 B
react-aria
ARIA - AriaLiveAnnouncer
3.259 kB
1.498 kB
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-badge
Badge
24.49 kB
7.925 kB
react-badge
CounterBadge
25.212 kB
8.184 kB
react-badge
PresenceBadge
25.012 kB
9.105 kB
react-breadcrumb
@fluentui/react-breadcrumb - package
103.23 kB
29.071 kB
react-button
Button
34.065 kB
9.04 kB
react-button
CompoundButton
40.945 kB
10.352 kB
react-button
MenuButton
39.729 kB
10.713 kB
react-button
SplitButton
49.148 kB
12.471 kB
react-button
ToggleButton
54.14 kB
11.256 kB
react-calendar-compat
Calendar Compat
142.719 kB
40.558 kB
react-calendar-preview
Calendar
159.337 kB
46.707 kB
react-card
Card - All
93.139 kB
27.125 kB
react-card
Card
85.734 kB
25.241 kB
react-card
CardFooter
13.021 kB
5.17 kB
react-card
CardHeader
15.568 kB
6.015 kB
react-card
CardPreview
13.099 kB
5.282 kB
react-charting
AreaChart
305.604 kB
96.064 kB
react-charting
ChartHoverCard
37.583 kB
12.898 kB
react-charting
DeclarativeChart
682.303 kB
194.265 kB
react-charting
DonutChart
204.722 kB
64.446 kB
react-charting
GanttChart
287.668 kB
90.971 kB
react-charting
GaugeChart
198.031 kB
61.913 kB
react-charting
GroupedVerticalBarChart
297.52 kB
93.326 kB
react-charting
HeatMapChart
288.382 kB
90.725 kB
react-charting
HorizontalBarChart
127.789 kB
40.246 kB
react-charting
HorizontalBarChartWithAxis
298.841 kB
93.377 kB
react-charting
Legends
152.339 kB
46.989 kB
react-charting
LineChart
335.132 kB
103.104 kB
react-charting
MultiStackedBarChart
182.884 kB
55.982 kB
react-charting
PieChart
135.373 kB
42.885 kB
react-charting
PolarChart
236.069 kB
74.906 kB
react-charting
SankeyChart
158.995 kB
49.787 kB
react-charting
ScatterChart
291.625 kB
92.346 kB
react-charting
Sparkline
88.444 kB
29.993 kB
react-charting
StackedBarChart
176.459 kB
53.543 kB
react-charting
TreeChart
86.064 kB
27.233 kB
react-charting
VerticalBarChart
308.514 kB
95.448 kB
react-charting
VerticalStackedBarChart
305.607 kB
95.128 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-color-picker
ColorArea
27.778 kB
10.463 kB
react-color-picker
ColorPicker
12.913 kB
5.244 kB
react-color-picker
ColorSlider
22.818 kB
9.023 kB
react-components
react-components: all base hooks
219.615 kB
68.539 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-divider
Divider
16.488 kB
5.964 kB
react-field
Field
23.331 kB
8.683 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-image
Image
13.855 kB
5.586 kB
react-input
Input
26.594 kB
8.782 kB
react-jsx-runtime
Classic Pragma
1.282 kB
613 B
react-jsx-runtime
JSX Dev Runtime
2.137 kB
988 B
react-jsx-runtime
JSX Runtime
2.134 kB
948 B
react-label
Label
13.201 kB
5.31 kB
react-link
Link
16.77 kB
6.61 kB
react-list
List
71.03 kB
21.795 kB
react-list
ListItem
95.718 kB
29.156 kB
react-message-bar
MessageBar (all components)
26.349 kB
9.34 kB
react-motion
@fluentui/react-motion - createMotionComponent()
4.269 kB
1.864 kB
react-motion
@fluentui/react-motion - createPresenceComponent()
6.001 kB
2.482 kB
react-motion
@fluentui/react-motion - PresenceGroup
1.715 kB
816 B
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
usePositioning
29.156 kB
10.251 kB
react-positioning
useSafeZoneArea
13.461 kB
5.425 kB
react-progress
ProgressBar
20.566 kB
7.98 kB
react-provider
FluentProvider
20.836 kB
8.049 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-spinner
Spinner
23.962 kB
7.926 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-teaching-popover
TeachingPopover
97.048 kB
30.59 kB
react-text
Text - Default
15.542 kB
6.022 kB
react-text
Text - Wrappers
18.706 kB
6.343 kB
react-textarea
Textarea
24.959 kB
9.052 kB
react-theme
Single theme token import
69 B
89 B
react-theme
Teams: all themes
37.967 kB
7.989 kB
react-theme
Teams: Light theme
20.797 kB
5.863 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
react-utilities
SSRProvider
182 B
160 B
🤖 This report was generated against c7b45497721c65bf274f790bfa5f4d87e56710bb

@github-actions

Copy link
Copy Markdown

Pull request demo site: URL

Make non-modal focus-exit dismissal built-in accessibility behavior rather than a consumer opt-in. Remove the proposed public API additions and cover default TeachingPopover and InfoLabel behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
@PaulGMardling Paul Mardling (PaulGMardling) changed the title feat(react-headless-components-preview): add opt-in Popover focus-exit dismissal fix(react-headless-components-preview): dismiss Popover on focus exit by default Oct 19, 2026
…tion

Preserve logical React portal focus through external shadow roots, retain native listeners across commits, and detect confirmed iframe focus exits without treating window blur alone as dismissal. Add unit and real-browser regressions while keeping the public API unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
…ship

Classify the live focus destination after Portal layout ownership settles, observe both trigger and surface portal roots, and retain bounded frame observation with direct same-origin events. Preserve native close intent through concurrent content updates and add native-browser and cleanup regressions. Keep the public API unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
…root chains

Observe every shadow ancestor for owned React focus, including nested closed roots. Cover whole-Popover and Fluent Portal nesting plus the approved bounded opaque-frame fallback without mixing InfoLabel changes into this branch.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
…ycle

Preserve native-close focus ownership through content replacement, resolve owned focus across accessible iframe chains, and retire navigated document observers safely. Guard reentrant unmounts against stale observations and resource allocation while retaining cached-document subscriptions for Back/Forward restoration. Add native browser and unit regressions without changing the public API.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
@PaulGMardling
Paul Mardling (PaulGMardling) marked this pull request as ready for review October 20, 2026 16:00
Keep master's released dependency versions and align the test-only Portal dependency with version 9.8.17. Preserve the existing Popover focus engine and public API reports.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
Normalize the test-only Portal dependency, close native state before releasing the surface in legacy React roots, and compact private observation state with one scoped frame sampler. Preserve the existing public API and 10% bundle budget.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
…rame focus

Keep hover-triggered content visible on keyboard focus exit while its trigger or surface remains hovered. Observe reachable same-origin ancestor documents and resolve the live focused frame chain, excluding embedding-only frames from sampling while retaining ancestor-portal opaque transitions. Add native controlled-state regressions and runnable Storybook examples without expanding the public API or bundle budget.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
Track live owned pointer targets across Portal content and invalidate removed hover sources. Cache trigger focus passively while closed so opening observes shadow roots before the first exit, including StrictMode replay. Add controlled/native regressions and runnable stories while preserving the public API, close lifecycle, and existing bundle budget.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
Share React-only fixtures and replace redundant mode permutations with focused boundary coverage. Preserve native lifecycle, iframe, hover, shadow-root, and controlled-state regressions without changing production behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
Move boundary browser coverage into PopoverFocus and frame observation units into the existing Popover suite. Remove three test files without removing test cases or changing production code.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
Keep one example export per story file for SSR discovery and render the unowned shadow sibling into an element rather than directly into a ShadowRoot. Preserve story IDs and keyboard reproduction behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 44bec1f8-d9c2-4333-a285-7270b37fe5da
@PaulGMardling

Copy link
Copy Markdown
Contributor Author

Downstream Modern integration draft: https://dev.azure.com/office/Office/_git/1JS/pullrequest/5905914 (internal access required). This adds regression coverage and a native-keyboard reproduction for 39630; it does not yet deliver the runtime fix.

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant