Skip to main content

Migrate BlockStack from Polaris React

The Polaris stack component arranges related children along the block or inline axis. It replaces the Polaris React BlockStack component from @shopify/polaris and is available as <s-stack>.

s-stack defaults to direction="block", matching BlockStack. Use s-grid instead when children form columns or named page regions rather than one flexible flow.

Migrating BlockStack to s-stack

export function SalesChannelSettings() {
return (
<s-stack direction="block" gap="base" alignItems="stretch">
<s-heading>Online store</s-heading>
<s-text>Manage the products available to this sales channel.</s-text>
<s-button variant="secondary" inlineSize="fill">
Manage products
</s-button>
</s-stack>
);
}
import {BlockStack, Button, Text} from '@shopify/polaris';

export function SalesChannelSettings() {
return (
<BlockStack gap="400" inlineAlign="stretch">
<Text as="h2" variant="headingSm">
Online store
</Text>
<Text as="p">
Manage the products available to this sales channel.
</Text>
<Button>Manage products</Button>
</BlockStack>
);
}

Preview


The following properties are different in the Polaris stack component.

Rename align to justifyContent. It distributes children on the stack's main axis. The existing values map directly.

Polaris ReactPolaris web components
align="start"justifyContent="start"
align="center"justifyContent="center"
align="end"justifyContent="end"
align="space-around"justifyContent="space-around"
align="space-between"justifyContent="space-between"
align="space-evenly"justifyContent="space-evenly"

For a block stack, main-axis distribution is vertical. It only creates visible extra space when the stack has more block size than its children need.

Rename inlineAlign to alignItems. It aligns children across a block stack's inline axis.

Polaris ReactPolaris web components
inlineAlign="start"alignItems="start"
inlineAlign="center"alignItems="center"
inlineAlign="end"alignItems="end"
inlineAlign="baseline"alignItems="baseline"
inlineAlign="stretch"alignItems="stretch"

alignItems="stretch" stretches the s-button host, but the button control keeps its automatic inline size. Add inlineSize="fill" to a button that needs to fill the stretched stack width.

Keep the gap property, but replace the old numeric spacing token with its Polaris web component value.

Polaris React valuePolaris web components
"0" or omitted"none" or omitted
"050""small-500"
"100""small-400"
"150""small-300"
"200""small-200"
"300""small-100"
"400""base"
"500""large"
"600""large-200"
"800""large-300"
"1000""large-400"
"1200""large-500"

The old "025", "250", "700", "1600", "2000", "2400", "2800", and "3200" values don't have exact equivalents. Choose the nearest supported value based on how closely the content is related, and verify the result in context. For very large separation, use distinct page regions or sections instead of a stack with an oversized gap.

Replace responsive objects with the documented responsive value string syntax. Don't pass {xs, sm, md, lg, xl} objects to s-stack.

Anchor to role and ARIA attributesrole and ARIA attributes

Rename supported container semantics to accessibilityRole:

Polaris ReactPolaris web components
role="status"accessibilityRole="status"
role="presentation"accessibilityRole="presentation"
aria-label="…"accessibilityLabel="…"
aria-hidden={true}accessibilityVisibility="hidden"

The old menu, listbox, combobox, and group roles aren't supported on s-stack. Migrate the complete interaction to the corresponding component, such as s-menu, s-select, s-choice-list, or a labeled s-section. Don't preserve an interactive ARIA role on a visual layout primitive.

Keep id when another element or app logic still references it. Remove generated IDs that only supported Polaris React styling.

Move the children into the default slot and migrate each nested Polaris React component. Their order remains their reading, focus, and visual order unless the layout explicitly changes direction at a responsive breakpoint.


s-stack doesn't accept an as property. Choose a semantic component instead of changing the stack's underlying tag.

Polaris React valueMigration
"div"Use s-stack.
"span"Use s-text for inline text; use s-stack only when the content is a layout group.
"ul"Use s-unordered-list with s-list-item children.
"ol"Use s-ordered-list with s-list-item children.
"li"Use s-list-item inside a list.
"fieldset"Use s-choice-list for related choices, or retain a semantic HTML fieldset around the appropriate web components when needed.

s-stack doesn't support reverseOrder. Put children in the intended reading and focus order in the DOM. If the old visual order differed from the DOM order, treat that as an accessibility bug and correct it during migration.

When the order changes responsively for a legitimate layout, use a grid or render a structure whose DOM order remains understandable at every size. Don't use CSS order to move focusable controls away from their reading order.


The Polaris stack component also provides properties that don't exist on Polaris React BlockStack:

PropertyDescription
directionSets "block" or "inline" and accepts responsive values. It defaults to "block".
rowGap and columnGapOverride one axis of gap when the direction changes or inline content wraps.
alignContentDistributes multiple wrapped lines; it doesn't replace alignItems for a single line.
Box-style propertiesAdd supported padding, background, border, size, overflow, and visibility directly when the stack owns that visual boundary.

  • Verify the stack at every responsive width used by the embedded iframe.
  • Check the numeric-to-scale gap replacement in its actual content hierarchy.
  • Test start and end alignment in both left-to-right and right-to-left languages.
  • Confirm list, choice, menu, and status semantics with a screen reader after replacing as and role.
  • Verify DOM, reading, and focus order after removing reverseOrder.
  • Remove responsive object helpers and the Polaris React BlockStack import after their final consumers are migrated.


Was this page helpful?