Repository navigation
Fix keyboard focus staying on a removed element when an overlay popup or flyout closes - #22345
Merged
MrJul merged 3 commits intoOct 7, 2026
Merged
Conversation
When a focus scope is removed or hidden while its focused element has the focus and the root scope's focused element can't be focused (e.g. a button disabled while its command waits for a choice in a flyout), the keyboard focus stays on the removed or hidden element. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e restored Focus(null) leaves the focus alone when the focused element is in another focus scope than the focus root, but a removed or hidden element also passes that check. Only apply it while the focused element is attached and visible. Fixes AvaloniaUI#22342 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NuGet packagesThe packages for this pull request have been published (workflow run):
|
Member
|
I've added a new test to I think it's important to test the real scenario here, as mocked services aren't always enough when focus and multiple window interactions are involved. |
MrJul
enabled auto-merge
October 7, 2026 16:14
MrJul
added a commit
that referenced
this pull request
Oct 9, 2026
… or flyout closes (#22345) * Add failing test for focus staying on a removed or hidden element When a focus scope is removed or hidden while its focused element has the focus and the root scope's focused element can't be focused (e.g. a button disabled while its command waits for a choice in a flyout), the keyboard focus stays on the removed or hidden element. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Clear focus when the focused element is removed or hidden and can't be restored Focus(null) leaves the focus alone when the focused element is in another focus scope than the focus root, but a removed or hidden element also passes that check. Only apply it while the focused element is attached and visible. Fixes #22342 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add popup tests with actual focus services --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
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.
What does the pull request do?
Follow-up to #22113
When an overlay popup or flyout closes and the element that had focus before it can't be focused (e.g. the button that opened it, disabled while its command waits for the choice), the keyboard focus stays on the removed element: Tab/Shift+Tab do nothing and Enter/Space click the removed button again. This mainly affects browser apps, where popups are always overlays.
What is the current behavior?
See #22342 for a small example with a video and code to reproduce
Additional context
Why closing a native popup looks fine (according to claude) :
Popupremoves the content first and hides the popup window afterwards. Hiding it runs InputElement's IsVisible handler, and the popup window still has a stale IsKeyboardFocusWithin = true, so it calls Focus(null) a second time. The first call had already set _focusRoot = null, so the second one skips the restore and clears focus. It's an accidental rescue.What is the updated/expected behavior with this PR?
After the popup/flyout with a focused element closes, and focus cannot be restored, focus is cleared
How was the solution implemented (if it's not obvious)?
After restoring the focus fails, we do not clear the focus ONLY IF the currently focused element is still visible (in addition to other checks that were in place before this PR of course)
Checklist
Added XML documentation to any related classes?Consider submitting a PR to https://github.com/AvaloniaUI/avalonia-docs with user documentationBreaking changesObsoletions / DeprecationsFixed issues
Fixes #22342