Migrate Stepper to the Polaris number field component
The Polaris number field component renders a numeric input. It replaces the previous Stepper component and is available as <s-number-field> in API versions 2025-10 and newer. The previous Stepper component always showed increment and decrement buttons. On the Polaris number field, controls defaults to 'auto', which lets the surface decide whether to show the buttons. To guarantee the previous behavior, set controls="stepper" explicitly.
Showing stepper buttons
Latest (Preact)
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
export default function extension() {
render(<Extension />, document.body);
}
function Extension() {
return (
<s-number-field
label="Quantity"
controls="stepper"
defaultValue="1"
min={1}
max={10}
/>
);
}Pre-Polaris (2025-07)
import {
reactExtension,
Stepper,
} from '@shopify/ui-extensions-react/checkout';
export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);
function Extension() {
return (
<Stepper label="Quantity" value={1} min={1} max={10} />
);
}Anchor to Updated propertiesUpdated properties
The following properties are different in the Polaris number field component.
Anchor to onChangeon Change
The previous Stepper onChange prop was called with the new numeric value, and an empty field was represented as undefined. On the Polaris number field, the handler receives an Event instead. Read the value from event.currentTarget.value, which is now a string. Don't cast it with Number(...) directly — Number('') evaluates to 0, so a cleared field would be reinterpreted as zero. Check for an empty string first, then cast:
Migrating onChange
Latest (Preact)
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
export default function extension() {
render(<Extension />, document.body);
}
function Extension() {
return (
<s-number-field
label="Quantity"
controls="stepper"
onChange={(event) => {
const raw = event.currentTarget.value;
const value = raw === '' ? undefined : Number(raw);
console.log('Value:', value);
}}
/>
);
}Pre-Polaris (2025-07)
import {
reactExtension,
Stepper,
} from '@shopify/ui-extensions-react/checkout';
export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);
function Extension() {
return (
<Stepper
label="Quantity"
onChange={(value) => console.log('Value:', value)}
/>
);
}Anchor to onInputon Input
The previous Stepper onInput prop was called with the new numeric value, and an empty field was represented as undefined. On the Polaris number field, the handler receives an Event. Read the value from event.currentTarget.value, which is now a string. Check for an empty string before casting with Number(...) — Number('') is 0, which would reinterpret a cleared field as zero.
The previous Stepper onBlur and onFocus props were called with no arguments. On the Polaris number field, both handlers now receive an Event.
Anchor to valuevalue
The previous Stepper value prop was a number. On the Polaris number field, value is a string. Use defaultValue (uncontrolled) or value (controlled) to set the initial value.
Migrating value
Latest (Preact)
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
export default function extension() {
render(<Extension />, document.body);
}
function Extension() {
return (
<s-number-field
label="Quantity"
controls="stepper"
defaultValue="1"
min={1}
max={10}
/>
);
}Pre-Polaris (2025-07)
import {
reactExtension,
Stepper,
} from '@shopify/ui-extensions-react/checkout';
export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);
function Extension() {
return (
<Stepper label="Quantity" value={1} min={1} max={10} />
);
}Anchor to readonlyreadonly
The previous Stepper readonly prop is now readOnly (capital O).
Anchor to min and max defaultsmin and max defaults
The previous Stepper min defaulted to 0 and max had no default. On the Polaris number field, min defaults to -Infinity and max defaults to Infinity. If your code relied on the previous min={0} default, set min={0} explicitly.
Anchor to iconicon
If you use the icon property, then update icon names to their Polaris web component equivalents. The number field uses the same icon names as the Polaris icon component.
This table lists only icon values that need more than a camelCase-to-kebab-case rename. If an icon isn't listed here, then convert its previous camelCase name to kebab-case. For example, arrowLeft becomes arrow-left.
This table lists only icon values that need more than a camelCase-to-kebab-case rename. If an icon isn't listed here, then convert its previous camelCase name to kebab-case. For example, arrowLeft becomes arrow-left.
| Previous icon | New icon |
|---|---|
'checkmark' | 'check' |
'close' | 'x' |
'critical' | 'alert-circle' |
'error' | 'x-circle' |
'errorFill' | 'x-circle-filled' |
'gift' | 'gift-card' |
'giftFill' | 'gift-card' |
'hamburger' | 'menu' |
'hollowCircle' | 'circle' |
'horizontalDots' | 'menu-horizontal' |
'infoFill' | 'info-filled' |
'list' | 'list-bulleted' |
'magnify' | 'search' |
'marker' | 'location' |
'orderBox' | 'order' |
'pen' | 'edit' |
'question' | 'question-circle' |
'questionFill' | 'question-circle-filled' |
'starFill' | 'star-filled' |
'success' | 'check-circle' |
'verticalDots' | 'menu-vertical' |
'warning' | 'alert-triangle' |
'warningFill' | 'alert-triangle-filled' |
Anchor to New propertiesNew properties
The Polaris number field component introduces the following new properties:
| New prop | Type | Description |
|---|---|---|
controls | 'auto' | 'stepper' | 'none' | Sets the type of controls displayed in the field. 'stepper' shows increment and decrement buttons, 'none' hides them, and 'auto' (the default) lets the surface decide. |
defaultValue | string | Sets the initial value for uncontrolled usage. |
suffix | string | Text content to render after the value. |
autocomplete | string | A hint to the browser about the autofill value for the field. |
inputMode | 'decimal' | 'numeric' | Hints at the type of virtual keyboard to display. |
labelAccessibilityVisibility | 'visible' | 'exclusive' | Controls whether the label is visible or only available to assistive technology. |
Anchor to accessoryaccessory
The Polaris number field exposes an accessory slot for supplementary interactive content (a button or clickable with text content). The previous Stepper had no equivalent — the slot is a new capability on <s-number-field>. Use it for actions adjacent to the input, such as a "Use max" button:
Adding an accessory to s-number-field
For static unit indicators like kg or %, use the prefix and suffix props instead:
Anchor to Removed propertiesRemoved properties
Anchor to accessibilityDescriptionaccessibility Description
The previous Stepper accessibilityDescription prop has been removed. Use label or the field's built-in error and validation messaging to communicate additional context to screen readers.