[Accessibility] Convert edit address link to a button (#49471)
* Update edit address button style * Add input prop to the ValidatedTextInputHandle type * Add optional isEditing prop to the AddressFormProps * Convert edit address link to button * Focus first input after opening the address form * Pass along the editing prop to children components in the shipping address block * Add changelog file * Clear timeout used to delay the focus on the first input * Adjust checkout toggler buttons for dark themes * Get first address field by id
This commit is contained in:
parent
e16a866cc5
commit
ece00533e4
|
@ -48,8 +48,10 @@ const Form = < T extends AddressFormValues | ContactFormValues >( {
|
|||
addressType = 'shipping',
|
||||
values,
|
||||
children,
|
||||
isEditing,
|
||||
}: AddressFormProps< T > ): JSX.Element => {
|
||||
const instanceId = useInstanceId( Form );
|
||||
const isFirstRender = useRef( true );
|
||||
|
||||
// Track incoming props.
|
||||
const currentFields = useShallowEqual( fields );
|
||||
|
@ -106,6 +108,41 @@ const Form = < T extends AddressFormValues | ContactFormValues >( {
|
|||
fieldsRef.current?.postcode?.revalidate();
|
||||
}, [ currentCountry ] );
|
||||
|
||||
// Focus the first input when opening the form.
|
||||
useEffect( () => {
|
||||
let timeoutId: ReturnType< typeof setTimeout >;
|
||||
|
||||
if ( ! isFirstRender.current && isEditing && fieldsRef.current ) {
|
||||
const firstField = addressFormFields.fields.find(
|
||||
( field ) => field.hidden === false
|
||||
);
|
||||
|
||||
if ( ! firstField ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { id: firstFieldId } = createFieldProps(
|
||||
firstField,
|
||||
id || `${ instanceId }`,
|
||||
addressType
|
||||
);
|
||||
const firstFieldEl = document.getElementById( firstFieldId );
|
||||
|
||||
if ( firstFieldEl ) {
|
||||
// Focus the first field after a short delay to ensure the form is rendered.
|
||||
timeoutId = setTimeout( () => {
|
||||
firstFieldEl.focus();
|
||||
}, 300 );
|
||||
}
|
||||
}
|
||||
|
||||
isFirstRender.current = false;
|
||||
|
||||
return () => {
|
||||
clearTimeout( timeoutId );
|
||||
};
|
||||
}, [ isEditing, addressFormFields, id, instanceId, addressType ] );
|
||||
|
||||
id = id || `${ instanceId }`;
|
||||
|
||||
return (
|
||||
|
|
|
@ -37,6 +37,8 @@ export interface AddressFormProps< T > {
|
|||
values: T;
|
||||
// support inserting children at end of form
|
||||
children?: React.ReactNode;
|
||||
// Is the form in editing mode.
|
||||
isEditing?: boolean;
|
||||
}
|
||||
|
||||
interface AddressFieldData {
|
||||
|
|
|
@ -22,11 +22,13 @@ const AddressCard = ( {
|
|||
onEdit,
|
||||
target,
|
||||
fieldConfig,
|
||||
isExpanded,
|
||||
}: {
|
||||
address: CartShippingAddress | CartBillingAddress;
|
||||
onEdit: () => void;
|
||||
target: string;
|
||||
fieldConfig: FormFieldsConfig;
|
||||
isExpanded: boolean;
|
||||
} ): JSX.Element | null => {
|
||||
const countryData = getSetting< Record< string, CountryData > >(
|
||||
'countryData',
|
||||
|
@ -76,18 +78,19 @@ const AddressCard = ( {
|
|||
) }
|
||||
</address>
|
||||
{ onEdit && (
|
||||
<a
|
||||
role="button"
|
||||
href={ '#' + target }
|
||||
<button
|
||||
className="wc-block-components-address-card__edit"
|
||||
aria-controls={ target }
|
||||
aria-expanded={ isExpanded }
|
||||
aria-label={ __( 'Edit address', 'woocommerce' ) }
|
||||
onClick={ ( e ) => {
|
||||
onEdit();
|
||||
e.preventDefault();
|
||||
onEdit();
|
||||
} }
|
||||
type="button"
|
||||
>
|
||||
{ __( 'Edit', 'woocommerce' ) }
|
||||
</a>
|
||||
</button>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -35,7 +35,15 @@
|
|||
}
|
||||
}
|
||||
.wc-block-components-address-card__edit {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
margin: 0 0 0 auto;
|
||||
text-decoration: none;
|
||||
@include font-size(small);
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,9 +83,10 @@ const CustomerAddress = ( {
|
|||
setEditing( true );
|
||||
} }
|
||||
fieldConfig={ addressFieldsConfig }
|
||||
isExpanded={ editing }
|
||||
/>
|
||||
),
|
||||
[ billingAddress, addressFieldsConfig ]
|
||||
[ billingAddress, addressFieldsConfig, editing ]
|
||||
);
|
||||
|
||||
const renderAddressFormComponent = useCallback(
|
||||
|
@ -98,10 +99,11 @@ const CustomerAddress = ( {
|
|||
values={ billingAddress }
|
||||
fields={ ADDRESS_FORM_KEYS }
|
||||
fieldConfig={ addressFieldsConfig }
|
||||
isEditing={ editing }
|
||||
/>
|
||||
</>
|
||||
),
|
||||
[ addressFieldsConfig, billingAddress, onChangeAddress ]
|
||||
[ addressFieldsConfig, billingAddress, onChangeAddress, editing ]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -64,9 +64,15 @@
|
|||
.wc-block-components-address-form__address_2-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin-top: $gap;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,9 +82,10 @@ const CustomerAddress = ( {
|
|||
setEditing( true );
|
||||
} }
|
||||
fieldConfig={ addressFieldsConfig }
|
||||
isExpanded={ editing }
|
||||
/>
|
||||
),
|
||||
[ shippingAddress, addressFieldsConfig ]
|
||||
[ shippingAddress, addressFieldsConfig, editing ]
|
||||
);
|
||||
|
||||
const renderAddressFormComponent = useCallback(
|
||||
|
@ -96,9 +97,10 @@ const CustomerAddress = ( {
|
|||
values={ shippingAddress }
|
||||
fields={ ADDRESS_FORM_KEYS }
|
||||
fieldConfig={ addressFieldsConfig }
|
||||
isEditing={ editing }
|
||||
/>
|
||||
),
|
||||
[ addressFieldsConfig, onChangeAddress, shippingAddress ]
|
||||
[ addressFieldsConfig, onChangeAddress, shippingAddress, editing ]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: enhancement
|
||||
|
||||
Convert edit address link to a button on checkout
|
Loading…
Reference in New Issue