diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3674084f38e9e3..7ad6becdb8aef6 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,7 @@ - `ToggleGroupControl`: Improve controlled value detection ([#57770](https://github.com/WordPress/gutenberg/pull/57770)). - `Tooltip`: Improve props forwarding to children of nested `Tooltip` components ([#57878](https://github.com/WordPress/gutenberg/pull/57878)). - `Tooltip`: revert prop types to only accept component-specific props ([#58125](https://github.com/WordPress/gutenberg/pull/58125)). +- `Button`: prevent the component from trashing and re-creating the HTML element ([#56490](https://github.com/WordPress/gutenberg/pull/56490)). ### Experimental diff --git a/packages/components/src/button/index.tsx b/packages/components/src/button/index.tsx index bd91de2ec2e83e..966075dd6e2b9a 100644 --- a/packages/components/src/button/index.tsx +++ b/packages/components/src/button/index.tsx @@ -195,9 +195,9 @@ export function UnforwardedButton( const shouldShowTooltip = ! trulyDisabled && // An explicit tooltip is passed or... - ( ( showTooltip && label ) || + ( ( showTooltip && !! label ) || // There's a shortcut or... - shortcut || + !! shortcut || // There's a label and... ( !! label && // The children are empty and... @@ -249,40 +249,28 @@ export function UnforwardedButton( ); - // Convert legacy `position` values to be used with the new `placement` prop - let computedPlacement; - // if `tooltipPosition` is defined, compute value to `placement` - if ( tooltipPosition !== undefined ) { - computedPlacement = positionToPlacement( tooltipPosition ); - } - - if ( ! shouldShowTooltip ) { - return ( - <> - { element } - { describedBy && ( - - { describedBy } - - ) } - - ); - } - - return ( - <> - - { element } - + : label, + shortcut, + placement: + tooltipPosition && + // Convert legacy `position` values to be used with the new `placement` prop + positionToPlacement( tooltipPosition ), + } + : {}; + + return ( + <> + { element } { describedBy && ( { describedBy } diff --git a/packages/components/src/button/test/index.tsx b/packages/components/src/button/test/index.tsx index 345ae3813fe067..9b719f23a923f1 100644 --- a/packages/components/src/button/test/index.tsx +++ b/packages/components/src/button/test/index.tsx @@ -197,6 +197,43 @@ describe( 'Button', () => { ).not.toBeInTheDocument(); } ); + it( 'should not trash the rendered HTML elements when toggling between showing and not showing a tooltip', async () => { + const user = userEvent.setup(); + + const { rerender } = render( + + ); + + const button = screen.getByRole( 'button', { + name: 'Button label', + } ); + + expect( button ).toBeVisible(); + + await user.tab(); + + expect( button ).toHaveFocus(); + + // Re-render the button, but this time change the settings so that it + // shows a tooltip. + rerender( + + ); + + // The same button element that we referenced before should still be + // in the document and have focus. + expect( button ).toHaveFocus(); + + // Re-render the button, but stop showing a tooltip. + rerender( ); + + // The same button element that we referenced before should still be + // in the document and have focus. + expect( button ).toHaveFocus(); + } ); + it( 'should add a disabled prop to the button', () => { render( - + ); }