diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 48113f874af3a..64e5eeb177652 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -10,6 +10,7 @@ - `Tabs`: fix skipping indication animation glitch ([#65878](https://github.com/WordPress/gutenberg/pull/65878)). - `ToggleGroupControl`: Don't autoselect option on first group focus ([#65892](https://github.com/WordPress/gutenberg/pull/65892)). - `Button`: fix `box-shadow` transition for secondary variation ([#66045](https://github.com/WordPress/gutenberg/pull/66045)). +- `ToggleGroupControl`: Don't set value on focus after a reset ([#66151](https://github.com/WordPress/gutenberg/pull/66151)). ### Deprecations diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx index d7b4824fce4de..168e8f498958b 100644 --- a/packages/components/src/toggle-group-control/test/index.tsx +++ b/packages/components/src/toggle-group-control/test/index.tsx @@ -175,6 +175,32 @@ describe.each( [ expect( radio ).not.toBeChecked(); } ); + if ( mode === 'controlled' ) { + it( 'should not set a value on focus, after the value is reset', async () => { + render( + + { options } + + ); + + expect( screen.getByRole( 'radio', { name: 'J' } ) ).toBeChecked(); + + await click( screen.getByRole( 'button', { name: 'Reset' } ) ); + + expect( + screen.getByRole( 'radio', { name: 'J' } ) + ).not.toBeChecked(); + + await press.ShiftTab(); + expect( + screen.getByRole( 'radio', { name: 'R' } ) + ).not.toBeChecked(); + expect( + screen.getByRole( 'radio', { name: 'J' } ) + ).not.toBeChecked(); + } ); + } + it( 'should render tooltip where `showTooltip` === `true`', async () => { render( diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx index b33f53dd706b5..041af1adf5e5b 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/component.tsx @@ -141,10 +141,14 @@ function ToggleGroupControlOptionBase( { + const selectedValueIsEmpty = + toggleGroupControlContext.value === null || + toggleGroupControlContext.value === ''; + // Conditions ensure that the first visible focus to a radio group // without a selected option will not automatically select the option. if ( - toggleGroupControlContext.value !== null || + ! selectedValueIsEmpty || toggleGroupControlContext.activeItemIsNotFirstItem?.() ) { toggleGroupControlContext.setValue( value ); diff --git a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx index 4481fc9f6138d..0166728dbafba 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/as-radio-group.tsx @@ -9,7 +9,7 @@ import { useStoreState } from '@ariakit/react'; * WordPress dependencies */ import { useInstanceId } from '@wordpress/compose'; -import { forwardRef, useMemo } from '@wordpress/element'; +import { forwardRef, useEffect, useMemo } from '@wordpress/element'; import { isRTL } from '@wordpress/i18n'; /** @@ -73,6 +73,13 @@ function UnforwardedToggleGroupControlAsRadioGroup( const selectedValue = useStoreState( radio, 'value' ); const setValue = radio.setValue; + // Ensures that the active id is also reset after the value is "reset" by the consumer. + useEffect( () => { + if ( selectedValue === '' ) { + radio.setActiveId( undefined ); + } + }, [ radio, selectedValue ] ); + const groupContextValue = useMemo( (): ToggleGroupControlContextProps => ( { activeItemIsNotFirstItem: () =>