Add reset button to BackgroundControlsPanel#71928
Conversation
|
Size Change: +189 B (+0.01%) Total Size: 1.95 MB
ℹ️ View Unchanged
|
t-hamano
left a comment
There was a problem hiding this comment.
Thanks for the PR!
The reset button works as expected, but the focus management is a bit complicated. This is because this UI renders different components based on whether an image is applied or not. So the approach we've been using so far, adding a ref to the dropdown button and focusing it, won't work.
This component has code that uses window.requestAnimationFrame to return focus to the toggle button when the image is reset. Using this, we could change it to look like this:
diff --git a/packages/block-editor/src/components/background-image-control/index.js b/packages/block-editor/src/components/background-image-control/index.js
index 0b0860079f..8b37a1d401 100644
--- a/packages/block-editor/src/components/background-image-control/index.js
+++ b/packages/block-editor/src/components/background-image-control/index.js
@@ -58,6 +58,24 @@ const BACKGROUND_POPOVER_PROPS = {
};
const noop = () => {};
+/**
+ * Focuses the toggle button.
+ * @param {Object} containerRef - ref object containing current element
+ */
+const focusToggleButton = ( containerRef ) => {
+ // Use requestAnimationFrame to ensure DOM updates are complete
+ window.requestAnimationFrame( () => {
+ const [ toggleButton ] = focus.tabbable.find( containerRef?.current );
+ if ( ! toggleButton ) {
+ return;
+ }
+ // Focus the toggle button and close the dropdown menu.
+ // This ensures similar behaviour as to selecting an image, where the dropdown is
+ // closed and focus is redirected to the dropdown toggle button.
+ toggleButton.focus();
+ } );
+};
+
/**
* Get the help text for the background size control.
*
@@ -184,8 +202,8 @@ function BackgroundControlsPanel( {
onToggle: onToggleCallback = noop,
hasImageValue,
onReset,
+ containerRef,
} ) {
- const backgroundImageDropdownButtonRef = useRef( undefined );
if ( ! hasImageValue ) {
return;
}
@@ -205,7 +223,6 @@ function BackgroundControlsPanel( {
'aria-label': __(
'Background size, position and repeat options.'
),
- ref: backgroundImageDropdownButtonRef,
isOpen,
};
return (
@@ -227,11 +244,11 @@ function BackgroundControlsPanel( {
icon={ resetIcon }
onClick={ () => {
onReset();
+ // Close the dropdown and focus the toggle button.
if ( isOpen ) {
onToggle();
- // Return focus to parent button.
- backgroundImageDropdownButtonRef.current?.focus();
}
+ focusToggleButton( containerRef );
} }
/>
) }
@@ -342,7 +359,7 @@ function BackgroundImageControls( {
);
setIsUploading( false );
// Close the dropdown and focus the toggle button.
- closeAndFocus();
+ focusToggleButton( containerRef );
};
// Drag and drop callback, restricting image to one.
@@ -360,22 +377,6 @@ function BackgroundImageControls( {
const hasValue = hasBackgroundImageValue( style );
- const closeAndFocus = () => {
- // Use requestAnimationFrame to ensure DOM updates are complete
- window.requestAnimationFrame( () => {
- const [ toggleButton ] = focus.tabbable.find(
- containerRef?.current
- );
- if ( ! toggleButton ) {
- return;
- }
- // Focus the toggle button and close the dropdown menu.
- // This ensures similar behaviour as to selecting an image, where the dropdown is
- // closed and focus is redirected to the dropdown toggle button.
- toggleButton.focus();
- } );
- };
-
const onRemove = () =>
onChange(
setImmutably( style, [ 'background' ], {
@@ -413,14 +414,14 @@ function BackgroundImageControls( {
) }
onError={ onUploadError }
onReset={ () => {
- closeAndFocus();
+ focusToggleButton( containerRef );
onResetImage();
} }
>
{ canRemove && (
<MenuItem
onClick={ () => {
- closeAndFocus();
+ focusToggleButton( containerRef );
onRemove();
onRemoveImage();
} }
@@ -737,6 +738,7 @@ export default function BackgroundImagePanel( {
onToggle={ setIsDropDownOpen }
hasImageValue={ hasImageValue }
onReset={ resetBackground }
+ containerRef={ containerRef }
>
<VStack spacing={ 3 } className="single-column">
<BackgroundImageControlsHere's an overview of the approach:
- Pass
containerRefto theBackgroundControlsPanelcomponent. - Using
containerRefas the starting point, create a function for the logic to focus the toggle button. - Use that function to focus the toggle button when the reset button in the
BackgroundControlsPanelis pressed.
In my testing, this approach seems to work well.
|
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. |
|
Thanks a lot for the review, Aki! Great catch. I’ve applied your suggestions and the focus is working well on my end too. |
|
Flaky tests detected in cdfd320. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/18075913305
|
packages/block-editor/src/components/background-image-control/style.scss
Outdated
Show resolved
Hide resolved
…style.scss Co-authored-by: Aki Hamano <[email protected]>
* Add reset button for the background image control. * Apply suggestions from code review. * Update packages/block-editor/src/components/background-image-control/style.scss Co-authored-by: Aki Hamano <[email protected]> --------- Co-authored-by: juanfra <[email protected]> Co-authored-by: t-hamano <[email protected]>
What?
Adding a reset button to the background image control.
Why?
To add cohesion with how the colors controls work, making it easier to unset a background image without having to open a menu.
This is a follow up #41866
Testing Instructions
Screenshots or screencast
background-control-reset.mp4