Commit 1896acb098e for woocommerce

commit 1896acb098e4d508623cf2a3901cb88eeb9e0d42
Author: Daniel Mallory <daniel.mallory@automattic.com>
Date:   Mon Jun 8 11:58:47 2026 +0100

    Align settings UI SDK with settings card design (#65557)

    * Align settings UI SDK with settings card design

    * Add settings UI unsaved changes modal

    * Fix custom settings save navigation protection

    ---------

    Co-authored-by: Ahmed <ahmed.el.azzabi@automattic.com>

diff --git a/packages/js/settings-ui-sdk/changelog/tweak-settings-ui-card-design b/packages/js/settings-ui-sdk/changelog/tweak-settings-ui-card-design
new file mode 100644
index 00000000000..ce3e1503b8f
--- /dev/null
+++ b/packages/js/settings-ui-sdk/changelog/tweak-settings-ui-card-design
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Align Settings UI SDK rendering with the settings card design.
diff --git a/packages/js/settings-ui-sdk/src/settings-ui-page.tsx b/packages/js/settings-ui-sdk/src/settings-ui-page.tsx
index 4a6fd5db543..c44a4940dc7 100644
--- a/packages/js/settings-ui-sdk/src/settings-ui-page.tsx
+++ b/packages/js/settings-ui-sdk/src/settings-ui-page.tsx
@@ -2,7 +2,7 @@
  * External dependencies
  */
 import { Page } from '@wordpress/admin-ui';
-import { Button, Notice } from '@wordpress/components';
+import { Button, Modal, Notice } from '@wordpress/components';
 import {
 	Component,
 	createElement,
@@ -10,6 +10,7 @@ import {
 	useCallback,
 	useEffect,
 	useMemo,
+	useRef,
 	useState,
 } from '@wordpress/element';
 import { __ } from '@wordpress/i18n';
@@ -44,6 +45,10 @@ type SaveNotice = {
 	message: string;
 };

+type PendingNavigation = {
+	href: string;
+};
+
 const getInitialValues = ( schema: SettingsUISchema ): SettingsValues => {
 	const values: SettingsValues = {};

@@ -100,6 +105,92 @@ const clearLegacyFormPrompt = () => {
 	window.onbeforeunload = null;
 };

+const shouldPromptForNavigation = ( event: MouseEvent ) => {
+	if (
+		event.defaultPrevented ||
+		event.button !== 0 ||
+		event.metaKey ||
+		event.ctrlKey ||
+		event.shiftKey ||
+		event.altKey
+	) {
+		return false;
+	}
+
+	const target = event.target;
+
+	if ( ! ( target instanceof Element ) ) {
+		return false;
+	}
+
+	const link = target.closest( 'a[href]' );
+
+	if ( ! ( link instanceof HTMLAnchorElement ) ) {
+		return false;
+	}
+
+	if ( link.target && link.target !== '_self' ) {
+		return false;
+	}
+
+	return Boolean( link.href ) && link.href !== window.location.href;
+};
+
+const getNavigationHref = ( event: MouseEvent ) => {
+	const target = event.target;
+
+	if ( ! ( target instanceof Element ) ) {
+		return undefined;
+	}
+
+	const link = target.closest( 'a[href]' );
+
+	return link instanceof HTMLAnchorElement ? link.href : undefined;
+};
+
+const UnsavedChangesModal = ( {
+	isSaving,
+	onClose,
+	onDiscard,
+	onSave,
+}: {
+	isSaving: boolean;
+	onClose: () => void;
+	onDiscard: () => void;
+	onSave: () => void;
+} ) => {
+	return (
+		<Modal
+			className="wc-settings-ui__unsaved-changes-modal"
+			title={ __( 'You have unsaved changes', 'woocommerce' ) }
+			onRequestClose={ onClose }
+		>
+			<p>
+				{ __(
+					"If you leave now, your changes won't be saved.",
+					'woocommerce'
+				) }
+			</p>
+			<div className="wc-settings-ui__unsaved-changes-actions">
+				<Button variant="tertiary" onClick={ onDiscard }>
+					{ __( 'Discard', 'woocommerce' ) }
+				</Button>
+				<Button
+					variant="primary"
+					type="button"
+					name="save"
+					value={ __( 'Save', 'woocommerce' ) }
+					isBusy={ isSaving }
+					disabled={ isSaving }
+					onClick={ onSave }
+				>
+					{ __( 'Save', 'woocommerce' ) }
+				</Button>
+			</div>
+		</Modal>
+	);
+};
+
 const GroupHeader = ( { group }: { group: SettingsUIGroup } ) => {
 	const hasHeaderContent =
 		group.title || group.description || ( group.actions || [] ).length > 0;
@@ -109,17 +200,19 @@ const GroupHeader = ( { group }: { group: SettingsUIGroup } ) => {
 	}

 	return (
-		<div className="wc-settings-ui__group-header">
-			{ group.title ? <h2>{ group.title }</h2> : null }
-			{ group.description ? (
-				<div className="wc-settings-ui__group-description">
-					<RawHTML>
-						{ sanitizeSettingsHtml( group.description ) }
-					</RawHTML>
-				</div>
-			) : null }
+		<header className="wc-settings-ui__section-header">
+			<div className="wc-settings-ui__section-heading">
+				{ group.title ? <h2>{ group.title }</h2> : null }
+				{ group.description ? (
+					<div className="wc-settings-ui__section-description">
+						<RawHTML>
+							{ sanitizeSettingsHtml( group.description ) }
+						</RawHTML>
+					</div>
+				) : null }
+			</div>
 			{ group.actions && group.actions.length > 0 ? (
-				<div className="wc-settings-ui__group-actions">
+				<div className="wc-settings-ui__section-actions">
 					{ group.actions.map( ( action ) => (
 						<Button
 							key={ action.id }
@@ -133,7 +226,7 @@ const GroupHeader = ( { group }: { group: SettingsUIGroup } ) => {
 					) ) }
 				</div>
 			) : null }
-		</div>
+		</header>
 	);
 };

@@ -256,7 +349,7 @@ const ShellHeader = ( {
 	isDirty: boolean;
 	isSaving: boolean;
 	saveStrategy: SettingsUISaveStrategy;
-	onSave: () => void;
+	onSave: () => void | Promise< boolean >;
 	children: ReactNode;
 } ) => {
 	const shell = schema.shell || {};
@@ -294,22 +387,20 @@ const ShellHeader = ( {
 			</nav>
 		) : undefined;

+	const saveButtonLabel = __( 'Save', 'woocommerce' );
+
 	const actions = showSaveButton ? (
 		<Button
 			className="woocommerce-save-button"
 			variant="primary"
 			type={ saveButtonType }
 			name="save"
-			value={ __( 'Save changes', 'woocommerce' ) }
+			value={ saveButtonLabel }
 			disabled={ ! isDirty || isSaving }
 			isBusy={ isSaving }
-			onClick={
-				saveStrategy.adapter === 'form_post'
-					? clearLegacyFormPrompt
-					: onSave
-			}
+			onClick={ onSave }
 		>
-			{ __( 'Save changes', 'woocommerce' ) }
+			{ saveButtonLabel }
 		</Button>
 	) : undefined;

@@ -400,6 +491,9 @@ export const SettingsUIPage = ( {
 	);
 	const [ isSaving, setIsSaving ] = useState( false );
 	const [ saveNotice, setSaveNotice ] = useState< SaveNotice | null >( null );
+	const [ pendingNavigation, setPendingNavigation ] =
+		useState< PendingNavigation | null >( null );
+	const allowNavigationRef = useRef( false );
 	const context: SettingsFieldContext = useMemo(
 		() => ( {
 			page: page || schema.id,
@@ -423,6 +517,7 @@ export const SettingsUIPage = ( {
 		setInitialValues( nextValues );
 		setValuesState( nextValues );
 		setSaveNotice( null );
+		setPendingNavigation( null );
 	}, [ schema ] );

 	const setValue = useCallback(
@@ -435,6 +530,33 @@ export const SettingsUIPage = ( {
 		[]
 	);

+	const allowNavigation = useCallback( () => {
+		allowNavigationRef.current = true;
+		clearLegacyFormPrompt();
+	}, [] );
+
+	const submitSettingsForm = useCallback( () => {
+		allowNavigation();
+
+		const form = document.getElementById( 'mainform' );
+
+		if ( ! ( form instanceof HTMLFormElement ) ) {
+			return;
+		}
+
+		const saveButton = document.querySelector( '.woocommerce-save-button' );
+
+		if (
+			saveButton instanceof HTMLButtonElement &&
+			saveButton.form === form
+		) {
+			form.requestSubmit( saveButton );
+			return;
+		}
+
+		form.requestSubmit();
+	}, [ allowNavigation ] );
+
 	const setValues = useCallback(
 		( nextValues: Partial< SettingsValues > ) => {
 			setValuesState( ( currentValues ) => {
@@ -456,7 +578,7 @@ export const SettingsUIPage = ( {

 	const handleCustomSave = useCallback( async () => {
 		if ( saveStrategy.adapter !== 'custom' ) {
-			return;
+			return false;
 		}

 		const handlerName =
@@ -469,7 +591,7 @@ export const SettingsUIPage = ( {
 				status: 'error',
 				message: __( 'Unable to save settings.', 'woocommerce' ),
 			} );
-			return;
+			return false;
 		}

 		setIsSaving( true );
@@ -493,12 +615,14 @@ export const SettingsUIPage = ( {
 					result?.notice ||
 					__( 'Settings saved successfully.', 'woocommerce' ),
 			} );
+			return true;
 		} catch ( saveError ) {
 			const message =
 				saveError instanceof Error && saveError.message
 					? saveError.message
 					: __( 'Unable to save settings.', 'woocommerce' );
 			setSaveNotice( { status: 'error', message } );
+			return false;
 		} finally {
 			setIsSaving( false );
 		}
@@ -512,6 +636,99 @@ export const SettingsUIPage = ( {
 		values,
 	] );

+	useEffect( () => {
+		if ( ! isDirty ) {
+			return;
+		}
+
+		const handleBeforeUnload = ( event: BeforeUnloadEvent ) => {
+			if ( allowNavigationRef.current ) {
+				return;
+			}
+
+			event.preventDefault();
+			event.returnValue = '';
+		};
+
+		window.addEventListener( 'beforeunload', handleBeforeUnload );
+
+		return () => {
+			window.removeEventListener( 'beforeunload', handleBeforeUnload );
+		};
+	}, [ isDirty ] );
+
+	useEffect( () => {
+		if ( ! isDirty ) {
+			return;
+		}
+
+		const handleNavigationClick = ( event: MouseEvent ) => {
+			const target = event.target;
+
+			if (
+				! ( target instanceof Element ) ||
+				! target.closest( '.wc-settings-ui-shell' ) ||
+				! shouldPromptForNavigation( event )
+			) {
+				return;
+			}
+
+			const href = getNavigationHref( event );
+
+			if ( ! href ) {
+				return;
+			}
+
+			event.preventDefault();
+			setPendingNavigation( { href } );
+		};
+
+		document.addEventListener( 'click', handleNavigationClick, true );
+
+		return () => {
+			document.removeEventListener(
+				'click',
+				handleNavigationClick,
+				true
+			);
+		};
+	}, [ isDirty ] );
+
+	const handleDiscardNavigation = useCallback( () => {
+		if ( ! pendingNavigation ) {
+			return;
+		}
+
+		allowNavigation();
+		window.location.assign( pendingNavigation.href );
+	}, [ allowNavigation, pendingNavigation ] );
+
+	const handleSavePendingNavigation = useCallback( async () => {
+		if ( ! pendingNavigation ) {
+			return;
+		}
+
+		if ( saveStrategy.adapter === 'form_post' ) {
+			submitSettingsForm();
+			return;
+		}
+
+		if ( saveStrategy.adapter === 'custom' ) {
+			const saved = await handleCustomSave();
+
+			if ( saved ) {
+				allowNavigation();
+				window.location.assign( pendingNavigation.href );
+			}
+		}
+	}, [
+		allowNavigation,
+		handleCustomSave,
+		pendingNavigation,
+		saveStrategy.adapter,
+		submitSettingsForm,
+	] );
+
 	const visibleGroups = useMemo(
 		() =>
 			Object.values( schema.groups )
@@ -555,8 +772,20 @@ export const SettingsUIPage = ( {
 			isDirty={ isDirty }
 			isSaving={ isSaving }
 			saveStrategy={ saveStrategy }
-			onSave={ handleCustomSave }
+			onSave={
+				saveStrategy.adapter === 'form_post'
+					? submitSettingsForm
+					: handleCustomSave
+			}
 		>
+			{ pendingNavigation ? (
+				<UnsavedChangesModal
+					isSaving={ isSaving }
+					onClose={ () => setPendingNavigation( null ) }
+					onDiscard={ handleDiscardNavigation }
+					onSave={ handleSavePendingNavigation }
+				/>
+			) : null }
 			{ saveNotice ? (
 				<Notice
 					className="wc-settings-ui-shell__notice"
@@ -569,38 +798,50 @@ export const SettingsUIPage = ( {
 			) : null }
 			<div className="wc-settings-ui">
 				{ visibleGroups.map( ( group ) => (
-					<section className="wc-settings-ui__group" key={ group.id }>
-						<GroupHeader group={ group } />
-						<div className="wc-settings-ui__group-panel">
-							{ group.fields.map( ( field ) => {
-								const FieldComponent =
-									resolveFieldComponent( field, context ) ||
-									NativeSettingsField;
-								const value = values[ field.id ];
-
-								return (
-									<div
-										className={ [
-											'wc-settings-ui__field',
-											getFieldTypeClassName( field.type ),
-										].join( ' ' ) }
-										key={ field.id }
-									>
-										<FieldComponent
-											field={ field }
-											value={ value }
-											context={ context }
-											values={ values }
-											initialValues={ initialValues }
-											setValue={ setValue }
-											setValues={ setValues }
-											onChange={ ( nextValue ) =>
-												setValue( field.id, nextValue )
-											}
-										/>
-									</div>
-								);
-							} ) }
+					<section
+						className="wc-settings-ui__section"
+						key={ group.id }
+					>
+						<div className="wc-settings-ui__section-card">
+							<GroupHeader group={ group } />
+							<div className="wc-settings-ui__section-fields">
+								{ group.fields.map( ( field ) => {
+									const FieldComponent =
+										resolveFieldComponent(
+											field,
+											context
+										) || NativeSettingsField;
+									const value = values[ field.id ];
+
+									return (
+										<div
+											className={ [
+												'wc-settings-ui__field',
+												getFieldTypeClassName(
+													field.type
+												),
+											].join( ' ' ) }
+											key={ field.id }
+										>
+											<FieldComponent
+												field={ field }
+												value={ value }
+												context={ context }
+												values={ values }
+												initialValues={ initialValues }
+												setValue={ setValue }
+												setValues={ setValues }
+												onChange={ ( nextValue ) =>
+													setValue(
+														field.id,
+														nextValue
+													)
+												}
+											/>
+										</div>
+									);
+								} ) }
+							</div>
 						</div>
 					</section>
 				) ) }
diff --git a/packages/js/settings-ui-sdk/src/test/html-rendering.test.tsx b/packages/js/settings-ui-sdk/src/test/html-rendering.test.tsx
index a37b0d16d72..fe514aec45b 100644
--- a/packages/js/settings-ui-sdk/src/test/html-rendering.test.tsx
+++ b/packages/js/settings-ui-sdk/src/test/html-rendering.test.tsx
@@ -7,14 +7,20 @@ import { createRoot } from 'react-dom/client';
 import type { ReactNode } from 'react';

 jest.mock( '@wordpress/admin-ui', () => ( {
-	Page: ( { children }: { children: ReactNode } ) => <>{ children }</>,
+	Page: ( {
+		children,
+		className,
+	}: {
+		children: ReactNode;
+		className?: string;
+	} ) => <div className={ className }>{ children }</div>,
 } ) );

 /**
  * Internal dependencies
  */
 import { SettingsUIPage } from '../settings-ui-page';
-import { NativeSettingsField } from '../native-fields';
+import { __resetRegistry, registerSettingsExtension } from '../registry';
 import type { SettingsUISchema } from '../types';

 globalThis.IS_REACT_ACT_ENVIRONMENT = true;
@@ -45,23 +51,86 @@ const expectUnsafeMarkupRemoved = ( container: HTMLElement ) => {
 };

 describe( 'settings HTML rendering', () => {
-	it( 'sanitizes native field help before rendering', () => {
+	afterEach( () => {
+		__resetRegistry();
+	} );
+
+	it( 'renders settings as centered sections and cards', () => {
+		const schema: SettingsUISchema = {
+			id: 'test-page',
+			title: 'Test page',
+			section: 'default',
+			save: { adapter: 'none' },
+			groups: {
+				general: {
+					id: 'general',
+					title: 'General settings',
+					description: 'Configure the basics.',
+					fields: [
+						{
+							id: 'test_field',
+							label: 'Test field',
+							type: 'text',
+							description: 'Shown as field description.',
+						},
+					],
+				},
+			},
+		};
+
 		const { container, root } = renderElement(
-			<NativeSettingsField
-				field={ {
-					id: 'test_field',
-					label: 'Test field',
-					type: 'text',
-					description: unsafeDescription,
-				} }
-				value=""
-				onChange={ jest.fn() }
-				context={ { page: 'test' } }
-				values={ {} }
-				initialValues={ {} }
-				setValue={ jest.fn() }
-				setValues={ jest.fn() }
-			/>
+			<SettingsUIPage schema={ schema } />
+		);
+
+		expect(
+			container.querySelector( '.wc-settings-ui__section' )
+		).not.toBeNull();
+		expect(
+			container.querySelector( '.wc-settings-ui__section-card' )
+		).not.toBeNull();
+		expect(
+			container.querySelector( '.wc-settings-ui__section-fields' )
+		).not.toBeNull();
+		expect( container.querySelector( '.wc-settings-ui__row' ) ).toBeNull();
+		expect(
+			container.querySelector( '.wc-settings-ui__group-panel' )
+		).toBeNull();
+		expect(
+			container.querySelector( '.wc-settings-ui__group-header' )
+		).toBeNull();
+		expect( container.textContent ).toContain( 'General settings' );
+		expect( container.textContent ).toContain( 'Test field' );
+		expect( container.textContent ).toContain(
+			'Shown as field description.'
+		);
+
+		act( () => root.unmount() );
+		container.remove();
+	} );
+
+	it( 'sanitizes native field descriptions before rendering', () => {
+		const schema: SettingsUISchema = {
+			id: 'test-page',
+			title: 'Test page',
+			section: 'default',
+			save: { adapter: 'none' },
+			groups: {
+				general: {
+					id: 'general',
+					fields: [
+						{
+							id: 'test_field',
+							label: 'Test field',
+							type: 'text',
+							description: unsafeDescription,
+						},
+					],
+				},
+			},
+		};
+
+		const { container, root } = renderElement(
+			<SettingsUIPage schema={ schema } />
 		);

 		expectUnsafeMarkupRemoved( container );
@@ -111,6 +180,189 @@ describe( 'settings HTML rendering', () => {
 		container.remove();
 	} );

+	it( 'prompts before navigating away with unsaved changes', () => {
+		const schema: SettingsUISchema = {
+			id: 'test-page',
+			title: 'Test page',
+			section: 'default',
+			save: { adapter: 'form_post' },
+			shell: {
+				navigation: [
+					{
+						id: 'next-page',
+						label: 'Next page',
+						href: 'https://example.com/next',
+					},
+				],
+			},
+			groups: {
+				general: {
+					id: 'general',
+					fields: [
+						{
+							id: 'test_field',
+							label: 'Test field',
+							type: 'text',
+							value: 'Initial value',
+						},
+					],
+				},
+			},
+		};
+
+		const { container, root } = renderElement(
+			<SettingsUIPage schema={ schema } />
+		);
+
+		const input = container.querySelector( 'input[type="text"]' );
+		const link = container.querySelector(
+			'a[href="https://example.com/next"]'
+		);
+
+		expect( input ).not.toBeNull();
+		expect( link ).not.toBeNull();
+
+		act( () => {
+			if ( input instanceof HTMLInputElement ) {
+				const valueSetter = Object.getOwnPropertyDescriptor(
+					HTMLInputElement.prototype,
+					'value'
+				)?.set;
+
+				valueSetter?.call( input, 'Changed value' );
+				input.dispatchEvent(
+					new Event( 'input', { bubbles: true, cancelable: true } )
+				);
+			}
+		} );
+
+		act( () => {
+			link?.dispatchEvent(
+				new MouseEvent( 'click', {
+					bubbles: true,
+					cancelable: true,
+					button: 0,
+				} )
+			);
+		} );
+
+		expect( document.body.textContent ).toContain(
+			'You have unsaved changes'
+		);
+		expect( document.body.textContent ).toContain(
+			"If you leave now, your changes won't be saved."
+		);
+		expect( document.body.textContent ).toContain( 'Discard' );
+		expect( document.body.textContent ).toContain( 'Save' );
+
+		act( () => root.unmount() );
+		container.remove();
+	} );
+
+	it( 'keeps unload protection when custom save before navigation fails', async () => {
+		const saveHandler = jest
+			.fn()
+			.mockRejectedValue( new Error( 'Save failed.' ) );
+
+		registerSettingsExtension( {
+			scope: { page: 'test-page', section: 'default' },
+			saveHandlers: {
+				fail: saveHandler,
+			},
+		} );
+
+		const schema: SettingsUISchema = {
+			id: 'test-page',
+			title: 'Test page',
+			section: 'default',
+			save: { adapter: 'custom', handler: 'fail' },
+			shell: {
+				navigation: [
+					{
+						id: 'next-page',
+						label: 'Next page',
+						href: 'https://example.com/next',
+					},
+				],
+			},
+			groups: {
+				general: {
+					id: 'general',
+					fields: [
+						{
+							id: 'test_field',
+							label: 'Test field',
+							type: 'text',
+							value: 'Initial value',
+						},
+					],
+				},
+			},
+		};
+
+		const { container, root } = renderElement(
+			<SettingsUIPage schema={ schema } />
+		);
+
+		const input = container.querySelector( 'input[type="text"]' );
+		const link = container.querySelector(
+			'a[href="https://example.com/next"]'
+		);
+
+		act( () => {
+			if ( input instanceof HTMLInputElement ) {
+				const valueSetter = Object.getOwnPropertyDescriptor(
+					HTMLInputElement.prototype,
+					'value'
+				)?.set;
+
+				valueSetter?.call( input, 'Changed value' );
+				input.dispatchEvent(
+					new Event( 'input', { bubbles: true, cancelable: true } )
+				);
+			}
+		} );
+
+		act( () => {
+			link?.dispatchEvent(
+				new MouseEvent( 'click', {
+					bubbles: true,
+					cancelable: true,
+					button: 0,
+				} )
+			);
+		} );
+
+		const saveButton = Array.from(
+			document.body.querySelectorAll(
+				'.wc-settings-ui__unsaved-changes-actions button'
+			)
+		).find( ( button ) => button.textContent === 'Save' );
+
+		await act( async () => {
+			saveButton?.dispatchEvent(
+				new MouseEvent( 'click', {
+					bubbles: true,
+					cancelable: true,
+					button: 0,
+				} )
+			);
+		} );
+
+		const beforeUnloadEvent = new Event( 'beforeunload', {
+			cancelable: true,
+		} );
+
+		window.dispatchEvent( beforeUnloadEvent );
+
+		expect( saveHandler ).toHaveBeenCalledTimes( 1 );
+		expect( beforeUnloadEvent.defaultPrevented ).toBe( true );
+		expect( document.body.textContent ).toContain( 'Save failed.' );
+
+		act( () => root.unmount() );
+		container.remove();
+	} );
+
 	it( 'sanitizes info fields and group descriptions before rendering', () => {
 		const schema: SettingsUISchema = {
 			id: 'test-page',
diff --git a/plugins/woocommerce/changelog/tweak-settings-ui-card-design b/plugins/woocommerce/changelog/tweak-settings-ui-card-design
new file mode 100644
index 00000000000..6b22f8777da
--- /dev/null
+++ b/plugins/woocommerce/changelog/tweak-settings-ui-card-design
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Align Settings UI SDK embed styling with the settings card design.
diff --git a/plugins/woocommerce/client/admin/client/wp-admin-scripts/settings-embed/settings-ui.scss b/plugins/woocommerce/client/admin/client/wp-admin-scripts/settings-embed/settings-ui.scss
index 5911212d033..118d42dd4cc 100644
--- a/plugins/woocommerce/client/admin/client/wp-admin-scripts/settings-embed/settings-ui.scss
+++ b/plugins/woocommerce/client/admin/client/wp-admin-scripts/settings-embed/settings-ui.scss
@@ -97,8 +97,10 @@ body.woocommerce_page_wc-settings.woocommerce-settings-ui-page {
 		position: static;
 	}

-	.wc-settings-ui-shell:has(.wc-settings-ui-shell__navigation) .admin-ui-page__header {
-		border-bottom: 0;
+	.wc-settings-ui-shell {
+		&:has(.wc-settings-ui-shell__navigation) .admin-ui-page__header {
+			border-bottom: 0;
+		}
 	}

 	.wc-settings-ui-shell .admin-ui-page__header-title {
@@ -131,7 +133,6 @@ body.woocommerce_page_wc-settings.woocommerce-settings-ui-page {
 		}
 	}

-
 	.wc-settings-ui-shell__navigation {
 		border-bottom: 1px solid #f0f0f0;
 		margin: 0;
@@ -193,72 +194,70 @@ body.woocommerce_page_wc-settings.woocommerce-settings-ui-page {
 	}

 	.wc-settings-ui {
-		--wc-settings-ui-panel-width: 681px;
-		--wc-settings-ui-sidebar-width: 296px;
+		box-sizing: border-box;
+		margin: 32px auto 48px;
+		max-width: 656px;
+	}
+
+	.wc-settings-ui__section {
+		margin: 0 0 32px;
+	}

+	.wc-settings-ui__section-card {
+		background: #fff;
+		border: 1px solid #e0e0e0;
+		border-radius: 4px;
 		box-sizing: border-box;
-		color: #1e1e1e;
-		font-size: 13px;
-		line-height: 20px;
-		margin: 48px 48px;
-		max-width: calc(var(--wc-settings-ui-sidebar-width) + var(--wc-settings-ui-panel-width) + 24px);
+		padding: 24px;
+		width: 100%;
 	}

-	.wc-settings-ui__group {
+	.wc-settings-ui__section-header {
 		align-items: flex-start;
 		display: flex;
 		gap: 24px;
-		margin: 0 0 48px;
+		justify-content: space-between;
+		margin-bottom: 24px;
 	}

-	.wc-settings-ui__group-header {
-		flex: 0 0 var(--wc-settings-ui-sidebar-width);
-		max-width: var(--wc-settings-ui-sidebar-width);
+	.wc-settings-ui__section-heading {
 		min-width: 0;
+	}

-		h2 {
-			color: #070707;
-			font-size: 16px;
-			font-weight: 600;
-			line-height: 24px;
-			margin: 0;
-		}
-
-		.wc-settings-ui__group-description {
-			color: #505050;
-			font-size: 14px;
-			line-height: 20px;
-			margin: 4px 0 0;
-			max-width: 240px;
+	.wc-settings-ui__section-header h2 {
+		color: #1e1e1e;
+		font-size: 15px;
+		font-weight: 500;
+		line-height: 20px;
+		margin: 0;
+	}

-			p {
-				margin: 0 0 8px;
-			}
+	.wc-settings-ui__section-description {
+		color: #757575;
+		font-size: 13px;
+		line-height: 20px;
+		margin: 8px 0 0;

-			p:last-child {
-				margin-bottom: 0;
-			}
+		p {
+			margin: 0 0 8px;
 		}

-		.wc-settings-ui__group-actions {
-			display: flex;
-			flex-wrap: wrap;
-			gap: 8px;
-			margin-top: 16px;
+		p:last-child {
+			margin-bottom: 0;
 		}
 	}

-	.wc-settings-ui__group-panel {
-		background: #fff;
-		border: 1px solid #e0e0e0;
-		border-radius: 4px;
+	.wc-settings-ui__section-actions {
+		display: flex;
+		flex: 0 0 auto;
+		flex-wrap: wrap;
+		gap: 8px;
+	}
+
+	.wc-settings-ui__section-fields {
 		display: flex;
-		flex: 0 1 var(--wc-settings-ui-panel-width);
 		flex-direction: column;
-		gap: 16px;
-		max-width: var(--wc-settings-ui-panel-width);
-		padding: 24px;
-		width: 100%;
+		gap: 24px;
 	}

 	.wc-settings-ui__field {
@@ -266,22 +265,13 @@ body.woocommerce_page_wc-settings.woocommerce-settings-ui-page {
 		width: 100%;
 	}

-	.wc-settings-ui__actions {
-		margin-left: calc(var(--wc-settings-ui-sidebar-width) + 24px);
-	}
-
 	.wc-settings-ui__info {
-		background: #f0f0f1;
+		background: #f6f7f7;
 		border-radius: 4px;
-		color: #505050;
-		font-size: 13px;
-		line-height: 20px;
 		padding: 16px;

 		strong {
-			color: #1e1e1e;
 			display: block;
-			font-weight: 500;
 			margin-bottom: 4px;
 		}

@@ -300,89 +290,42 @@ body.woocommerce_page_wc-settings.woocommerce-settings-ui-page {
 			margin-bottom: 0;
 		}

-		.components-base-control__label {
-			color: #1e1e1e;
-			display: block;
-			font-size: 11px;
-			font-weight: 500;
-			line-height: 16px;
-			margin: 0 0 8px;
-			text-transform: uppercase;
-		}
-
 		.components-base-control__help {
-			color: #505050;
-			font-size: 12px;
-			line-height: 16px;
-			margin: 8px 0 0;
+			color: #757575;
+			font-size: 13px;
+			line-height: 20px;
+			margin-top: 8px;
 		}
 	}

-	.wc-settings-ui__control input[type="text"],
-	.wc-settings-ui__control input[type="password"],
-	.wc-settings-ui__control input[type="datetime-local"],
-	.wc-settings-ui__control input[type="date"],
-	.wc-settings-ui__control input[type="time"],
-	.wc-settings-ui__control input[type="email"],
-	.wc-settings-ui__control input[type="url"],
-	.wc-settings-ui__control input[type="tel"],
-	.wc-settings-ui__control input[type="number"],
-	.wc-settings-ui__control select,
-	.wc-settings-ui__control textarea {
-		border-color: #949494;
-		border-radius: 2px;
-		color: #1e1e1e;
-		font-size: 13px;
-		line-height: 20px;
-		margin: 0;
-		max-width: none;
-		min-height: 40px;
-		width: 100%;
-	}
-
-	.wc-settings-ui__control input[type="text"],
-	.wc-settings-ui__control input[type="password"],
-	.wc-settings-ui__control input[type="datetime-local"],
-	.wc-settings-ui__control input[type="date"],
-	.wc-settings-ui__control input[type="time"],
-	.wc-settings-ui__control input[type="email"],
-	.wc-settings-ui__control input[type="url"],
-	.wc-settings-ui__control input[type="tel"],
-	.wc-settings-ui__control input[type="number"],
-	.wc-settings-ui__control select {
-		padding: 8px 12px;
-	}
-
-	.wc-settings-ui__control textarea {
-		padding: 10px 12px;
-	}
-
-	.wc-settings-ui__field--checkbox {
-		.components-base-control__field {
-			align-items: flex-start;
-			display: flex;
-			gap: 12px;
+	.wc-settings-ui__unsaved-changes-modal {
+		.components-modal__header {
+			min-height: 72px;
+			padding: 24px 32px 8px;
 		}

-		.components-h-stack {
-			align-items: flex-start;
-			gap: 12px;
+		.components-modal__header-heading {
+			font-size: 20px;
+			font-weight: 500;
+			line-height: 24px;
 		}

-		.components-checkbox-control__input-container {
-			flex: 0 0 auto;
-			margin: 0;
+		.components-modal__content {
+			padding: 4px 32px 32px;
 		}

-		.components-checkbox-control__label {
-			color: #1e1e1e;
+		p {
 			font-size: 13px;
 			line-height: 20px;
+			margin: 0;
 		}
+	}

-		.components-base-control__help {
-			margin-left: 32px;
-		}
+	.wc-settings-ui__unsaved-changes-actions {
+		display: flex;
+		gap: 8px;
+		justify-content: flex-end;
+		margin-top: 24px;
 	}

 	@media (max-width: 960px) {
@@ -424,25 +367,20 @@ body.woocommerce_page_wc-settings.woocommerce-settings-ui-page {
 		}

 		.wc-settings-ui {
-			margin: 32px 24px;
+			margin: 48px 24px 32px;
 			max-width: none;
 		}

-		.wc-settings-ui__group {
-			display: block;
+		.wc-settings-ui__section-card {
+			padding: 24px;
 		}

-		.wc-settings-ui__group-header {
-			margin-bottom: 16px;
-			max-width: none;
-		}
-
-		.wc-settings-ui__group-panel {
-			max-width: none;
+		.wc-settings-ui__section-header {
+			display: block;
 		}

-		.wc-settings-ui__actions {
-			margin-left: 0;
+		.wc-settings-ui__section-actions {
+			margin-top: 16px;
 		}
 	}
 }