Migrate ToggleButtonGroup to the Polaris choice list component
The previous ToggleButtonGroup and ToggleButton components have been replaced by <s-choice-list> with variant="grid" and <s-choice> children, available in API versions 2025-10 and newer.
The grid variant renders each choice as a selectable block without checkbox or radio controls, matching the visual appearance of the previous toggle buttons. See the choice list migration guide for additional property changes shared across all choice list variants.
Anchor to Component mappingComponent mapping
| Previous component | New component | Notes |
|---|---|---|
ToggleButtonGroup | <s-choice-list variant="grid"> | Wraps the set of choices. |
ToggleButton | <s-choice> | Each selectable option. Use the value attribute instead of id. |
<s-choice-list variant="grid"> is the right fit for a mutually-exclusive group that's submitted by a single name — pick-one behaviour with form semantics. If the buttons aren't mutually exclusive, or you have a single standalone toggle, use <s-press-button> instead. Each <s-press-button> tracks its own state through pressed (or defaultPressed for uncontrolled usage), so you can have several pressed at once.
Migrating independent toggles to s-press-button
Latest (Preact)
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
import {useState} from 'preact/hooks';
export default function extension() {
render(<Extension />, document.body);
}
function Extension() {
const [filters, setFilters] = useState({gift: false, express: false});
const toggle = (key) =>
setFilters((prev) => ({...prev, [key]: !prev[key]}));
return (
<s-stack direction="inline" gap="small-200">
<s-press-button
pressed={filters.gift}
onClick={() => toggle('gift')}
>
Gift wrap
</s-press-button>
<s-press-button
pressed={filters.express}
onClick={() => toggle('express')}
>
Express shipping
</s-press-button>
</s-stack>
);
}Pre-Polaris (2025-07)
import {
reactExtension,
ToggleButtonGroup,
ToggleButton,
} from '@shopify/ui-extensions-react/checkout';
import {useState} from 'react';
export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);
function Extension() {
const [filters, setFilters] = useState({gift: false, express: false});
return (
<ToggleButtonGroup value={undefined}>
<ToggleButton
id="gift"
onPress={() =>
setFilters((prev) => ({...prev, gift: !prev.gift}))
}
>
Gift wrap
</ToggleButton>
<ToggleButton
id="express"
onPress={() =>
setFilters((prev) => ({...prev, express: !prev.express}))
}
>
Express shipping
</ToggleButton>
</ToggleButtonGroup>
);
}For the standalone single-button case, see the ToggleButton migration guide.
Anchor to Updated propertiesUpdated properties
Anchor to value and onChangevalue and on Change
The previous ToggleButtonGroup value prop (a single string) maps to <s-choice-list> values (always a string[]). The onChange callback now receives an Event — read the current selection from event.currentTarget.values.
The previous ToggleButton id prop that identified the choice within the group is now the value attribute on <s-choice>. The label text is passed as children.
Migrating ToggleButtonGroup to s-choice-list variant=grid
Latest (Preact)
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
import {useState} from 'preact/hooks';
export default function extension() {
render(<Extension />, document.body);
}
function Extension() {
const [size, setSize] = useState('medium');
return (
<s-choice-list
name="size"
variant="grid"
onChange={(event) => setSize(event.currentTarget.values[0])}
>
<s-choice value="small" selected={size === 'small'}>
Small
</s-choice>
<s-choice value="medium" selected={size === 'medium'}>
Medium
</s-choice>
<s-choice value="large" selected={size === 'large'}>
Large
</s-choice>
</s-choice-list>
);
}Pre-Polaris (2025-07)
import {
reactExtension,
ToggleButtonGroup,
ToggleButton,
} from '@shopify/ui-extensions-react/checkout';
import {useState} from 'react';
export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);
function Extension() {
const [size, setSize] = useState('medium');
return (
<ToggleButtonGroup
value={size}
onChange={(value) => setSize(value)}
>
<ToggleButton id="small">Small</ToggleButton>
<ToggleButton id="medium">Medium</ToggleButton>
<ToggleButton id="large">Large</ToggleButton>
</ToggleButtonGroup>
);
}Anchor to Removed propertiesRemoved properties
The following properties from the previous components are no longer available:
ToggleButtononPress— no longer supported. Use theonChangeevent on the parent<s-choice-list>instead.ToggleButtonaccessibilityLabel— no longer supported. The label text is passed as children of<s-choice>.
Anchor to New propertiesNew properties
Using <s-choice-list> with variant="grid" gives access to all the choice list properties not available on the previous ToggleButtonGroup:
| New prop | Type | Description |
|---|---|---|
label | string | Sets the label text for the choice list. |
error | string | Sets an error message to display. |
multiple | boolean | Enables multi-select. The previous ToggleButtonGroup only supported single selection. |