Appearance
UI: Polaris & App Bridge
Embedded apps should look and behave like part of Shopify Admin. Two libraries make that happen.
| Library | What it is |
|---|---|
| App Bridge | Loaded from Shopify's CDN. Connects your iframe to the Admin: title bar, nav menu, toasts, modals, resource pickers, and session tokens |
| Polaris web components | Shopify's design system as <s-*> custom elements. Matches the Admin look automatically |
Polaris React is deprecated
The old @shopify/polaris React library is deprecated, and its components will be removed in future majors. New work should use Polaris web components (<s-page>, <s-section>, <s-button>…).
A page with Polaris web components
tsx
export default function Index() {
const { orders } = useLoaderData<typeof loader>();
return (
<s-page heading="Recent orders">
<s-button slot="primary-action" onClick={sync}>Sync now</s-button>
<s-section heading="Last 10 orders">
<s-table>
<s-table-header-row>
<s-table-header>Order</s-table-header>
<s-table-header>Customer</s-table-header>
<s-table-header>Total</s-table-header>
</s-table-header-row>
<s-table-body>
{orders.map((o) => (
<s-table-row key={o.id}>
<s-table-cell>{o.name}</s-table-cell>
<s-table-cell>{o.customer?.displayName}</s-table-cell>
<s-table-cell>{o.total}</s-table-cell>
</s-table-row>
))}
</s-table-body>
</s-table>
</s-section>
</s-page>
);
}Migrating from Polaris React — the gotchas
- There is no
Card. Use<s-section>. - Multi-word props become camelCase attributes, and
urlbecomeshref. - Migrate a whole page shell at once. Don't mix the two systems on one page.
App Bridge APIs you'll use
ts
shopify.toast.show("Saved"); // toast
await shopify.resourcePicker({ type: "product" }); // native product picker
shopify.modal.show("my-modal"); // <ui-modal id="my-modal">
const token = await shopify.idToken(); // session token (rarely needed by hand)Navigation menu, in app.tsx:
tsx
<s-app-nav>
<s-link href="/app" rel="home">Home</s-link>
<s-link href="/app/settings">Settings</s-link>
</s-app-nav>Built for Shopify checks this
The badge needs the latest App Bridge. It also needs fast Admin Web Vitals: LCP ≤ 2.5 s, CLS ≤ 0.1, INP ≤ 200 ms at p75. Keep loaders lean.
Project step: render the orders from the API page in an
<s-table>, with a "Sync now" primary action that shows a toast.
Check yourself
- Which library gives you the session token?
- What replaces Polaris React's
Card?