diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx
index b6f2d9a5be49dc..e05910245e2dca 100644
--- a/packages/components/src/toggle-group-control/test/index.tsx
+++ b/packages/components/src/toggle-group-control/test/index.tsx
@@ -2,6 +2,7 @@
* External dependencies
*/
import { render, fireEvent, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
/**
* WordPress dependencies
@@ -126,4 +127,130 @@ describe( 'ToggleGroupControl', () => {
screen.queryByText( 'Click for Sumptuous Caponata' )
).not.toBeInTheDocument();
} );
+
+ describe( 'isDeselectable', () => {
+ describe( 'isDeselectable = false', () => {
+ it( 'should not be deselectable', async () => {
+ const mockOnChange = jest.fn();
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
+
+ render(
+
+ { options }
+
+ );
+
+ const rigas = screen.getByRole( 'radio', {
+ name: 'R',
+ checked: true,
+ } );
+ await user.click( rigas );
+ expect( mockOnChange ).toHaveBeenCalledTimes( 0 );
+ } );
+
+ it( 'should not tab to next radio option', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
+
+ render(
+
+ { options }
+
+ );
+
+ const rigas = screen.getByRole( 'radio', {
+ name: 'R',
+ } );
+
+ await user.tab();
+ expect( rigas ).toHaveFocus();
+
+ await user.tab();
+ expect( rigas.ownerDocument.body ).toHaveFocus();
+ } );
+ } );
+
+ describe( 'isDeselectable = true', () => {
+ it( 'should be deselectable', async () => {
+ const mockOnChange = jest.fn();
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
+
+ render(
+
+ { options }
+
+ );
+
+ await user.click(
+ await screen.findByRole( 'button', {
+ name: 'R',
+ pressed: true,
+ } )
+ );
+ expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
+ expect( mockOnChange ).toHaveBeenCalledWith( undefined );
+ expect(
+ screen.getByRole( 'button', {
+ name: 'R',
+ pressed: false,
+ } )
+ ).toBeInTheDocument();
+ } );
+
+ it( 'should tab to the next option button', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
+
+ render(
+
+ { options }
+
+ );
+
+ await user.tab();
+ expect(
+ screen.getByRole( 'button', {
+ name: 'R',
+ pressed: true,
+ } )
+ ).toHaveFocus();
+
+ await user.tab();
+ expect(
+ screen.getByRole( 'button', {
+ name: 'J',
+ pressed: false,
+ } )
+ ).toHaveFocus();
+
+ // Focus should not move with arrow keys
+ await user.keyboard( '{ArrowLeft}' );
+ expect(
+ screen.getByRole( 'button', {
+ name: 'J',
+ pressed: false,
+ } )
+ ).toHaveFocus();
+ } );
+ } );
+ } );
} );
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 ac40cadd7dac69..e1d90fc1085a29 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
@@ -97,6 +97,7 @@ function ToggleGroupControlOptionBase(
{ isDeselectable ? (