Commit 278bf85e7c for woocommerce

commit 278bf85e7c0357e50a8d5b3ae8ce31d151a28170
Author: Thomas Roberts <5656702+opr@users.noreply.github.com>
Date:   Wed Dec 31 15:15:33 2025 +0000

    Add address type prefix to checkout form fields for autofill (#62513)

    * Add address type prefix to checkout form fields for autofill

    * Prefix address field autocomplete value with address type in block

    * Ensure autocomplete attr is reset to correct value after autocomplete

    * Add changelog

    * Add section tokens to autocomplete attributes per HTML spec

    Adds `section-billing` and `section-shipping` tokens to autocomplete
    attributes to help browsers distinguish between billing and shipping
    address fields. Also adds `name` attribute to Blocks checkout fields.

    Format: `section-{type} {type} {field-name}`
    Example: `section-billing billing address-level1`

    🤖 Generated with [Claude Code](https://claude.com/claude-code)

    Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

    ---------

    Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
    Co-authored-by: Seghir Nadir <nadir.seghir@gmail.com>

diff --git a/plugins/woocommerce/changelog/wooplug-5541-bug-safari-autocomplete-overwrites-shipping-address-state b/plugins/woocommerce/changelog/wooplug-5541-bug-safari-autocomplete-overwrites-shipping-address-state
new file mode 100644
index 0000000000..03e2cd8c1c
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooplug-5541-bug-safari-autocomplete-overwrites-shipping-address-state
@@ -0,0 +1,4 @@
+Significance: minor
+Type: update
+
+Add prefixes to checkout autocomplete attributes to help with Safari autofill
diff --git a/plugins/woocommerce/client/blocks/assets/js/base/components/cart-checkout/form/utils.ts b/plugins/woocommerce/client/blocks/assets/js/base/components/cart-checkout/form/utils.ts
index 8c168b992e..98e9baa720 100644
--- a/plugins/woocommerce/client/blocks/assets/js/base/components/cart-checkout/form/utils.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/base/components/cart-checkout/form/utils.ts
@@ -14,6 +14,7 @@ import type { JSONSchemaType } from 'ajv';
 export interface FieldProps {
 	id: string;
 	errorId: string;
+	name: string;
 	label: string;
 	autoCapitalize: string | undefined;
 	autoComplete: string | undefined;
@@ -30,9 +31,15 @@ export const createFieldProps = (
 ): FieldProps => ( {
 	id: `${ formId }-${ field?.key }`.replaceAll( '/', '-' ), // Replace all slashes with hyphens to avoid invalid HTML ID.
 	errorId: `${ fieldAddressType }_${ field?.key }`,
+	name: `${ fieldAddressType }_${ field?.key }`,
 	label: ( field?.required ? field?.label : field?.optionalLabel ) || '',
 	autoCapitalize: field?.autocapitalize,
-	autoComplete: field?.autocomplete,
+	// Prefix autocomplete value with section and address type per HTML spec.
+	// Format: section-<name> [shipping|billing] <autofill-field>
+	// e.g., 'address-level1' becomes 'section-billing billing address-level1'
+	autoComplete: field?.autocomplete
+		? `section-${ fieldAddressType } ${ fieldAddressType } ${ field.autocomplete }`
+		: undefined,
 	errorMessage: field?.errorMessage || '',
 	required: field?.required,
 	placeholder: field?.placeholder,
diff --git a/plugins/woocommerce/client/legacy/js/frontend/address-autocomplete.js b/plugins/woocommerce/client/legacy/js/frontend/address-autocomplete.js
index 2b7714b586..ba05bb36fb 100644
--- a/plugins/woocommerce/client/legacy/js/frontend/address-autocomplete.js
+++ b/plugins/woocommerce/client/legacy/js/frontend/address-autocomplete.js
@@ -226,6 +226,14 @@ if (
 					return;
 				}

+				// Store the original autocomplete value before disabling
+				const originalAutocomplete =
+					input.getAttribute( 'autocomplete' ) || '';
+				input.setAttribute(
+					'data-original-autocomplete',
+					originalAutocomplete
+				);
+
 				input.setAttribute( 'autocomplete', 'none' );
 				input.setAttribute( 'data-lpignore', 'true' );
 				input.setAttribute( 'data-op-ignore', 'true' );
@@ -274,7 +282,11 @@ if (
 					return;
 				}

-				input.setAttribute( 'autocomplete', 'address-line1' );
+				// Restore the original autocomplete value
+				const originalAutocomplete =
+					input.getAttribute( 'data-original-autocomplete' ) ||
+					'address-line1';
+				input.setAttribute( 'autocomplete', originalAutocomplete );
 				input.setAttribute( 'data-lpignore', 'false' );
 				input.setAttribute( 'data-op-ignore', 'false' );
 				input.setAttribute( 'data-1p-ignore', 'false' );
diff --git a/plugins/woocommerce/includes/class-wc-countries.php b/plugins/woocommerce/includes/class-wc-countries.php
index 48de063ac9..c991ee8566 100644
--- a/plugins/woocommerce/includes/class-wc-countries.php
+++ b/plugins/woocommerce/includes/class-wc-countries.php
@@ -1733,11 +1733,20 @@ class WC_Countries {
 		// Prepend field keys.
 		$address_fields = array();

+		// Convert type prefix (e.g., 'billing_' or 'shipping_') to address type for autocomplete (e.g., 'billing' or 'shipping').
+		$address_type = rtrim( $type, '_' );
+
 		foreach ( $fields as $key => $value ) {
 			if ( 'state' === $key ) {
 				$value['country_field'] = $type . 'country';
 				$value['country']       = $country;
 			}
+			// Prefix autocomplete value with section and address type per HTML spec.
+			// Format: section-<name> [shipping|billing] <autofill-field>
+			// e.g., 'address-level1' becomes 'section-billing billing address-level1'.
+			if ( ! empty( $value['autocomplete'] ) ) {
+				$value['autocomplete'] = 'section-' . $address_type . ' ' . $address_type . ' ' . $value['autocomplete'];
+			}
 			$address_fields[ $type . $key ] = $value;
 		}

@@ -1750,7 +1759,7 @@ class WC_Countries {
 					'type'         => 'tel',
 					'class'        => array( 'form-row-wide' ),
 					'validate'     => array( 'phone' ),
-					'autocomplete' => 'tel',
+					'autocomplete' => 'section-' . $address_type . ' ' . $address_type . ' tel',
 					'priority'     => 100,
 				);
 			}
@@ -1760,7 +1769,7 @@ class WC_Countries {
 				'type'         => 'email',
 				'class'        => array( 'form-row-wide' ),
 				'validate'     => array( 'email' ),
-				'autocomplete' => 'email',
+				'autocomplete' => 'section-' . $address_type . ' ' . $address_type . ' email',
 				'priority'     => 110,
 			);
 		}