Skip to main content

Migrate to the Polaris text field components

The previous TextField component has been split into dedicated components based on the type prop. Each type now has its own Polaris web component, available in API versions 2025-10 and newer.


Anchor to Component mapping by typeComponent mapping by type

The type prop you previously set on TextField determines which new component to use:

Previous typeNew componentDocumentation
'text' (default)<s-text-field>Text field
'email'<s-email-field>Email field
'number'<s-number-field>Number field
'telephone'<s-phone-field>Phone field. See also the phone field migration guide for property-level changes.
No previous equivalent<s-url-field>URL field. New component — previously, URL inputs used <TextField type="text">. Switch to <s-url-field> for built-in URL validation and keyboard.
multiline prop<s-text-area>Text area

Migrating TextField type='email' to s-email-field

import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
render(<Extension />, document.body);
}

function Extension() {
return (
<s-email-field
label="Email address"
/>
);
}
import {
reactExtension,
TextField,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);

function Extension() {
return (
<TextField
label="Email address"
type="email"
/>
);
}

Migrating TextField type='number' to s-number-field

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"
/>
);
}
import {
reactExtension,
TextField,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);

function Extension() {
return (
<TextField
label="Quantity"
type="number"
/>
);
}

Migrating TextField type='telephone' to s-phone-field

import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
render(<Extension />, document.body);
}

function Extension() {
return (
<s-phone-field
label="Phone number"
/>
);
}
import {
reactExtension,
TextField,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);

function Extension() {
return (
<TextField
label="Phone number"
type="telephone"
/>
);
}

Migrating multiline TextField to s-text-area

import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
render(<Extension />, document.body);
}

function Extension() {
return (
<s-text-area
label="Order notes"
rows={3}
/>
);
}
import {
reactExtension,
TextField,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);

function Extension() {
return (
<TextField
label="Order notes"
multiline={3}
/>
);
}

The following table summarizes which new components support the icon prop and the accessory slot:

Componenticon propaccessory slot
<s-text-field>YesYes
<s-email-field>NoYes
<s-number-field>YesYes
<s-phone-field>NoYes
<s-url-field>NoYes
<s-text-area>NoNo

The previous TextField readonly prop is now called readOnly (camelCase) on all field components.

The previous TextField accessory prop has been replaced with the accessory slot on <s-text-field>, <s-email-field>, <s-number-field>, <s-phone-field>, and <s-url-field>. Place an element with slot="accessory" as a child of the field. The accessory slot isn't available on <s-text-area> — to position supplementary content next to a text area, use layout components.

Migrating accessory from prop to slot

import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
render(<Extension />, document.body);
}

function Extension() {
return (
<s-text-field label="Search products">
<s-icon slot="accessory" type="info" />
</s-text-field>
);
}
import {
reactExtension,
TextField,
Icon,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);

function Extension() {
return (
<TextField
label="Search products"
accessory={<Icon source="info" />}
/>
);
}

The icon prop is supported only on <s-text-field> and <s-number-field>. On those components, update icon names to their Polaris web component equivalents — they use the same icon names as the Polaris icon component. The icon prop isn't available on <s-email-field>, <s-phone-field>, or <s-url-field>. For a trailing icon (the previous icon={{source: '...', position: 'end'}}), use the accessory slot — it only renders at the end of the field. A leading-position icon (the previous default) has no direct equivalent on those components; place an icon next to the field using layout components, or omit it.

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 iconNew 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'

Migrating icon values

import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
render(<Extension />, document.body);
}

function Extension() {
return (
<s-text-field
label="Search products"
icon="search"
/>
);
}
import {
reactExtension,
TextField,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);

function Extension() {
return (
<TextField
label="Search products"
icon="magnify"
/>
);
}

Migrating a trailing icon to the accessory slot

import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
render(<Extension />, document.body);
}

function Extension() {
return (
<s-email-field label="Email address">
<s-icon slot="accessory" type="info" />
</s-email-field>
);
}
import {
reactExtension,
TextField,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
'purchase.checkout.block.render',
() => <Extension />,
);

function Extension() {
return (
<TextField
label="Email address"
type="email"
icon={{source: 'info', position: 'end'}}
/>
);
}

The following properties aren't supported on any of the new field components:

  • type — no longer needed. Use the dedicated component for your input type instead.
  • multiline — no longer supported. Use <s-text-area> instead.
  • accessibilityDescription — no longer supported. Use the label prop to provide context.
  • controlledValue — no longer supported. Use the standard value management pattern.

The new field components introduce the following properties:

New propTypeDescription
labelAccessibilityVisibility'visible' | 'exclusive'Controls whether the label is visually displayed or only available to screen readers. Default is 'visible'.
minLengthnumberSpecifies the minimum number of characters required.
defaultValuestringInitial value for uncontrolled usage.

Was this page helpful?