Repository navigation
fix(react-headless-components-preview): recover TeachingPopover focus when a navigation button is hidden - #36989
Open
Paul Mardling (PaulGMardling) wants to merge 7 commits into
Conversation
Expose committed boundary state and add opt-in boundary hiding with explicit footer focus recovery. Preserve default behavior and cover navigation, controlled state, focus ownership, and ref forwarding. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Pull request demo site: URL |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve consumer-controlled visibility and remove the boundary-hiding API and styled package changes. Recover after sibling refs reattach and clear stale focus ownership, with focused regression coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use mount-safe focus callbacks and shadow-aware ownership checks. Replace the forbidden Tabster runtime with a private availability check that preserves programmatic focusability, and cover the reported regressions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
📊 Bundle size reportUnchanged fixtures
|
Set the inert attribute through a ref so older React versions do not omit the fixture's boolean attribute. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Retain callback-ref cleanup on replacement and unmount without changing legacy null-detachment behavior. Respect explicit focus on the carousel shadow host and cover both open and closed roots. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Recognize content-visibility hidden ancestors and closed details while preserving the first visible summary. Cover hidden recovery destinations and preserve programmatic focus behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Mardling (PaulGMardling)
marked this pull request as ready for review
October 26, 2026 16:06
This branch has not been deployed
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.

Previous Behavior
The downstream Fluent UI Modern Feature Tour in 1JS hides Previous on its first page. Navigating 2 → 1 can leave keyboard focus on the document body instead of an available tour control.
New Behavior
Recover focus to the opposite footer navigation button when the focused button becomes unavailable during a committed update. Ordinary navigation retains focus, and deliberate focus changes are respected.
This is internal to
react-headless-components-preview: no new public props, no changes to styled TeachingPopover, and consumers still control visibility. Includes controlled-state, shadow-root, ref-cleanup, and hidden-ancestor regressions.Verification (2026-10-26):
yarn nx run react-headless-components-preview:test --runInBand --skipNxCache— passed: 90 suites / 1,341 tests.yarn nx run-many --targets=build,lint,type-check --projects=react-headless-components-preview --excludeTaskDependencies --parallel=1— passed. Current CI, including React-version integration, bundle isolation and bundle size, is green.:empty { visibility: hidden }loses focus before the fix and recovers to Next with it. Normal 3 → 2 navigation retains Previous focus; Tab/Shift+Tab passes in light DOM and open/closed shadow roots. This is not an installed downstream-release test; Narrator/NVDA speech remains unverified.Reproduction: start a three-page carousel on page 3, with consumer CSS hiding empty Previous content. Focus Previous and activate twice: 3 → 2 must retain Previous focus; 2 → 1 must focus Next when Previous hides. Shift+Tab must skip the hidden control.
The runnable regression is
packages/react-components/react-headless-components-preview/library/src/components/TeachingPopover/TeachingPopoverCarouselFooter/TeachingPopoverCarouselFooter.test.tsx(run with the test command above; Node 22 and installed repository dependencies required). The Chrome before/after comparison substituted the original hook/renderer into the same dependency build, not a separate full build. A durable interactive browser walkthrough is still outstanding.Screenshots omitted: UI-only images would not establish focus order or spoken output; keyboard and focus assertions are the relevant evidence. Accessibility reference: WCAG 2.4.3 Focus Order.
Related Issue(s)
Azure DevOps links require the appropriate Microsoft access. This PR addresses upstream focus recovery, not the entire downstream announcement issue.
Integration: the consumer can keep its public hook/renderer composition and CSS visibility policy without a focus adapter or new public API. The fix must be released and adopted downstream before installed-package verification; announcement/content and scrolling work remain separate.