diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index 9d20924dcfe610..fdeea311958938 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Bug Fixes
+
+- `CustomGradientPicker`: Add state persistence when switching between Linear and Radial Gradient ([#76595](https://github.com/WordPress/gutenberg/pull/76595)).
+
## 32.4.0 (2026-03-18)
### Bug Fixes
diff --git a/packages/components/src/custom-gradient-picker/index.tsx b/packages/components/src/custom-gradient-picker/index.tsx
index 1777f5260eb0a4..ceab70c0a82dc3 100644
--- a/packages/components/src/custom-gradient-picker/index.tsx
+++ b/packages/components/src/custom-gradient-picker/index.tsx
@@ -7,6 +7,7 @@ import { type LinearGradientNode } from 'gradient-parser';
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
+import { useRef } from '@wordpress/element';
/**
* Internal dependencies
@@ -25,8 +26,8 @@ import {
import { serializeGradient } from './serializer';
import {
DEFAULT_LINEAR_GRADIENT_ANGLE,
- HORIZONTAL_GRADIENT_ORIENTATION,
GRADIENT_OPTIONS,
+ HORIZONTAL_GRADIENT_ORIENTATION,
} from './constants';
import {
AccessoryWrapper,
@@ -70,14 +71,24 @@ const GradientTypePicker = ( {
onChange,
}: GradientTypePickerProps ) => {
const { type } = gradientAST;
+ const lastLinearOrientationAngle = useRef(
+ Number( HORIZONTAL_GRADIENT_ORIENTATION.value )
+ );
+
+ if ( type === 'linear-gradient' && gradientAST.orientation ) {
+ lastLinearOrientationAngle.current = Number(
+ gradientAST.orientation.value
+ );
+ }
const onSetLinearGradient = () => {
onChange(
serializeGradient( {
...gradientAST,
- orientation: gradientAST.orientation
- ? undefined
- : HORIZONTAL_GRADIENT_ORIENTATION,
+ orientation: {
+ type: 'angular' as const,
+ value: `${ lastLinearOrientationAngle.current }`,
+ },
type: 'linear-gradient',
} satisfies LinearGradientNode )
);
diff --git a/packages/components/src/custom-gradient-picker/test/index.tsx b/packages/components/src/custom-gradient-picker/test/index.tsx
new file mode 100644
index 00000000000000..69b32d8f1a3521
--- /dev/null
+++ b/packages/components/src/custom-gradient-picker/test/index.tsx
@@ -0,0 +1,81 @@
+/**
+ * External dependencies
+ */
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+
+/**
+ * Internal dependencies
+ */
+import CustomGradientPicker from '../';
+
+describe( 'CustomGradientPicker', () => {
+ describe( 'GradientTypePicker angle persistence', () => {
+ it( 'should restore the previous linear angle when switching from radial back to linear', async () => {
+ const user = userEvent.setup();
+ const onChange = jest.fn();
+
+ render(
+
+ );
+
+ const typeSelect = screen.getByRole( 'combobox', {
+ name: /type/i,
+ } );
+ await user.selectOptions( typeSelect, 'radial-gradient' );
+ await user.selectOptions( typeSelect, 'linear-gradient' );
+
+ // Verify the angle from before the radial switch is restored, not the default
+ const lastCall =
+ onChange.mock.calls[ onChange.mock.calls.length - 1 ][ 0 ];
+ expect( lastCall ).toContain( '125deg' );
+ } );
+
+ it( 'should use HORIZONTAL_GRADIENT_ORIENTATION when no prior linear angle exists', async () => {
+ const user = userEvent.setup();
+ const onChange = jest.fn();
+
+ // Start with a radial gradient so there is no previous linear angle in the ref
+ render(
+
+ );
+
+ const typeSelect = screen.getByRole( 'combobox', {
+ name: /type/i,
+ } );
+ await user.selectOptions( typeSelect, 'linear-gradient' );
+
+ const lastCall =
+ onChange.mock.calls[ onChange.mock.calls.length - 1 ][ 0 ];
+ expect( lastCall ).toContain( '90deg' );
+ } );
+
+ it( 'should not restore angle when switching to radial', async () => {
+ const user = userEvent.setup();
+ const onChange = jest.fn();
+
+ render(
+
+ );
+
+ const typeSelect = screen.getByRole( 'combobox', {
+ name: /type/i,
+ } );
+ await user.selectOptions( typeSelect, 'radial-gradient' );
+
+ // Radial gradients have no orientation, so deg should not appear in the output
+ const lastCall =
+ onChange.mock.calls[ onChange.mock.calls.length - 1 ][ 0 ];
+ expect( lastCall ).not.toContain( 'deg' );
+ } );
+ } );
+} );