Skip to main content

Migrate FormLayout from Polaris React

Replace Polaris React FormLayout and FormLayout.Group with s-grid. s-grid controls layout only. Keep form submission on a native form element, and keep labels, values, validation, and errors on each field.


Anchor to Migrate a form layoutMigrate a form layout

The following example preserves a two-column name group that collapses to one column when its container is 500 pixels wide or narrower. The email field remains a full-width row.

Migrating a contact form layout

function MerchantContactForm() {
return (
<form data-save-bar>
<s-grid gridTemplateColumns="1fr" gap="base">
<s-query-container>
<s-grid
gridTemplateColumns="@container (inline-size > 500px) 1fr 1fr, 1fr"
gap="base"
>
<s-text-field
label="First name"
name="firstName"
autocomplete="given-name"
/>
<s-text-field
label="Last name"
name="lastName"
autocomplete="family-name"
/>
</s-grid>
</s-query-container>
<s-email-field
label="Email"
name="email"
autocomplete="email"
/>
</s-grid>
</form>
);
}
import {FormLayout, TextField} from '@shopify/polaris';
import {useState} from 'react';

export function MerchantContactForm() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');

return (
<FormLayout>
<FormLayout.Group>
<TextField
label="First name"
value={firstName}
onChange={setFirstName}
autoComplete="given-name"
/>
<TextField
label="Last name"
value={lastName}
onChange={setLastName}
autoComplete="family-name"
/>
</FormLayout.Group>
<TextField
label="Email"
type="email"
value={email}
onChange={setEmail}
autoComplete="email"
/>
</FormLayout>
);
}

Preview

The migrated fields use name attributes so that the native form includes their values in FormData. The example also adds data-save-bar so that the form participates in the App Bridge save-bar pattern. Omit data-save-bar if the form doesn't track unsaved changes.


Anchor to Replace FormLayout and FormLayout.GroupReplace FormLayout and FormLayout.Group

Polaris ReactPolaris web componentsMigration notes
FormLayoutAn outer s-grid with gridTemplateColumns="1fr"Creates the vertical sequence of rows.
FormLayout.GroupA nested s-gridCreates columns for related fields.
Space between fieldsgapChoose a documented Polaris spacing value.
Responsive groupings-query-container and a container query in gridTemplateColumnsBase the field layout on the available container width, not the viewport width.
condensed groupAn explicit gridTemplateColumns valueChoose column widths for the form instead of carrying the visual preset forward.
Group titleAn s-heading before the nested gridKeep the heading and fields together in the outer grid.
Group helpTextAn s-paragraph before the nested gridKeep instructions visible and adjacent to the fields they describe.

Don't replace FormLayout with s-stack. A grid expresses field columns and their responsive collapse without adding layout wrappers around each field.


Anchor to Preserve form behaviorPreserve form behavior

s-grid doesn't own form state. Migrate each field's behavior with the field component:

  • Add a stable name to every value that the form submits.
  • Preserve autocomplete, required state, constraints, and validation messages.
  • Preserve controlled state when app logic needs it. Use native form values when React doesn't need to own each keystroke.
  • Keep source order aligned with the intended reading and keyboard order. CSS columns shouldn't reorder fields.
  • Keep a group heading or instructions adjacent to the group instead of placing them in placeholder text.

For field-specific property mappings, refer to the migration guide for that field, such as TextField or Select.


  • Resize the form's container through each layout breakpoint, including when the app navigation changes the available width.
  • Verify the reading and keyboard order in both the one-column and multi-column layouts.
  • Submit the form, and confirm that FormData contains every named field.
  • Verify field errors and instructions remain associated with the correct field.
  • If you use data-save-bar, then test save, discard, validation failure, and navigation with unsaved changes.

Anchor to Remove Polaris ReactRemove Polaris React

After every FormLayout call site is migrated, remove the FormLayout import and layout wrappers used only by it. Remove @shopify/polaris only after no other route in scope imports it.



Was this page helpful?