Skip to main content

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.


Anchor to Migrate the app shellMigrate 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

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>
</>
);
}
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.


Anchor to Migrate Frame responsibilitiesMigrate Frame responsibilities

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

Frame responsibilityPolaris web componentsMigration guidance
navigations-app-navRender real s-link destinations and keep them synchronized with the app router.
topBarThe Shopify admin plus s-pageMove page context and actions to each route. Don't recreate an in-iframe top bar.
contextualSaveBardata-save-bar or the Save Bar APIMigrate dirty state, save, discard, and navigation protection together.
Toast descendantsToast APIReplace rendered toast state with shopify.toast.show().
Loading descendantsLoading APIConnect route-level loading state to shopify.loading().
Modal and popover portalss-modal, s-popover, or s-menuUse documented overlay components so that they manage focus and dismissal.
childrenApp routes and page componentsRender the existing route tree directly.

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


Anchor to Remove navigation shell stateRemove 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.


Anchor to Remove provider and style dependencies separatelyRemove 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.


  • 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.

Anchor to Remove Polaris ReactRemove 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.



Was this page helpful?