Migrate Choice List from Polaris React
Replace Polaris React ChoiceList with s-choice-list and explicit s-choice children. Preserve whether the field accepts one value or multiple values, and keep the selected values in the same form or app state that performs the operation.
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 choice listMigrate a choice list
The destination renders each choice directly instead of accepting a choices descriptor array.
Migrating multiple checkout choices
Polaris web components
<s-choice-list label="Checkout options" name="checkout" multiple>
<s-choice value="shipping" selected>
Use the shipping address as the billing address by default
<s-text slot="details">
Reduces the number of fields required to check out. The billing address
can still be edited.
</s-text>
</s-choice>
<s-choice value="confirmation">
Require a confirmation step
<s-text slot="details">
Customers must review their order details before purchasing.
</s-text>
</s-choice>
</s-choice-list>Polaris React
import {ChoiceList} from '@shopify/polaris';
export function CheckoutChoices({
selectedChoices = ['shipping'],
onChange,
}) {
return (
<ChoiceList
title="Checkout options"
allowMultiple
selected={selectedChoices}
onChange={onChange}
choices={[
{
label: 'Use the shipping address as the billing address by default',
value: 'shipping',
helpText: 'Reduces the number of fields required to check out. The billing address can still be edited.',
},
{
label: 'Require a confirmation step',
value: 'confirmation',
helpText: 'Customers must review their order details before purchasing.',
},
]}
/>
);
}Preview
Anchor to Replace choice descriptorsReplace choice descriptors
| Polaris React | Polaris web components | Migration notes |
|---|---|---|
title | label on s-choice-list | Keep a group label that describes the decision. |
titleHidden | labelAccessibilityVisibility="exclusive" | Visually hide only a redundant label. |
choices | Explicit s-choice children | Move each descriptor's label to child content and keep its stable value. |
Choice helpText | s-text slot="details" inside that s-choice | Keep explanation with the option it describes. |
Choice disabled | disabled on that s-choice | Disable only the unavailable option. |
allowMultiple | multiple | Omit it for a single-choice radio group. |
selected | values on s-choice-list | Pass the controlled string array. For initial-only selection, use selected on child choices. |
onChange(selected, name) | onChange(event) | Read the selected array from event.currentTarget.values. |
error | error | Keep the message at group level so it describes the complete decision. |
disabled | disabled on s-choice-list | Disable the group and preserve the condition that controls availability. |
Don't create a second descriptor array only to map it into s-choice elements. Render from the domain options that the app already uses, and derive selected state from one source.
Anchor to Choose single or multiple selectionChoose single or multiple selection
For single selection, omit multiple and store zero or one value in the values array. If the old code used individual RadioButton components, migrate the complete group to one choice list so the shared label and keyboard behavior remain intact.
For multiple selection, set multiple and treat values as an unordered set unless option order has domain meaning. Validate combinations at group level, such as requiring at least one value or preventing mutually exclusive choices.
Anchor to Test the migrationTest the migration
- Select every option with pointer and keyboard input.
- Verify single-choice fields never retain more than one value.
- Verify multiple-choice values submit with the expected
nameand stable values. - Test per-choice and whole-group disabled states.
- Trigger and announce group errors, including required and invalid combinations.
- Reload controlled forms and confirm the selected values restore correctly.
Anchor to Remove Polaris ReactRemove Polaris React
After every call site is migrated, remove ChoiceList, descriptor-only helpers, and callback adapters. Remove @shopify/polaris only after no other route in scope imports it.