---
title: Migrate Page to the Polaris page component
description: >-
  Learn how to migrate the Page component to Polaris web components in customer
  account UI extensions.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/customer-accounts/migrate-to-web-components/page
  md: >-
    https://shopify.dev/docs/apps/build/customer-accounts/migrate-to-web-components/page.md
---

# Migrate Page to the Polaris page component

The Polaris page component is the outer wrapper of a full page, including the page heading, subheading, and page-level actions. It replaces the previous [`Page`](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/components/structure/page) component and is available as [`<s-page>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page) in API versions 2025-10 and newer.

## Migrating Page to s-page

##### Latest (Preact)

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

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

function Extension() {
  return (
    <s-page heading="Order #1411" subheading="Confirmed Oct 5">
      <s-button slot="primary-action" onClick={() => {}}>
        Buy again
      </s-button>
      <s-text>Content</s-text>
    </s-page>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  Page,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.page.render',
  () => <Extension />,
);

function Extension() {
  return (
    <Page
      title="Order #1411"
      subtitle="Confirmed Oct 5"
      primaryAction={<Button onPress={() => {}}>Buy again</Button>}
    >
      Content
    </Page>
  );
}
```

***

## Updated properties

### title

The previous `Page` `title` prop has been renamed to [`heading`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#properties-propertydetail-heading). It's now optional.

### subtitle

The previous `Page` `subtitle` prop has been renamed to [`subheading`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#properties-propertydetail-subheading).

### primary​Action

The previous `Page` `primaryAction` prop accepted a `RemoteFragment` containing one or more `Button` components, optionally grouped behind an overflow label. The Polaris page component splits this into two [slots](https://shopify.dev/docs/api/polaris/using-polaris-web-components#slots):

* Place the first action in the `primary-action` slot. This slot accepts a single button and renders it as the prominent primary action.
* Place any additional actions in the `secondary-actions` slot.

| Previous prop | New slot |
| - | - |
| `primaryAction={<Button>…</Button>}` (single button) | `<s-button slot="primary-action">…</s-button>` |
| `primaryAction={<><Button>A</Button><Button>B</Button></>}` (multiple buttons) | First button in the `primary-action` slot, remaining buttons in the `secondary-actions` slot |

Buttons in the `primary-action` and `secondary-actions` slots share the same supported properties. See [Primary and secondary slot button properties](#primary-and-secondary-slot-button-properties).

## Migrating multiple primary actions to slots

##### Latest (Preact)

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

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

function Extension() {
  return (
    <s-page heading="Order #1411">
      <s-button slot="primary-action" onClick={() => {}}>
        Buy again
      </s-button>
      <s-button slot="secondary-actions" onClick={() => {}}>
        Track package
      </s-button>
      <s-button slot="secondary-actions" onClick={() => {}}>
        Return items
      </s-button>
      <s-text>Order details</s-text>
    </s-page>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  Page,
  TextBlock,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.page.render',
  () => <Extension />,
);

function Extension() {
  return (
    <Page
      title="Order #1411"
      primaryAction={
        <>
          <Button onPress={() => {}}>Buy again</Button>
          <Button onPress={() => {}}>Track package</Button>
          <Button onPress={() => {}}>Return items</Button>
        </>
      }
    >
      <TextBlock>Order details</TextBlock>
    </Page>
  );
}
```

### secondary​Action

The previous `Page` `secondaryAction` prop rendered as a back-arrow breadcrumb link in the page header. It's been renamed to the `breadcrumb-actions` slot. Place an `<s-button>` in the slot to replace the previous prop.

| Previous prop | New slot |
| - | - |
| `secondaryAction={<Button>Label</Button>}` | `<s-button slot="breadcrumb-actions" accessibilityLabel="Label" />` |

Buttons in the `breadcrumb-actions` slot only support a restricted set of properties, and any children are discarded. Use [`accessibilityLabel`](#breadcrumbactionsslotbuttonproperties-propertydetail-accessibilitylabel) to describe the breadcrumb's destination. See [Breadcrumb slot button properties](#breadcrumb-slot-button-properties) for the full restricted set.

## Migrating secondaryAction to breadcrumb-actions

##### Latest (Preact)

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

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

function Extension() {
  return (
    <s-page heading="Order #1411">
      <s-button
        slot="breadcrumb-actions"
        accessibilityLabel="Back to orders"
        href="shopify:customer-account/orders"
      />
      <s-text>Order details</s-text>
    </s-page>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  Page,
  TextBlock,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.page.render',
  () => <Extension />,
);

function Extension() {
  return (
    <Page
      title="Order #1411"
      secondaryAction={
        <Button to="shopify:customer-account/orders">
          Orders
        </Button>
      }
    >
      <TextBlock>Order details</TextBlock>
    </Page>
  );
}
```

***

## Removed properties

### primary​Action​Label and primary​Action​Accessibility​Label

The previous `primaryActionLabel` and `primaryActionAccessibilityLabel` props set a custom label on the overflow trigger that grouped multiple primary action buttons together. With the new slot split (see [`primaryAction`](#primaryaction)), actions render directly into the `primary-action` and `secondary-actions` slots and the overflow trigger is managed automatically.

When the `secondary-actions` slot contains multiple buttons, the extras collapse into a menu with a built-in trigger. The `<s-page>` web component doesn't expose a prop to customize that trigger's label. If you need control over the label (the equivalent of the previous `primaryActionLabel`), replace the slot's built-in trigger with your own button that targets an [`<s-menu>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/menu) with [`commandFor`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#properties-propertydetail-commandfor).

## Customizing the secondary actions menu trigger label

##### Latest (Preact)

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

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

function Extension() {
  return (
    <s-page heading="Order #1411">
      <s-button slot="primary-action" onClick={() => {}}>
        Buy again
      </s-button>
      <s-button
        slot="secondary-actions"
        commandFor="order-actions-menu"
      >
        Manage
      </s-button>
      <s-menu id="order-actions-menu">
        <s-button>Track package</s-button>
        <s-button>Return items</s-button>
      </s-menu>
      <s-text>Order details</s-text>
    </s-page>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  Page,
  TextBlock,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.page.render',
  () => <Extension />,
);

function Extension() {
  return (
    <Page
      title="Order #1411"
      primaryActionLabel="Manage"
      primaryAction={
        <>
          <Button onPress={() => {}}>Buy again</Button>
          <Button onPress={() => {}}>Track package</Button>
          <Button onPress={() => {}}>Return items</Button>
        </>
      }
    >
      <TextBlock>Order details</TextBlock>
    </Page>
  );
}
```

### loading

The previous `loading` prop rendered a loading state on the page-owned UI elements, such as the action buttons in the header. The Polaris page doesn't have a page-level loading state. If you need to indicate loading, set [`loading`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#primaryactionslotbuttonproperties-propertydetail-loading) on the button inside `primary-action`, or render an [`<s-spinner>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/loading-and-feedback/spinner) alongside the content.

***

## Primary and secondary slot button properties

Buttons placed in the `primary-action` and `secondary-actions` slots only support a subset of the [`<s-button>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button) properties.

### Removed slot button properties

The following props from the previous `Button` component are no longer supported inside action slots:

| Removed prop | Migration notes |
| - | - |
| `loadingLabel` | Removed. Use the default loading indicator by setting [`loading`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#primaryactionslotbuttonproperties-propertydetail-loading). |
| `overlay` | Removed. Use [`command`](#new-slot-button-properties) and [`commandFor`](#new-slot-button-properties) to target a sibling component by ID. |

To open a modal when the slot button is activated, target a sibling [`<s-modal>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/overlays/modal) by ID. To close the modal, use `command="--hide"` with `commandFor`, or call the modal's [`hideOverlay()`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/overlays/modal#methods-propertydetail-hideoverlay) method.

## Migrating overlay to command and commandFor

##### Latest (Preact)

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

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

function Extension() {
  return (
    <s-page heading="Order #1411">
      <s-button
        slot="primary-action"
        command="--show"
        commandFor="cancel-order"
      >
        Cancel order
      </s-button>
      <s-modal id="cancel-order" heading="Cancel order">
        <s-text>Are you sure? This action can't be undone.</s-text>
        <s-button
          slot="primary-action"
          command="--hide"
          commandFor="cancel-order"
        >
          Confirm cancellation
        </s-button>
      </s-modal>
      <s-text>Order details</s-text>
    </s-page>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  Modal,
  Page,
  TextBlock,
  reactExtension,
  useApi,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.page.render',
  () => <Extension />,
);

function Extension() {
  const {ui} = useApi();

  return (
    <Page
      title="Order #1411"
      primaryAction={
        <Button
          overlay={
            <Modal
              id="cancel-order"
              title="Cancel order"
              primaryAction={
                <Button onPress={() => ui.overlay.close('cancel-order')}>
                  Confirm cancellation
                </Button>
              }
            >
              <TextBlock>
                Are you sure? This action can't be undone.
              </TextBlock>
            </Modal>
          }
        >
          Cancel order
        </Button>
      }
    >
      <TextBlock>Order details</TextBlock>
    </Page>
  );
}
```

### Updated slot button properties

#### on​Press

The previous `Button` `onPress` prop is now called [`onClick`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#primaryactionslotbuttonproperties-propertydetail-click).

#### to

The previous `Button` `to` prop is now called [`href`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#primaryactionslotbuttonproperties-propertydetail-href).

### New slot button properties

Slot buttons support the following new properties:

| New prop | Description |
| - | - |
| [`command`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#primaryactionslotbuttonproperties-propertydetail-command) | Sets the action to run on the target component when the button is activated. |
| [`commandFor`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#primaryactionslotbuttonproperties-propertydetail-commandfor) | Sets the ID of the target component for the command. |

***

## Breadcrumb slot button properties

Buttons placed in the `breadcrumb-actions` slot render as a back-arrow breadcrumb link in the page header and only support a restricted set of [`<s-button>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button) properties. Children aren't supported — describe the destination with [`accessibilityLabel`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#breadcrumbactionsslotbuttonproperties-propertydetail-accessibilitylabel) instead.

### Supported properties

| Prop | Description |
| - | - |
| [`accessibilityLabel`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#breadcrumbactionsslotbuttonproperties-propertydetail-accessibilitylabel) | Required. A label that describes the breadcrumb's destination to assistive technologies. The button's text content is discarded, so this label is what screen readers announce. |
| [`onClick`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#breadcrumbactionsslotbuttonproperties-propertydetail-click) | A callback that fires when the breadcrumb is activated. Replaces the previous `Button` `onPress` prop. |
| [`href`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/page#breadcrumbactionsslotbuttonproperties-propertydetail-href) | The URL to navigate to when the breadcrumb is activated. Replaces the previous `Button` `to` prop. |

All other `Button` props from the previous API are unsupported in the `breadcrumb-actions` slot.

***
