diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index a2dc5d34472580..258e33c86b2744 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Bug Fixes
+
+- `ToggleGroupControl`: Don't set value on focus after a reset ([#66151](https://github.com/WordPress/gutenberg/pull/66151)).
+
## 28.8.6 (2024-10-14)
### Bug Fixes
diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx
index d7b4824fce4de8..168e8f498958b5 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 3b33d75ca7c229..8b401423742e14 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
@@ -143,10 +143,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 876e61944dd5a2..7393ea725dbc5b 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';
/**
@@ -72,6 +72,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(
() =>
( {