Migrate Checkbox from Polaris React
Replace Polaris React Checkbox with s-checkbox. Keep the checked value in app state when other controls or backend operations depend on it, and use the field's native form properties when the value is submitted with a form.
If the app renders this controlled field through React, upgrade to React 19 first. React 18 doesn't provide the custom-element property and event behavior this example relies on. If you can't upgrade yet, leave the controlled Polaris React field in place during this migration slice.
Anchor to Migrate a checkboxMigrate a checkbox
This example preserves a required acknowledgement and its visible validation message.
Migrating a required acknowledgement
Polaris web components
import {useState} from 'react';
export function TermsCheckbox() {
const [accepted, setAccepted] = useState(false);
return (
<s-checkbox
label="I agree to the terms"
checked={accepted}
error={accepted ? undefined : 'You must accept the terms to continue'}
onChange={(event) => setAccepted(event.currentTarget.checked)}
/>
);
}Polaris React
import {Checkbox} from '@shopify/polaris';
export function TermsCheckbox({
accepted = false,
error = 'You must accept the terms to continue',
onChange,
}) {
return (
<Checkbox
label="I agree to the terms"
checked={accepted}
error={error}
onChange={onChange}
/>
);
}Preview
Anchor to Map checkbox propertiesMap checkbox properties
| Polaris React | Polaris web components | Migration notes |
|---|---|---|
label | label | Pass a string that describes the choice. Don't move the only label into surrounding text. |
labelHidden | Visible label, or accessibilityLabel when adjacent content already identifies the control | s-checkbox doesn't expose labelAccessibilityVisibility. Prefer a visible label. |
helpText | details | Keep instructions next to the checkbox. |
error | error | Pass the validation message as a string. A boolean error state without a message isn't sufficient. |
checked={true} | checked | Use for controlled state. Read the next value from event.currentTarget.checked. |
checked="indeterminate" | indeterminate | Keep checked and indeterminate as separate values. Indeterminate changes appearance, not the submitted value. |
disabled | disabled | Preserve the reason the choice can't be changed. Don't use disabled state to hide an authorization failure. |
id, name, and value | id, name, and value | Keep stable form names and backend values. |
onChange(checked, id) | onChange(event) | Read event.currentTarget.checked and use the component's known ID when the handler needs it. |
Use defaultChecked instead of checked only when the checkbox is intentionally uncontrolled. Don't combine defaultChecked with React state that expects to update the rendered value.
Like a native checkbox, an unchecked s-checkbox contributes no entry to FormData. If the backend must receive an explicit false value, normalize the missing key on the server or append a fallback value in the submit handler. Don't add a hidden input with the same name unless the backend intentionally supports receiving both values when the checkbox is checked.
Anchor to Preserve partial selectionPreserve partial selection
For a select-all checkbox, calculate these values from the selected resource IDs:
- Set
checkedwhen every item in the defined scope is selected. - Set
indeterminatewhen at least one, but not every, item is selected. - Update the same selected-ID state from the select-all and row checkbox handlers.
- Define whether the scope means the visible page, the current query, or every resource.
Don't store selection only in the checkbox element. Bulk-action payloads, selected counts, and post-action cleanup must use the same app state.
Anchor to Test the migrationTest the migration
- Toggle the checkbox with pointer, keyboard, and label activation.
- Verify controlled and initial values don't drift after rerenders or form resets.
- Submit checked and unchecked states and confirm the backend treats the missing unchecked value as intended.
- Trigger, announce, and clear validation errors.
- Test checked, unchecked, and indeterminate selection calculations.
Anchor to Remove Polaris ReactRemove Polaris React
After every call site is migrated, remove the Checkbox import and adapters that convert (checked, id) callbacks. Remove @shopify/polaris only after no other route in scope imports it.