---
title: Migrate Frame from Polaris React
description: >-
  Remove the Polaris React Frame after moving its host-level responsibilities to
  App Bridge and Polaris web components.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/frame
  md: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/frame.md
api_name: app-home
---

# Migrate Frame from Polaris React

Polaris React `Frame` has no replacement wrapper. In an embedded app, the Shopify admin and App Bridge provide the surrounding chrome. Migrate each responsibility that depends on `Frame`, and then render the app routes without it.

Don't replace `Frame` with a generic `div`, `s-box`, or compatibility component. Those wrappers don't reproduce its navigation, overlays, loading, or save-bar behavior.

***

## Migrate the app shell

The following example moves primary navigation to `s-app-nav`, moves the page title and content to Polaris web components, and removes the in-iframe shell.

## Migrating the embedded app shell

##### Polaris web components

```tsx
function AppShell() {
  return (
    <>
      <s-app-nav>
        <s-link href="/products">Products</s-link>
        <s-link href="/settings">Settings</s-link>
      </s-app-nav>
      <s-page heading="Products">
        <s-section>
          <s-paragraph>Manage products from this page.</s-paragraph>
        </s-section>
      </s-page>
    </>
  );
}
```

##### Polaris React

```tsx
import {Card, Frame, Navigation, Page, Text} from '@shopify/polaris';

export function AppShell() {
  const navigation = (
    <Navigation location="/products">
      <Navigation.Section
        items={[
          {label: 'Home', url: '/'},
          {label: 'Products', url: '/products'},
          {label: 'Settings', url: '/settings'},
        ]}
      />
    </Navigation>
  );

  return (
    <Frame navigation={navigation}>
      <Page title="Products">
        <Card>
          <Text as="p">Manage products from this page.</Text>
        </Card>
      </Page>
    </Frame>
  );
}
```

`s-app-nav` renders only in the Shopify admin shell, so this admin navigation example isn't available as an isolated live preview.

In a real app, keep `s-app-nav` mounted near the app root and render the active route below it. Each route can own its `s-page` heading, actions, and sections.

***

## Migrate Frame responsibilities

Remove `Frame` only after every responsibility used by the app has a destination:

| Frame responsibility | Polaris web components | Migration guidance |
| - | - | - |
| `navigation` | [`s-app-nav`](https://shopify.dev/docs/api/app-home/app-bridge-web-components/app-nav) | Render real `s-link` destinations and keep them synchronized with the app router. |
| `topBar` | The Shopify admin plus `s-page` | Move page context and actions to each route. Don't recreate an in-iframe top bar. |
| `contextualSaveBar` | [`data-save-bar`](https://shopify.dev/docs/api/app-home/app-bridge-web-components/save-bar) or the Save Bar API | Migrate dirty state, save, discard, and navigation protection together. |
| `Toast` descendants | [Toast API](https://shopify.dev/docs/api/app-home/apis/user-interface-and-interactions/toast-api) | Replace rendered toast state with `shopify.toast.show()`. |
| `Loading` descendants | [Loading API](https://shopify.dev/docs/api/app-home/apis/user-interface-and-interactions/loading-api) | Connect route-level loading state to `shopify.loading()`. |
| Modal and popover portals | `s-modal`, `s-popover`, or `s-menu` | Use documented overlay components so that they manage focus and dismissal. |
| `children` | App routes and page components | Render the existing route tree directly. |

Follow the linked component migration guide for each responsibility before removing the wrapper.

***

## Remove navigation shell state

`Frame` and `Navigation` often introduce state that opens or dismisses mobile navigation. Remove state and callbacks used only for that in-iframe shell. The Shopify admin owns the surrounding responsive navigation behavior.

Keep route state in the app router. Use real `href` values so that modified clicks, copied links, direct navigation, and browser history continue to work.

***

## Remove provider and style dependencies separately

Removing `Frame` doesn't mean every Polaris React dependency is gone. Keep `AppProvider` while a mounted route still renders components from `@shopify/polaris`. Remove Polaris styles and provider setup only after their final consumer is migrated.

Delete CSS that targets `.Polaris-Frame`, `.Polaris-Navigation`, or other Frame internals. Don't copy those internal selectors or layout variables into the new shell.

***

## Test the migration

* Open every primary navigation destination directly and through `s-app-nav`.
* Test browser back and forward navigation, modified clicks, and copied URLs.
* Verify route-level loading, toasts, save bars, modals, and popovers without `Frame`.
* Test keyboard focus after route changes and overlay dismissal.
* Resize the embedded app, and confirm that no in-iframe shell duplicates the surrounding Shopify admin.
* Run the app's production build and check the console for missing context or custom-element errors.

***

## Remove Polaris React

After all Frame responsibilities are migrated, remove the `Frame` import, wrapper, shell-only state, and internal CSS. Remove `@shopify/polaris` only after no other route in scope imports it.

***

## Related guidance

* [App nav](https://shopify.dev/docs/api/app-home/app-bridge-web-components/app-nav)
* [Migrate Navigation from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/navigation)
* [Migrate ContextualSaveBar from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/contextual-save-bar)
* [Migrate Toast from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/toast)
* [Migrate Loading from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/loading)
* [Remove AppProvider after migrating Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/app-provider)

***
