--- title: Migrate Stepper to the Polaris number field component description: >- Learn how to migrate the Stepper component to Polaris web components in checkout and customer account UI extensions. source_url: html: >- https://shopify.dev/docs/apps/build/checkout/migrate-to-web-components/stepper md: >- https://shopify.dev/docs/apps/build/checkout/migrate-to-web-components/stepper.md --- # Migrate Stepper to the Polaris number field component The Polaris number field component renders a numeric input. It replaces the previous [`Stepper`](https://shopify.dev/docs/api/checkout-ui-extensions/2025-07/ui-components/forms/stepper) component and is available as [``](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/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`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-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) ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { return ( ); } ``` ##### Pre-Polaris (2025-07) ```jsx import { reactExtension, Stepper, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( ); } ``` *** ## Updated properties The following properties are different in the Polaris number field component. ### on​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) ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { return ( { const raw = event.currentTarget.value; const value = raw === '' ? undefined : Number(raw); console.log('Value:', value); }} /> ); } ``` ##### Pre-Polaris (2025-07) ```jsx import { reactExtension, Stepper, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( console.log('Value:', value)} /> ); } ``` ### on​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. ### on​Blur and on​Focus The previous `Stepper` `onBlur` and `onFocus` props were called with no arguments. On the Polaris number field, both handlers now receive an `Event`. ### value The previous `Stepper` `value` prop was a `number`. On the Polaris number field, [`value`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-value) is a `string`. Use [`defaultValue`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-defaultvalue) (uncontrolled) or `value` (controlled) to set the initial value. ## Migrating value ##### Latest (Preact) ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { return ( ); } ``` ##### Pre-Polaris (2025-07) ```jsx import { reactExtension, Stepper, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( ); } ``` ### readonly The previous `Stepper` `readonly` prop is now [`readOnly`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-readonly) (capital `O`). ### min and max defaults The previous `Stepper` `min` defaulted to `0` and `max` had no default. On the Polaris number field, [`min`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-min) defaults to `-Infinity` and [`max`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-max) defaults to `Infinity`. If your code relied on the previous `min={0}` default, set `min={0}` explicitly. ### icon If you use the [`icon`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-icon) property, then update icon names to their Polaris web component equivalents. The number field uses the same icon names as the Polaris [icon](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/media-and-visuals/icon) component. **Note:** 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'` | *** ## New properties The Polaris number field component introduces the following new properties: | New prop | Type | Description | | - | - | - | | [`controls`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-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`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-defaultvalue) | `string` | Sets the initial value for uncontrolled usage. | | [`suffix`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-suffix) | `string` | Text content to render after the value. | | [`autocomplete`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-autocomplete) | `string` | A hint to the browser about the autofill value for the field. | | [`inputMode`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-inputmode) | `'decimal'` \| `'numeric'` | Hints at the type of virtual keyboard to display. | | [`labelAccessibilityVisibility`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-labelaccessibilityvisibility) | `'visible'` \| `'exclusive'` | Controls whether the label is visible or only available to assistive technology. | ### accessory The Polaris number field exposes an [`accessory`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#slots-propertydetail-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 ``. Use it for actions adjacent to the input, such as a "Use max" button: ## Adding an accessory to s-number-field ```tsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { return ( Use max ); } ``` For static unit indicators like `kg` or `%`, use the [`prefix`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-prefix) and [`suffix`](https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/forms/number-field#properties-propertydetail-suffix) props instead: ```tsx ``` *** ## Removed properties ### accessibility​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. ***