-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Fix focus loss from unsync and edit button in navigation link inspector sidebar #72436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The unsync and edit button enables the disabled input and removes the button that was focused. This causes a focus loss. I added: - Ref for the input - Ref for knowing if we should focus on next render (we can't focus immediately, as the input is disabled and cannot receive focus) - useEffect to check if we should send focus to the input when hasUrlBinding changes
To avoid potential edge cases, I make shouldFocusURLInputRef ALWAYS get set to false when the useEffect runs. Also, only send focus if hasUrlBinding is false (input enabled)
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Size Change: +1 B (0%) Total Size: 2.08 MB
ℹ️ View Unchanged
|
|
Flaky tests detected in a2cea97. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/18596049407
|
| const lastURLRef = useRef( url ); | ||
| const dropdownMenuProps = useToolsPanelDropdownMenuProps(); | ||
| const urlInputRef = useRef(); | ||
| const shouldFocusURLInputRef = useRef( false ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is a state more appropriate than a ref here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think state would cause an additional render. Also, we don't need this as a state. It's an action we want to perform at a specific time.
If we use state, then it looks like:
- Unlink click -> setShouldFocusInput( true )
useEffect( () => {
if( shouldFocusInput ) {
urlInputRef.current.focus();
setShouldFocusInput( false ); <--- causes this setState to run again with an additional render
}
), [ shouldFocusInput, setShouldFocusInput ] );
I prefer the useEffect that doesn't cause an additional unnecessary rerender
Co-authored-by: Ben Dwyer <ben@scruffian.com>
getdave
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change works as described using a mouse and also using a keyboard.
The focus is correctly applied only when unsyncing entity bound links.
The fix is well scoped and avoids unwanted re-renders.
I appreciate the augmenting of the existing test coverage 👏
| if ( ! hasUrlBinding && shouldFocusURLInputRef.current ) { | ||
| urlInputRef.current?.focus(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be helpful to have a comment here explaining why we need the ! hasUrlBinding.
My understanding is that it's because this logic should only apply when unsyncing an existing binding (effectively when you "unlock" the Link field).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it was a defensive coding thing. Not strictly necessary, as it shouldn't happen anyways.
| const { updateBlockAttributes } = useDispatch( blockEditorStore ); | ||
|
|
||
| const editBoundLink = () => { | ||
| const unsyncBoundLink = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for renaming this 👍
| // Focus management to send focus to the URL input | ||
| // on next render after disabled state is removed. | ||
| shouldFocusURLInputRef.current = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good that we didn't try to abstract this into the unsyncBoundLink. This keeps the fix targetted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup! Wanted to keep things tidy and focused.
…or sidebar (#72436) Co-authored-by: jeryj <jeryj@git.wordpress.org> Co-authored-by: scruffian <scruffian@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org>
|
The bot is failing, I'm not sure why. https://github.com/WordPress/gutenberg/actions/runs/19265984111/job/55081805728
I've manually cherry picked this in a8932f6. |
What?
Fixes a focus loss from the inspector sidebar on navigation links when pressing the unsync and edit button
Why?
The unsync and edit button enables the disabled input and removes the button that was focused. This causes a focus loss. We need to manage focus to meet accessibility standards.
How?
Testing Instructions
Testing Instructions for Keyboard
Screenshots or screencast