---
title: Migrate ResourceItem to the Polaris section component
description: >-
  Learn how to migrate the ResourceItem component to Polaris web components in
  customer account UI extensions.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/customer-accounts/migrate-to-web-components/resource-item
  md: >-
    https://shopify.dev/docs/apps/build/customer-accounts/migrate-to-web-components/resource-item.md
---

# Migrate ResourceItem to the Polaris section component

The Polaris section component groups related content inside a bordered container with an optional heading and action slots. It replaces the previous [`ResourceItem`](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/components/actions/resourceitem) component and is available as [`<s-section>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/section) in API versions 2025-10 and newer.

## Migrating ResourceItem to s-section

##### Latest (Preact)

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-section heading="Order #1001">
      <s-text>Placed on April 12, 2026</s-text>
      <s-button slot="primary-action" variant="primary">
        Buy again
      </s-button>
      <s-button slot="secondary-actions">View details</s-button>
    </s-section>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  ResourceItem,
  Text,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.profile.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <ResourceItem
      action={
        <>
          <Button kind="primary">Buy again</Button>
          <Button kind="secondary">View details</Button>
        </>
      }
    >
      <Text>Order #1001</Text>
      <Text>Placed on April 12, 2026</Text>
    </ResourceItem>
  );
}
```

***

## Updated properties

The following properties are different in the Polaris section component.

### action

The previous `ResourceItem` `action` prop accepted a fragment of `Button` components that were rendered alongside the item's content. On the Polaris section, use the [`primary-action`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/section#slots-propertydetail-primary-action) and [`secondary-actions`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/section#slots-propertydetail-secondary-actions) slots instead. Assign a single button to `primary-action` and one or more buttons to `secondary-actions` using the `slot` attribute.

## Migrating action to slots

##### Latest (Preact)

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-section heading="Order #1001">
      <s-text>Placed on April 12, 2026</s-text>
      <s-button slot="primary-action" variant="primary">
        Buy again
      </s-button>
      <s-button slot="secondary-actions">Track shipment</s-button>
      <s-button slot="secondary-actions">Return</s-button>
    </s-section>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  ResourceItem,
  Text,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.profile.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <ResourceItem
      action={
        <>
          <Button kind="primary">Buy again</Button>
          <Button kind="secondary">Track shipment</Button>
          <Button kind="secondary">Return</Button>
        </>
      }
    >
      <Text>Order #1001</Text>
      <Text>Placed on April 12, 2026</Text>
    </ResourceItem>
  );
}
```

***

## Button changes in action slots

Buttons placed in the `primary-action` and `secondary-actions` slots use the updated [`<s-button>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button) API. The following properties are different from the previous `Button` used inside `action`.

### kind

The previous `Button` `kind` prop is now [`variant`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#properties-propertydetail-variant). Use the following mapping:

| Previous `kind` | New `variant` |
| - | - |
| `'primary'` | `'primary'` |
| `'secondary'` | `'secondary'` |
| `'plain'` | Removed. |

### on​Press

The previous `Button` `onPress` prop is now called [`onClick`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#events-propertydetail-click).

### to

The previous `Button` `to` prop is now called [`href`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#properties-propertydetail-href).

### overlay

The previous `Button` `overlay` prop has been removed. To open a modal from a button in the `primary-action` or `secondary-actions` slot, use [`command`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#properties-propertydetail-command) and [`commandFor`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#properties-propertydetail-commandfor) to target a sibling modal by ID.

## Migrating overlay to command

##### Latest (Preact)

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <>
      <s-section heading="Order #1001">
        <s-text>Placed on April 12, 2026</s-text>
        <s-button
          slot="primary-action"
          variant="primary"
          command="--show"
          commandFor="order-details-modal"
        >
          View details
        </s-button>
      </s-section>
      <s-modal id="order-details-modal" heading="Order details">
        <s-text>Your order ships in 2 to 4 business days.</s-text>
      </s-modal>
    </>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  Modal,
  ResourceItem,
  Text,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.profile.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <ResourceItem
      action={
        <Button
          kind="primary"
          overlay={
            <Modal id="order-details-modal" title="Order details">
              <Text>Your order ships in 2 to 4 business days.</Text>
            </Modal>
          }
        >
          View details
        </Button>
      }
    >
      <Text>Order #1001</Text>
      <Text>Placed on April 12, 2026</Text>
    </ResourceItem>
  );
}
```

### loading​Label

The previous `Button` `loadingLabel` prop has been removed.

***

## New properties

The Polaris section component introduces the following new properties:

| New prop | Type | Description |
| - | - | - |
| [`heading`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/section#properties-propertydetail-heading) | `string` | Sets the section's visible heading. |
| [`id`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/section#properties-propertydetail-id) | `string` | A unique identifier for the section. |

***

## Removed properties

### on​Press and to

The previous `ResourceItem` `onPress` and `to` props made the whole item interactive or turned it into a link. The Polaris section is purely structural and doesn't handle interaction directly. Wrap the content you want to make interactive in [`<s-clickable>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/clickable): set [`href`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/clickable#properties-propertydetail-href) to replace `to`, or read presses from its [`click`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/clickable#events-propertydetail-click) event to replace `onPress`.

Buttons in the `primary-action` and `secondary-actions` slots stay interactive on their own and don't need to be wrapped.

## Migrating onPress and to to s-clickable

##### Latest (Preact)

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-section heading="Order #1001">
      <s-clickable href="shopify:customer-account/orders/1001">
        <s-text>Placed on April 12, 2026</s-text>
      </s-clickable>
      <s-button slot="primary-action" variant="primary">
        Buy again
      </s-button>
    </s-section>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  ResourceItem,
  Text,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.profile.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <ResourceItem
      to="shopify:customer-account/orders/1001"
      action={<Button kind="primary">Buy again</Button>}
    >
      <Text>Order #1001</Text>
      <Text>Shipped</Text>
    </ResourceItem>
  );
}
```

### action​Label and action​Accessibility​Label

The previous `actionLabel` and `actionAccessibilityLabel` props have been removed. Buttons placed in the `primary-action` and `secondary-actions` slots carry their own label and [`accessibilityLabel`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#properties-propertydetail-accessibilitylabel).

By default, the `secondary-actions` slot renders extra buttons inline when there's room and collapses the rest into a menu at narrower widths, using its own built-in trigger. To set the label on that trigger (the equivalent of the previous `actionLabel`), replace the slot's built-in trigger with your own button that targets an [`<s-menu>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/menu) with [`commandFor`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#properties-propertydetail-commandfor). Opting in to this pattern turns off the automatic responsive behavior: the actions stay behind the menu at every width instead of rendering inline when there's space.

## Customizing the menu trigger label

##### Latest (Preact)

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-section heading="Order #1001">
      <s-text>Placed on April 12, 2026</s-text>
      <s-button slot="primary-action" variant="primary">
        Buy again
      </s-button>
      <s-button
        slot="secondary-actions"
        variant="secondary"
        commandFor="order-actions-menu"
      >
        Manage
      </s-button>
      <s-menu id="order-actions-menu">
        <s-button>Track shipment</s-button>
        <s-button>Return</s-button>
      </s-menu>
    </s-section>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  ResourceItem,
  Text,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.profile.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <ResourceItem
      actionLabel="Manage"
      action={
        <>
          <Button kind="primary">Buy again</Button>
          <Button kind="secondary">Track shipment</Button>
          <Button kind="secondary">Return</Button>
        </>
      }
    >
      <Text>Order #1001</Text>
      <Text>Placed on April 12, 2026</Text>
    </ResourceItem>
  );
}
```

### loading

The previous `loading` prop rendered a loading state on the whole item. The Polaris section doesn't have a loading state. If you need to indicate loading, set [`loading`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/actions/button#properties-propertydetail-loading) on the button inside `primary-action`, or render a [`<s-spinner>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/loading-and-feedback/spinner) alongside the content.

***

## Updated patterns

### Matching the previous spacing

The default gap between the heading, content, and action buttons is tighter in `<s-section>` than it was in `ResourceItem`. To approximate the previous spacing, wrap the section's content in [`<s-stack>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/stack) with `direction="block"` and `paddingBlock="large"`. Buttons stay in their slots and aren't wrapped.

## Approximating the previous spacing

##### Latest (Preact)

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-section heading="Order #1001">
      <s-stack direction="block" paddingBlock="large">
        <s-text>Placed on April 12, 2026</s-text>
      </s-stack>
      <s-button slot="primary-action" variant="primary">
        Buy again
      </s-button>
      <s-button slot="secondary-actions">View details</s-button>
    </s-section>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Button,
  ResourceItem,
  Text,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.profile.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <ResourceItem
      action={
        <>
          <Button kind="primary">Buy again</Button>
          <Button kind="secondary">View details</Button>
        </>
      }
    >
      <Text>Order #1001</Text>
      <Text>Placed on April 12, 2026</Text>
    </ResourceItem>
  );
}
```

### Using s-image-group inside s-section

When [`<s-image-group>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/media/image-group) is rendered inside an `<s-section>`, it always uses a grid layout. The `variant` prop has been removed — the grid layout is implicit inside a section, so drop `variant` from existing usages.

Two other props have been removed:

* `accessibilityLabel` — describe each image with its own `alt` attribute instead.
* `loading` — each `<s-image>` manages its own loading state automatically.

## Migrating image-group inside a section

##### Latest (Preact)

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-section heading="Wishlist">
      <s-image-group totalItems={7}>
        <s-image src="https://example.com/product-1.jpg" alt="Blue t-shirt" />
        <s-image src="https://example.com/product-2.jpg" alt="Red mug" />
        <s-image src="https://example.com/product-3.jpg" alt="Canvas tote" />
        <s-image src="https://example.com/product-4.jpg" alt="Notebook" />
      </s-image-group>
    </s-section>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Image,
  ImageGroup,
  ResourceItem,
  Text,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.profile.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <ResourceItem>
      <Text>Wishlist</Text>
      <ImageGroup variant="grid" totalItems={7}>
        <Image source="https://example.com/product-1.jpg" accessibilityDescription="Blue t-shirt" />
        <Image source="https://example.com/product-2.jpg" accessibilityDescription="Red mug" />
        <Image source="https://example.com/product-3.jpg" accessibilityDescription="Canvas tote" />
        <Image source="https://example.com/product-4.jpg" accessibilityDescription="Notebook" />
      </ImageGroup>
    </ResourceItem>
  );
}
```

### Recreating the inline-stack image group layout

The grid layout is the preferred way to display multiple images inside a section. If you need the overlapping inline-stack look from the previous `ImageGroup`, you can recreate it with an [`<s-grid>`](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/web-components/layout-and-structure/grid) that uses overlapping column widths:

## Recreating inline-stack with s-grid

##### Latest (Preact)

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  return (
    <s-section heading="Wishlist">
      <s-grid gridTemplateColumns="28px 28px 28px 42px" alignItems="center">
        <s-box
          inlineSize="42px"
          blockSize="42px"
          border="base"
          borderRadius="base"
          overflow="hidden"
        >
          <s-image
            src="https://example.com/product-1.jpg"
            alt="Blue t-shirt"
            aspectRatio="1/1"
            objectFit="cover"
          />
        </s-box>
        <s-box
          inlineSize="42px"
          blockSize="42px"
          border="base"
          borderRadius="base"
          overflow="hidden"
        >
          <s-image
            src="https://example.com/product-2.jpg"
            alt="Red mug"
            aspectRatio="1/1"
            objectFit="cover"
          />
        </s-box>
        <s-box
          inlineSize="42px"
          blockSize="42px"
          border="base"
          borderRadius="base"
          overflow="hidden"
        >
          <s-image
            src="https://example.com/product-3.jpg"
            alt="Canvas tote"
            aspectRatio="1/1"
            objectFit="cover"
          />
        </s-box>
        <s-stack
          direction="inline"
          inlineSize="42px"
          blockSize="42px"
          borderRadius="large-100"
          border="large base solid"
          background="subdued"
          alignItems="center"
          justifyContent="center"
        >
          <s-text>+3</s-text>
        </s-stack>
      </s-grid>
    </s-section>
  );
}
```

##### Pre-Polaris (2025-07)

```jsx
import {
  Image,
  ImageGroup,
  ResourceItem,
  Text,
  reactExtension,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
  'customer-account.profile.block.render',
  () => <Extension />,
);

function Extension() {
  return (
    <ResourceItem>
      <Text>Wishlist</Text>
      <ImageGroup variant="inline-stack" totalItems={6}>
        <Image source="https://example.com/product-1.jpg" accessibilityDescription="Blue t-shirt" />
        <Image source="https://example.com/product-2.jpg" accessibilityDescription="Red mug" />
        <Image source="https://example.com/product-3.jpg" accessibilityDescription="Canvas tote" />
      </ImageGroup>
    </ResourceItem>
  );
}
```

***
