---
title: Migrate Banner from Polaris React
description: >-
  Learn how to migrate the Polaris React Banner component to Polaris web
  components in an embedded app.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/banner
  md: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/banner.md
api_name: app-home
---

# Migrate Banner from Polaris React

The Polaris banner component communicates important contextual feedback and next steps. It replaces the Polaris React `Banner` component from `@shopify/polaris` and is available as [`<s-banner>`](https://shopify.dev/docs/api/app-home/web-components/feedback-and-status-indicators/banner).

Keep field validation next to its field. Use `s-banner` when the message affects a section or the wider task.

## Migrating Banner to s-banner

##### Polaris web components

```tsx
import {useState} from 'react';

export function ShippingWeightBanner() {
  const [hidden, setHidden] = useState(false);

  return (
    <s-banner
      heading="127 products missing shipping weights"
      tone="warning"
      dismissible
      hidden={hidden}
      onDismiss={() => setHidden(true)}
    >
      Products without weights may show inaccurate shipping rates.
      <s-button
        slot="secondary-actions"
        variant="secondary"
        href="/products?filter=missing-weights"
      >
        Review products
      </s-button>
      <s-button
        slot="secondary-actions"
        variant="secondary"
        href="/settings/shipping"
      >
        Setup guide
      </s-button>
    </s-banner>
  );
}
```

##### Polaris React

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

interface ShippingWeightBannerProps {
  onDismiss(): void;
}

export function ShippingWeightBanner({
  onDismiss,
}: ShippingWeightBannerProps) {
  return (
    <Banner
      title="127 products missing shipping weights"
      tone="warning"
      onDismiss={onDismiss}
      action={{
        content: 'Review products',
        url: '/products?filter=missing-weights',
      }}
      secondaryAction={{
        content: 'Setup guide',
        url: '/settings/shipping',
      }}
    >
      Products without weights may show inaccurate shipping rates.
    </Banner>
  );
}
```

***

## Updated properties

The following properties are different in the Polaris banner component.

### title

Rename `title` to [`heading`](https://shopify.dev/docs/api/app-home/web-components/feedback-and-status-indicators/banner#banner-propertydetail-heading). If the old banner intentionally had no title, omit `heading`; don't invent a heading only to fill the property.

### tone

The four Polaris React tone values remain available. The default has changed, so make the old default explicit when its informational meaning matters.

| Polaris React value | Polaris web components | Migration notes |
| - | - | - |
| Omitted | `tone="info"` | Polaris React defaulted to `info`; `s-banner` defaults to `auto`. |
| `"info"` | `"info"` | No change is needed. |
| `"success"` | `"success"` | No change is needed. |
| `"warning"` | `"warning"` | No change is needed. |
| `"critical"` | `"critical"` | No change is needed. |

Choose the tone from the message's meaning rather than its preferred color. The new `auto` value is appropriate only when the banner doesn't communicate a specific success, warning, or critical state.

### children

Move the banner's children into the default slot. Plain text can remain as text. Replace nested Polaris React components, such as lists or links, with their Polaris web component equivalents.

### action and secondary​Action

Replace action descriptor objects with up to two [`s-button`](https://shopify.dev/docs/api/app-home/web-components/actions/button) children in the `secondary-actions` slot. Use `variant="secondary"` or `variant="auto"`.

| Polaris React action field | `s-button` migration |
| - | - |
| `content` | Move the string into the button's children. |
| `onAction` | Rename to `onClick`. |
| `url` | Rename to `href`. |
| `external: true` | Set `target="_blank"`. |
| `target` | Keep `target`. |
| `disabled` | Keep `disabled`. |
| `loading` | Keep `loading`. |
| `accessibilityLabel` | Keep `accessibilityLabel` when the visible label needs more context. |

Don't pass the old object through a compatibility wrapper. Rendering buttons as children makes their labels, navigation, loading state, and event handling independently testable.

### on​Dismiss

Replace `onDismiss` with the `dismissible` property and the `dismiss` event. In React, use `onDismiss={handleDismiss}`. The banner hides itself after dismissal; when React owns visibility, also set `hidden` to `true` in the handler so app state matches the rendered state.

Use `afterhide` instead when cleanup must wait until the hide transition finishes.

***

## Removed properties

### icon

`s-banner` doesn't accept a custom icon. It chooses an icon from `tone`. Remove imported Polaris React icon sources, and put any essential meaning from a custom icon into the heading or body text.

### hide​Icon

`s-banner` doesn't support hiding its tone icon. Don't reproduce the banner with custom boxes only to remove the icon. If the content doesn't need banner semantics or visual prominence, migrate it to normal content in an [`s-section`](https://shopify.dev/docs/api/app-home/web-components/layout-and-structure/section) or [`s-box`](https://shopify.dev/docs/api/app-home/web-components/layout-and-structure/box).

### stop​Announcements

`s-banner` doesn't expose an announcement override. If `stopAnnouncements` prevented frequently changing or non-urgent content from being announced, don't update that content inside a banner. Use normal page content, or update the banner only when there is a new message that merchants need to hear.

***

## New properties and events

| Property or event | Description |
| - | - |
| `dismissible` | Shows the built-in dismiss button independently from the event handler. |
| `hidden` | Controls whether the banner is visible and supports app-owned dismissal state. |
| `tone="auto"` | Uses the default contextual treatment when no specific semantic tone applies. |
| `afterhide` event | Runs after the banner finishes hiding. |

***

## Test the migration

* Verify every banner tone still matches the message's meaning, especially banners that previously omitted `tone`.
* Test action navigation, click handlers, disabled state, and loading state.
* Dismiss the banner and confirm both the rendered banner and app-owned state remain hidden.
* Verify any persisted dismissal still survives the same reloads or sessions as before; `s-banner` doesn't persist it.
* Check the message with a screen reader, especially call sites that used `stopAnnouncements`.
* Remove unused Polaris React action objects, icon imports, and the `Banner` import after their final consumers are migrated.

***

## Related guidance

* [Banner component](https://shopify.dev/docs/api/app-home/web-components/feedback-and-status-indicators/banner)
* [Banner best practices](https://shopify.dev/docs/api/app-home/web-components/feedback-and-status-indicators/banner#best-practices)
* [Migrate from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react)

***
