---
title: Migrate PageActions from Polaris React
description: >-
  Replace Polaris React PageActions with s-page action slots or an in-content
  s-button-group while preserving priority, state, and destructive safeguards.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/page-actions
  md: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/page-actions.md
api_name: app-home
---

# Migrate Page​Actions from Polaris React

Polaris React `PageActions` rendered primary and secondary action descriptors in page content. Move actions that define the page into supported `s-page` slots. Keep an `s-button-group` in content only when the actions belong to a form section or local workflow rather than the whole page.

***

## Move page-level actions into s-page

The following page slots the primary and overflow trigger buttons. The `s-menu` remains an unslotted sibling because the secondary-actions slot accepts button controls, not the menu itself.

## Migrating page-level actions

##### Polaris web components

```tsx
export function ProductActions({onCreate, onDuplicate, onArchive}) {
  return (
    <s-page heading="Products">
      <s-button slot="primary-action" variant="primary" onClick={onCreate}>
        Create product
      </s-button>
      <s-button slot="secondary-actions" commandFor="product-actions">
        More actions
      </s-button>
      <s-menu id="product-actions" accessibilityLabel="Product actions">
        <s-button onClick={onDuplicate}>Duplicate product</s-button>
        <s-button onClick={onArchive}>Archive product</s-button>
      </s-menu>
      <s-section heading="All products">
        <s-paragraph>Manage the products available through your app.</s-paragraph>
      </s-section>
    </s-page>
  );
}
```

##### Polaris React

```tsx
import {PageActions} from '@shopify/polaris';

export function ProductActions({onCreate, onDuplicate, onArchive}) {
  return (
    <PageActions
      primaryAction={{
        content: 'Create product',
        onAction: onCreate,
      }}
      secondaryActions={[
        {content: 'Duplicate product', onAction: onDuplicate},
        {content: 'Archive product', onAction: onArchive},
      ]}
    />
  );
}
```

***

## Replace action descriptors

| Polaris React action field | Polaris web components | Migration notes |
| - | - | - |
| `primaryAction.content` | Primary button child text | Use one clear verb and object. |
| `primaryAction.onAction` | `onClick` | Keep pending protection and result handling in the operation. |
| `primaryAction.loading` | `loading` | Prevent repeat submission while the same operation is pending. |
| `primaryAction.disabled` | `disabled` | Preserve the condition and explain unmet requirements near the relevant content. |
| `primaryAction.tone="critical"` | `tone="critical"` | Confirm destructive operations when the result is difficult to reverse. |
| `secondaryActions` | Explicit secondary buttons | Keep frequent actions visible. Move related overflow actions into an `s-menu`. |
| Action `url` | `href` on a link or button | Use a real URL for navigation so modified clicks and copied links work. |
| Action `icon` | `icon` | Use a documented icon name and keep visible text unless the action remains unambiguous without it. |
| Action `accessibilityLabel` | `accessibilityLabel` only when needed | Prefer visible text that already provides a complete name. |

Don't keep the old descriptor objects behind a compatibility wrapper. Explicit elements make placement, semantics, and state visible at the call site.

***

## Choose page or in-content placement

Use `slot="primary-action"` and `slot="secondary-actions"` when the actions apply to the whole route, such as creating a product or opening page-wide settings.

Use `s-button-group` in page content when the actions apply to a local section, such as submitting or resetting one form. A form submit button should use `type="submit"` and remain inside its owning form so Enter-key submission and validation work.

Avoid rendering the same action in both the title bar and the page body. If a former `PageActions` group appears only at the bottom of a long form, decide whether it is the form's submit group or the page's primary action, then keep one source of truth.

***

## Preserve destructive and asynchronous behavior

For each action:

1. Keep authorization and precondition checks in the backend operation.
2. Set pending state before starting the request and block duplicate execution.
3. Confirm destructive actions when the result is difficult to reverse.
4. On success, update or revalidate the affected data and show appropriate feedback.
5. On failure, preserve the merchant's input and provide a retry path.

Changing action placement doesn't change the safety requirements of the operation.

***

## Test the migration

* Run every action through enabled, disabled, loading, success, and failure states.
* Verify destructive actions require the intended confirmation and can't run twice.
* Test navigation actions with direct, modified, and copied links.
* Submit forms by button and Enter key.
* Test action order and overflow behavior at narrow widths.
* Verify accessible names and keyboard focus after menus and dialogs close.

***

## Remove Polaris React

After every call site is migrated, remove `PageActions`, descriptor builders, and duplicate action state. Remove `@shopify/polaris` only after no other route in scope imports it.

***

## Related guidance

* [Page component](https://shopify.dev/docs/api/app-home/web-components/layout-and-structure/page)
* [Button group component](https://shopify.dev/docs/api/app-home/web-components/actions/button-group)
* [Migrate Page from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/page)
* [Migrate ActionMenu from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/action-menu)

***
