Repository navigation
fix: focus stealing on render of Menu Trigger button - #4970
SleeplessByte wants to merge 1 commit into
Conversation
When the menu is rendered, the portal is updated async. This steals the focus as `hide()` focuses the button. Instead only focus when requested, for example when the menu was visible and hiding should focus the trigger.
|
FYI this also auto scrolls any scroll container if there is a menu somewhere lower on the page :') |
There was a problem hiding this comment.
🟡 Changes recommended
Rapid open-close transitions can still leave focus on a hidden menu, and regression coverage is missing.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Prevents Menu from stealing focus when initially rendered hidden.
Changes:
- Makes trigger focusing optional during hide.
- Focuses the trigger only after a previously rendered menu closes.
File summaries
| File | Description |
|---|---|
src/components/Menu/Menu.tsx |
Adjusts focus restoration during menu hiding. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| if (!display) { | ||
| hide(); | ||
| hide(prevRendered.current); |
There was a problem hiding this comment.
If the animation is interrupted, the callback should not run. If the callback still runs on an interrupted animation, that's a separate bug unrelated to this PR and should be solved in a different PR.
| setRendered(false); | ||
| prevRendered.current = false; | ||
| focusFirstDOMNode(anchorRef.current); | ||
| if (focus) { focusFirstDOMNode(anchorRef.current) }; |
|
|
||
| if (!display) { | ||
| hide(); | ||
| hide(prevRendered.current); |
There was a problem hiding this comment.
I'll leave this one for someone at the company who can take over this PR. It's impossible to run this repository on my windows machine, so cannot run the tests locally nor develop.
satya164
left a comment
There was a problem hiding this comment.
thanks for the PR. can you fix the CI errors and target the PR to the 5.0 branch?
| setRendered(false); | ||
| prevRendered.current = false; | ||
| focusFirstDOMNode(anchorRef.current); | ||
| if (focus) { focusFirstDOMNode(anchorRef.current) }; |
There was a problem hiding this comment.
on a quick open and close, the focus could be lost:
- menu is opened
- then closed before open animation finishes
- both
hideandshowanimation callbacks run - since
prevRendered.currentis read beforehidestarts and stops the animation, it won't reflect the change toprevRendered.current = truein theshowcallback, using old value forshow
we should check for finished in the animation callbacks to avoid changing focus when animation is interrupted.
There was a problem hiding this comment.
See my comment on the AI review regarding the +quick open and close+.
I currently don't have any bandwidth to update this PR, but I left "edits allowed from maintainers" checked, so someone can take it over.
When the menu is rendered, the portal is updated async. This steals the focus as
hide()focuses the button. Instead only focus when requested, for example when the menu was visible and hiding should focus the trigger.Motivation
Stealing the focus is bad for me as a keyboard user and bad for assistive technology
Test plan
Before: open any page with a menu rendered in the appbar. The focus should move automatically to the trigger button, even without opening.
After: open any page with a menu rendered in the appbar. The focus should not move automatically to the trigger button, unless the menu is opened and then closed.
Workaround before this is merged
react-native-paper-npm-5.15.3-9a600de527.patch