> ## Documentation Index
> Fetch the complete documentation index at: https://swish.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Reference for all SDK options - storefront credentials, context, metafields, transforms, intents, placements, UI views, and translations.

When using the **app embed** (recommended), the embed loads the SDK and provides storefront credentials and customer context automatically. Set `window.SwishOptions` before the embed runs to customize behavior and appearance:

```js theme={null}
window.SwishOptions = {
  intents: { ... },
  placements: [ ... ],
  transforms: { ... },
  translations: { ... },
  ui: { ... },
};
```

> [!TIP]
>
> For headless storefronts or manual setups without the app embed, call
> `createSwish()` directly with the full options object including `storefront`
> and `context`. See the [quickstart](https://swish.app/docs/guides/get-started/quickstart.md) for both
> approaches.

The sections below document every available option. All options can be passed via `window.SwishOptions` or directly to `createSwish()`.

## `storefront`

Credentials for the Shopify Storefront API. The SDK uses these to load product data, images, and recommendations.

**storefront.storeDomain** `string` *required*

Your `.myshopify.com` domain (e.g. `my-store.myshopify.com`). This is the same
value as `context.myshopifyDomain`.

**storefront.accessToken** `string` *required*

A Shopify Storefront API access token with read access to products.

> [!NOTE]
>
> The Storefront API access token is not generated automatically - you need to create one in your Shopify admin.
>
> 1. Go to **Settings** > **Apps and sales channels** > **Develop apps**.
> 2. Create a new app (or select an existing one).
> 3. Under **Configuration**, enable the **Storefront API** and grant at minimum the `unauthenticated_read_product_listings` scope.
> 4. Install the app and copy the **Storefront API access token** from the **API credentials** tab.
>
> For headless storefronts, store the token in an environment variable (e.g. `NEXT_PUBLIC_SHOPIFY_STOREFRONT_TOKEN`) rather than hardcoding it.

## `context`

Information about the current customer and storefront environment.

### Customer

**context.customer.id** `string | null` *required*

Shopify customer ID, or `null` for guest visitors.

**context.customer.email** `string | null` *required*

Customer email address.

**context.customer.firstName** `string | null` *required*

Customer first name.

**context.customer.lastName** `string | null` *required*

Customer last name.

**context.customer.b2b** `boolean | null` *required*

Whether the customer is a B2B customer.

**context.customer.tags** `string[] | null`

Shopify customer tags. Used to target [content blocks](https://swish.app/docs/guides/customize/views/home.md#content-block) at a subset of shoppers. Optional — omit it and tag-targeted blocks simply never match.

### Localization

**context.localization.country** `string` *required*

ISO country code (e.g. `"US"`).

**context.localization.language** `string` *required*

ISO language code (e.g. `"EN"`).

**context.localization.market** `string` *required*

Shopify market handle.

### Other context

**context.myshopifyDomain** `string` *required*

Your `.myshopify.com` domain.

**context.shopName** `string`

Your store's name, as shoppers know it. The drawer header shows it when you
have set neither a title nor a logo — see [Drawer](https://swish.app/docs/guides/customize/views/drawer.md).
On Shopify themes this is `shop.name` and the app embed passes it for you.

**context.moneyFormat** `string`

The store's currency format, as set under **Settings → General → Currency
formatting**. Only its decimal placeholder is read: a format using
`amount_no_decimals` (any variant) drops the cents from every price Swish
renders. The currency symbol, its position and the thousands separator come
from Swish's own per-currency formats either way. On Shopify themes this is
`shop.money_format` and the app embed passes it for you.

**context.newCustomerAccounts** `boolean` *required*

Whether the store uses Shopify's new customer accounts.

**context.routes.accountUrl** `string` *required*

URL path for the customer account page.

**context.routes.rootUrl** `string` (default: /)

Root URL for the storefront. Useful for multi-language stores with prefixed
paths.

**context.routes.listDetailPagePath** `string` (default: /apps/wishlist)

URL path for the full-page list detail view.

## `auth`

**auth.tokenUrl** `string` (default: /apps/wishlist/api/profiles/token)

URL the SDK calls to create auth tokens. On Shopify themes this is the default
app proxy token endpoint. For headless setups, set this to the route where you
host the [auth proxy](https://swish.app/docs/guides/headless/auth-proxy.md).

## `features`

**features.signInRequirement** `"none" | "save" | "view" | "all"` (default: none)

Require the customer to be signed in to perform specific actions. `"save"`
requires sign-in to save an item, `"view"` requires sign-in to open the
drawer, and `"all"` requires it for every action Swish can gate, including
any gated in a later release. See the
[Account guide](https://swish.app/docs/guides/features/account.md) for details.

## `integrations`

Third-party destinations the SDK sends events to from the storefront. The theme sets these through `window.SwishOptions`; they are not part of the setup yet.

**integrations.metaPixel.enabled** `boolean` (default: true)

Send every save to the store's Meta Pixel as an `AddToWishlist` event, through
the theme's `fbq` when the customer allows marketing or, without one, as a
`swish-add-to-wishlist` customer event for a custom pixel to forward. See the
[Meta Pixel integration](https://swish.app/docs/integrations/platforms/meta-pixel.md).

## `metafields`

Fetch additional Shopify metafields alongside product data. Metafields are specified in `namespace.key` format. See the [Metafields guide](https://swish.app/docs/guides/customize/metafields.md) for usage examples.

```js theme={null}
metafields: {
  product: ["custom.material", "custom.care_instructions"],
  productVariant: ["custom.weight"],
}
```

**metafields.product** `string[]` (default: \[])

Product metafields to fetch.

**metafields.productVariant** `string[]` (default: \[])

Variant metafields to fetch.

## `transforms`

Transform functions that customize how product, variant, and option data is displayed in the Swish UI. See the [Transforms guide](https://swish.app/docs/guides/customize/transforms.md) for usage examples.

| Transform | Signature | Default behavior |
| - | - | - |
| `productTitle` | `({ product }) => string` | Returns `product.title`. |
| `productSubtitle` | `({ product, variant }) => string \| undefined` | Returns `undefined` (no subtitle). |
| `productDescription` | `({ product }) => string` | Returns `product.descriptionHtml`. |
| `productBadges` | `({ product, variant, defaultBadges }) => (string \| Badge)[]` | Returns `defaultBadges` unchanged. |
| `productPrice` | `({ product, variant }) => string \| false \| undefined` | Returns `undefined` (default price rendering). |
| `productImage` | `({ product, variant, defaultImage }) => Image \| undefined` | Returns `defaultImage` (variant's image, else featured image). |
| `addToCartButton` | `({ product }) => boolean` | Returns `true` (cart buttons shown). |
| `linkToProductPage` | `({ product }) => boolean` | Returns `false` (in-drawer product view). |
| `variantTitle` | `({ variant }) => string` | Returns `variant.title`. |
| `optionValues` | `({ option, optionValues }) => OptionValue[]` | Returns option values unchanged. |
| `combinedListingParent` | `({ product }) => boolean \| string` | Returns `false` (not a combined listing). |
| `hideOption` | `({ option, product }) => boolean` | Returns `false` (option is visible). |
| `recommendations` | `({ product, defaultRecommendations }) => Ref[] \| Promise<Ref[]>` | Returns `defaultRecommendations` unchanged. |

A `Badge` can be a plain string or an object with `id`, `label`, and optional `style`.

`productImage` returns an image object with at least a `url`, such as one of `product.images.nodes`. Returning `undefined` or `null` keeps `defaultImage`.

`recommendations` receives and returns product references carrying only `id` - the recommendations query fetches nothing else, and each card re-fetches full product data per item. It may return a promise, so it's the one transform that can do async work.

> [!NOTE]
>
> `addToCartButton` defaults to `true`, so supply it only to hide cart buttons
> for particular products - add-to-cart on the product detail view, the buy
> button on cards, and the quick-buy button. The section options
> (`showBuyButton`, `showQuickBuyButton`) gate the same buttons independently:
> both the section option and this transform must allow a button for it to
> render.
>
> This transform is per product, not per view, so it cannot keep the product
> detail button while removing quick-buy from cards. Use
> [`ui.productCard.showQuickBuyButton`](#product-cards) for that.

> [!NOTE]
>
> Only `addToCartButton`, `linkToProductPage`, `combinedListingParent`, and
> `hideOption` tolerate a non-function value - a literal such as
> `linkToProductPage: true` is wrapped into a constant function. The other
> transforms are called directly, so passing a non-function (for example
> `productPrice: false`) throws on every render.

## `intents`

Behavioral options that control how specific intents interact with the customer.

### `saveProduct`

| Option | Type | Default | Description |
| - | - | - | - |
| `promptVariantIfMissing` | `boolean \| ((args: { product, variant }) => boolean)` | `true` | Show variant selector when no variant is provided. Pass a function to decide per product. |
| `promptVariantIfPresent` | `boolean` | `false` | Show variant selector even when a variant is already selected. |
| `saveBeforeVariantPrompt` | `boolean` | `true` | Save the item before showing the variant selector. |
| `showFeedback` | `boolean` | `true` | Show a toast after saving. |

### `unsaveProduct`

| Option | Type | Default | Description |
| - | - | - | - |
| `selectList` | `boolean` | `true` | Let the user choose which list to remove the item from. |
| `confirm` | `boolean` | `true` | Show a confirmation dialog before removing. |
| `showFeedback` | `boolean` | `true` | Show a toast after removing. |

### `editSavedProduct`

| Option | Type | Default | Description |
| - | - | - | - |
| `promptVariantChange` | `boolean` | `true` | Show variant selector when editing a saved item. |
| `showFeedback` | `boolean` | `true` | Show a toast after updating. |

### `initiateQuickBuy`

Whether the quick-buy button on a product card adds straight to cart or opens the quick buy dialog.

| Option | Type | Default | Description |
| - | - | - | - |
| `promptVariantIfPresent` | `boolean` | `false` | When the card already knows the variant, open the dialog to confirm it. |

By default, a card that knows its variant, such as an item saved with one, adds that variant to the cart directly without invoking `initiate:quick-buy`. Cards without a variant always open the dialog. Set to `true` to open the dialog for every card. [`initiate:quick-buy`](https://swish.app/docs/references/sdk/intents#initiate-quick-buy) invoked from your own code follows the same option.

### `createCartLine`

| Option | Type | Default | Description |
| - | - | - | - |
| `afterComplete` | `(response) => void` | `undefined` | Callback invoked after adding to cart. |

### `removeCartLine`

| Option | Type | Default | Description |
| - | - | - | - |
| `saveCartLine` | `boolean` | `true` | Prompt the customer to save items removed from the cart. |

### `saveCartLine`

| Option | Type | Default | Description |
| - | - | - | - |
| `confirm` | `boolean \| "toast" \| "dialog"` | `false` | Ask before saving the removed cart item. `true` or `"toast"` asks in a toast, `"dialog"` in a modal dialog. |
| `showFeedback` | `boolean` | `true` | Show a toast after saving. |
| `destination` | `"saved-from-cart" \| "wishlist"` | `"saved-from-cart"` | Which list the saved cart line lands in. |
| `afterComplete` | `(response) => void` | `undefined` | Callback invoked after saving the cart item. |

## `placements`

Declare placements upfront so the SDK automatically mounts them at initialization. Each entry uses the same placement spec as [`swish.placements.create()`](https://swish.app/docs/references/sdk/placements).

```js theme={null}
placements: [
  {
    id: "card-save-overlay",
    target: { selector: ".product-card" },
    mount: { at: { query: ".product-card__image" }, mode: "append" },
    element: { name: "save-button" },
    layout: { type: "overlay", anchor: "top-right", offset: { x: 8, y: 8 } },
    design: {
      background: "rgba(255, 255, 255, 0.9)",
      height: 36,
      radius: "50%",
    },
  },
  {
    id: "pdp-save-inline",
    target: { selector: ".product-form" },
    mount: { at: { query: 'button[type="submit"]' }, mode: "after" },
    element: { name: "save-button" },
    layout: { type: "inline" },
  },
];
```

After initialization, all configured placements are accessible via `swish.placements.list` - an array of `{ spec, mount, unmount }` objects you can use to unmount individual placements programmatically.

For the full placement spec reference, see [Placements](https://swish.app/docs/references/sdk/placements.md).

## `ui`

UI options control the visual layout and behavior of every view in the Swish drawer. Pass view-specific sections arrays to customize the layout.

For a detailed guide with examples, see [Views](https://swish.app/docs/guides/customize/views/overview.md).

### Global options

| Option | Type | Default | Description |
| - | - | - | - |
| `baseUrl` | `string` | `"https://swish.app/cdn"` | CDN base URL for Swish UI assets. |
| `css` | `(string \| URL)[]` | `[]` | Custom stylesheets injected into the shadow DOM. |
| `design` | `UiDesignOptions` | `{}` | Design tokens for colors, typography, rounding, and sizes. |
| `icons` | `Record<string, string>` | `{}` | Override default icons. Keys are icon names, values are SVG strings. |
| `images` | `{ baseTint: boolean }` | `{ baseTint: true }` | Global image display options. |
| `toasts` | `{ autoHideDuration: number }` | `{ autoHideDuration: 5000 }` | Toast notification options. `autoHideDuration` is the time in milliseconds before a toast auto-dismisses (applies to all toast variants; `0` disables auto-dismiss). |

### Product cards

`ui.productCard` applies to every product card, in every view. `showQuickBuyButton` and `linkToProductPage` have no default - leave one unset and the layer below it decides.

**ui.productCard.showQuickBuyButton** `boolean`

Whether cards show the quick-buy button (the floating cart button over the card
image). Set `false` to hide it on **every** card - the saves grid, both list
detail views, product recommendations and featured collections - while leaving
add to cart on the product detail view untouched. This is the only way to hide
quick-buy store-wide without also removing the product detail button, which is
what [`transforms.addToCartButton`](#transforms) would do.

It is a hard off switch, not a fallback: a section that sets
`showQuickBuyButton: true` cannot re-show the button while this is `false`.
Sections that expose their own toggle can still hide it in just their view.

This switch is code-only. In the customiser, you turn quick-buy on per view
with that view's **Show quick buy button**.

**ui.productCard.linkToProductPage** `boolean`

Whether a card is a hard link to its PDP rather than opening the in-drawer
product view. It is the only setting for this: no section has its own
`linkToProductPage`. When it is unset,
[`transforms.linkToProductPage`](https://swish.app/docs/guides/customize/transforms#link-to-product-page)
decides. The standalone Wishlist page ignores both and always links to the
PDP. Set it in the customiser under **Global → Preferences → Product cards**.

**ui.productCard.saveButtonPosition** `"image" | "title"` (default: "image")

Where a card's save button sits. `"image"` keeps it over the bottom corner of
the card image. `"title"` moves it beside the product title and price, as a
plain icon in the card title colour, outlined until saved and filled once
saved. The save button's **On image** settings do not apply there. Only the
save button moves: quick buy and badges stay on the image. Applies to the
drawer and the standalone Wishlist page. Set it in the customiser under
**Global → Preferences → Product cards → Save button position**.

### Save button

**ui.saveButton.animation** `"none" | "pulse" | "jello" | "particles"` (default: "none")

The animation a save button plays when a customer taps it to save an item.
`"pulse"` shrinks the icon and springs it back, `"jello"` squashes and
stretches it, and `"particles"` bursts small copies of the icon out of it.
It plays once the save goes through, never for an item that is already
saved, and not at all for customers who turn on reduced motion in their
system settings. It applies to every save button: placed buttons, and the
hearts in the drawer and on the Wishlist page. A value it doesn't know plays
nothing. Set it in the customiser under **Global → Save button → Save
animation**.

```js theme={null}
ui: {
  saveButton: { animation: "particles" },
}
```

### Product badges

`ui.badges.rules` is the product badge priority list for product cards and the product detail view. Each product shows one badge: the first enabled row, in list order, that applies to it. Set it in the customiser under **Global → Preferences → Product badges**. The chosen badge then goes through [`transforms.productBadges`](https://swish.app/docs/guides/customize/transforms#product-badges) as `defaultBadges`.

The list holds Swish's built-in badges, `{ type: "sold-out" }`, `{ type: "sale" }` and `{ type: "low-stock" }`, and your own `{ type: "custom" }` rows. It defaults to the three built-ins in that order, with Low stock hidden, which is how badges worked before the list existed. A list that leaves a built-in out gets it appended as in the default: Sold out and Sale shown, Low stock hidden. Set `enabled: false` to hide a built-in, and `enabled: true` to show Low stock.

```js theme={null}
window.SwishOptions = {
  ui: {
    badges: {
      rules: [
        { type: "sold-out" },
        {
          type: "custom",
          label: "New",
          condition: { type: "tag", tag: "new-arrival" },
          backgroundColor: "#16a34a",
          textColor: "#ffffff",
        },
        { type: "sale", enabled: false },
        { type: "low-stock", enabled: true, max: 3 },
        {
          type: "custom",
          label: "Just in",
          condition: { type: "published-within", days: 14 },
        },
        {
          type: "custom",
          label: "Vegan",
          condition: {
            type: "metafield",
            metafield: "custom.diet",
            operator: "contains",
            value: "vegan",
          },
        },
      ],
    },
  },
};
```

**ui.badges.rules\[].type** `"sold-out" | "sale" | "low-stock" | "custom"` *required*

`"sold-out"` applies when the product or selected variant can't be bought,
`"sale"` when its compare-at price is above its price, and `"low-stock"` when
1 to `max` units are left. The built-in badges show translated text
(`productCard.badges.soldOut`, `productCard.badges.sale`,
`productCard.badges.lowStock`), which you change per language in
[translations](https://swish.app/docs/guides/customize/translations.md). `"custom"` applies when its
`condition` matches.

**ui.badges.rules\[].enabled** `boolean` (default: true)

Set `false` to hide the badge. The next matching row shows instead. The Low
stock row defaults to `false`.

**ui.badges.rules\[].max** `number` (default: 5)

Low stock row only. The badge shows when 1 to `max` units are left. It reads
the selected variant when there is one; without one it reads the product's
total stock. It never applies to a sold-out product or a variant selling on
backorder. Swish fetches stock levels only while this row is shown.

**ui.badges.rules\[].label** `string` (default: "")

The badge text, as plain text. On a custom row it is required: a blank label
shows nothing. On a built-in row, blank keeps the translated text and a value
replaces it in every language; to change a built-in badge's text per
language, use [translations](https://swish.app/docs/guides/customize/translations.md) instead. The
badge keeps its `badge-sold_out` / `badge-sale` / `badge-low_stock` class
either way.

**ui.badges.rules\[].condition** `object`

Custom rows only. `{ type: "tag", tag }` matches a product tag, ignoring case.
`{ type: "metafield", metafield, operator, value }` reads a product metafield
named `namespace.key`. `operator` is `"exists"` (any value, the default),
`"equals"` or `"contains"`, all ignoring case. `"contains"` also matches one
item of a list metafield. Swish adds every metafield a row names to
[`metafields.product`](#metafields) for you.

`{ type: "discount", minPercent }` applies when the price is at least
`minPercent` below the compare-at price (default `20`). It reads the selected
variant when there is one, otherwise the product.

`{ type: "published-within", days }` applies for `days` days after the
product was published to your storefront's sales channel (default `30`), so
a **New** badge drops off by itself. It reads the product's `publishedAt`
date, so every variant of a product shows the same result.

**ui.badges.rules\[].backgroundColor** `string` (default: "")

The badge background. Blank uses the badge colours from `ui.design`.

**ui.badges.rules\[].textColor** `string` (default: "")

The badge text colour. Blank uses the badge colours from `ui.design`.

### Wishlist

`ui.wishlist` covers how the wishlist itself works, as opposed to how any one view looks. Set both fields in the customiser under **Global → Preferences → Wishlist experience**, where `experience` is **Wishlist surface**.

**ui.wishlist.experience** `"drawer" | "classic-page"` (default: "drawer")

`"classic-page"` replaces the drawer with your standalone wishlist page. Every
navigation intent (`view:home`, `view:saves`, `view:list`, …) sends the
customer to `context.routes.listDetailPagePath` instead of opening the drawer,
carrying `?list-id=` when a list is targeted. It implies `multipleLists:
    false`: the save toast drops its **Add to list** action and unsaving no longer
asks which list to remove from.

**ui.wishlist.multipleLists** `boolean` (default: true)

Whether customers can keep more than one saved list. With `false`, the save
toast's action opens `ui.defaultView` instead of the list picker, and unsaving
skips the picker regardless of `intents.unsaveProduct.selectList`. Reach for
it when you want a single list *and* the drawer, since
`experience: "classic-page"` already implies one on its own. See
[Single list only](https://swish.app/docs/guides/customize/views/overview.md#single-list-only).

**ui.defaultView** `"home" | "saves" | "lists" | "notifications" | "orders" | "profile"` (default: "home")

The view the drawer opens on. `view:home` resolves to it, so every generic
entry point - a `swish-intent="view:home"` button, a `#swish` link, the header
button - lands there without any theme changes, and so does the save toast's
**View** action. It is also the drawer's root: the Back chevron is hidden
there, and Back from any other view returns to it. The Home view stays
reachable through the footer **Home** tab; a store running Swish as a pure
wishlist sets this to `"saves"` and turns that tab off. Set it in the
customiser under **Global → Preferences → Wishlist experience**.

### Views

Each view accepts a `sections` array. See [Views](https://swish.app/docs/guides/customize/views/overview.md) for the full configuration reference with defaults and examples.

| View | Key | Default sections |
| - | - | - |
| Drawer | `ui.drawer` | `drawer-header`, `drawer-footer` |
| Home | `ui.home` | `sign-in`, `notifications`, `recently-viewed`, `saved-from-cart`, `saved-items`, `lists`, `mini-menu` |
| Saves | `ui.saves` | `sign-in`, `lists-section` (myLists), `lists-section` (forYouLists), `all-items-grid` |
| Lists | `ui.lists` | `sign-in`, `lists-grid` |
| List detail | `ui.listDetail` | `list-items-grid` |
| Product detail | `ui.productDetail` | `image-slider`, `product-info`, `buy-buttons`, `complementary-products`, `related-products` |
| Orders | `ui.orders` | `orders-list` |
| Order detail | `ui.orderDetail` | `order-info`, `order-items`, `order-actions` |
| Profile | `ui.profile` | `profile-form` |
| Notifications | `ui.notifications` | `notifications-list` |
| List detail page | `ui.listDetailPage` | `page-header`, `list-items-grid` |

### drawer-header

The drawer's top bar. See [Drawer](https://swish.app/docs/guides/customize/views/drawer.md#header) for examples.

#### `ui.drawer.sections[].options`

| Option | Type | Default | Description |
| - | - | - | - |
| `title` | `string` | `""` | Header title. Empty shows your store's name. A logo replaces it. |
| `logo` | `{ url, altText }` | `{ url: "", altText: "" }` | Logo image shown in place of the title. |
| `headerStyle` | `"logo" \| "greeting"` | `"logo"` | `"greeting"` shows "Hi, \{\{firstName}}" to a signed-in customer and `guestGreeting` to a guest, in place of the logo, title and store name. |
| `guestGreeting` | `string` | `""` | A guest's greeting when `headerStyle` is `"greeting"`. Empty uses the translated `drawerHeader.guestGreeting`, "Welcome". |
| `useCloseButton` | `boolean` | `false` | Show a close button after the notification and account buttons. |
| `accountButton` | `boolean` | `true` | Show the account button. |
| `accountButtonUrl` | `string` | `"profile"` | Where the account button goes: `"profile"`, `"shopify"` or a URL. See [Account button destination](https://swish.app/docs/guides/customize/views/drawer.md#account-button-destination). |
| `notificationButton` | `boolean` | `true` | Show the notification button. |

### sign-in

The sign-in callout shown to signed-out shoppers. Used by `ui.home`, `ui.saves` and `ui.lists`, each with its own copy. It renders above the rest of the view, so a guest's own saves and lists stay visible below it, and `hidden: true` removes it from that view.

#### `ui.home.sections[].options`, `ui.saves.sections[].options`, `ui.lists.sections[].options`

| Option | Type | Default | Description |
| - | - | - | - |
| `message` | `string` | `""` | Copy shown above the sign-in button. Empty uses the translated `signIn.description` default. A `t:`-prefixed value resolves as a [translation](https://swish.app/docs/guides/customize/translations.md) key. |

### page-header

The standalone Wishlist page's header: the title, then the page's actions. Used by `ui.listDetailPage` only. See the [List detail page](https://swish.app/docs/guides/customize/views/list-detail-page.md#page-header) guide for which actions appear on which view.

#### `ui.listDetailPage.sections[].options`

| Option | Type | Default | Description |
| - | - | - | - |
| `title` | `string` | `""` | The title on the all-items view. Empty shows the translated `drawer.listDetail.allItems` ("Wishlist"). A single list always shows its own name. |
| `titleAlignment` | `"left" \| "center"` | `"left"` | `center` stacks the title above the actions, both centred. |
| `showShareButton` | `boolean` | `false` | Show **Share** on a list the customer owns. Never shown on the all-items view or a shared link. Off, and locked in the Swish admin, until the whole wishlist can be shared. |
| `showAddAllToCartButton` | `boolean` | `false` | Show **Add all to cart**, which adds every item on the page in one cart call. |
| `showAccountAvatar` | `boolean` | `true` | Show the account button: **Sign in** for a guest, the customer's initial and the account menu for an account. |

### list-items-grid

Renders a list's items, either as a product grid (`layout: "gallery"`) or as one full-width row per item (`layout: "card"`). Used by both `ui.listDetail` (in-drawer) and `ui.listDetailPage` (standalone full-page). Each view exposes a different subset of options.

Card layout puts the image on the left and the vendor, title, price, variant and an **Add to cart** button on the right. The image renders square in that layout rather than following the **Global → Components → Product cards → Card image aspect ratio**, so rows stay compact.

Neither list detail view exposes `layout` in the Swish admin, so both render the gallery layout unless you set the option in code. The `all-items-grid` section below still offers the choice.

Neither view has a `linkToProductPage` option. In the drawer, cards follow [`ui.productCard.linkToProductPage`](#product-cards). The standalone page always links its cards to the PDP.

#### `ui.listDetailPage.sections[].options`

| Option | Type | Default | Description |
| - | - | - | - |
| `layout` | `"gallery" \| "card"` | `"gallery"` | Grid of product tiles, or a full-width row per item. Not exposed in the Swish admin for this view. |
| `showVendor` | `boolean` | `true` | Show the product's vendor above the title. Card layout only. Not exposed in the Swish admin for this view. |
| `desktopColumns` | `number` | `4` | Number of product columns on desktop viewports. Card rows are wide — 1 or 2 reads best; mobile is always one column in card layout. |
| `showBuyButton` | `boolean` | `false` | Show the solid buy button beneath each product card. Off by default; applies to both layouts when you turn it on. |
| `showQuickBuyButton` | `boolean` | `false` | Show the floating quick-buy button on the card image. Off until you turn it on. |
| `showQuantityInput` | `boolean` | `false` | Show a quantity stepper on each card, set to the item's saved quantity. The buy and quick-buy buttons add that amount. On the customer's own list a change is saved to the item; on a shared list it only changes the amount added. |
| `showVariantTitle` | `boolean` | `true` | Show the saved variant's title on the product card. |
| `showVariantOptionNames` | `boolean` | `false` | Show option names alongside values. Not exposed in the Swish admin for this view. |
| `enableVariantChange` | `boolean` | `true` | Allow customers to change the saved variant directly on the page. |
| `hideCompareAtPrice` | `boolean` | `false` | Hide the strike-through compare-at price; only the active price renders. |

#### `ui.listDetail.sections[].options`

| Option | Type | Default | Description |
| - | - | - | - |
| `layout` | `"gallery" \| "card"` | `"gallery"` | Two-column grid of product tiles, or a full-width row per item. Not exposed in the Swish admin for this view. |
| `showVendor` | `boolean` | `true` | Show the product's vendor above the title. Card layout only. Not exposed in the Swish admin for this view. |
| `showBuyButton` | `boolean` | `false` | Show the solid buy button beneath each product card. Off by default; applies to both layouts when you turn it on. |
| `showQuickBuyButton` | `boolean` | `false` | Show the floating quick-buy button on the card image. Off until you turn it on. |
| `showQuantityInput` | `boolean` | `false` | Show a quantity stepper on each card, set to the item's saved quantity. The buy and quick-buy buttons add that amount. On the customer's own list a change is saved to the item; on a smart list it only changes the amount added. |
| `showVariantTitle` | `boolean` | `true` | Show the saved variant's title on the product card. |
| `showVariantOptionNames` | `boolean` | `false` | Show option names alongside values. Not exposed in the Swish admin for this view. |
| `enableVariantChange` | `boolean` | `false` | Allow customers to change the saved variant directly on the card. |
| `hideCompareAtPrice` | `boolean` | `false` | Hide the strike-through compare-at price; only the active price renders. |
| `showImageToggle` | `boolean` | `false` | Show a switch above the grid that flips every card between its main image and the one the [`productImage` transform](https://swish.app/docs/guides/customize/transforms#product-image) picks. Shows only when that transform is set. |
| `showExpandButton` | `boolean` | `false` | Show an expand button in the list's header that widens the drawer to the full browser width and hides the footer navigation, from 600px wide. The drawer returns to its usual width when the customer collapses it, leaves the list or closes the drawer. See the [List detail](https://swish.app/docs/guides/customize/views/list-detail.md#full-width-view) guide. |

### all-items-grid

Renders the customer's saved items, either as a product grid (`layout: "gallery"`) or as one full-width row per item (`layout: "card"`). Used by `ui.saves`, and by the **All Items** screen that the grid's heading links to — both read this one section.

Card layout puts the image on the left and the vendor, title, price, variant and an **Add to cart** button on the right. The image renders square in that layout rather than following the **Global → Components → Product cards → Card image aspect ratio**, so rows stay compact.

#### `ui.saves.sections[].options`

| Option | Type | Default | Description |
| - | - | - | - |
| `layout` | `"gallery" \| "card"` | `"gallery"` | Two-column grid of product tiles, or a full-width row per item. |
| `showVendor` | `boolean` | `true` | Show the product's vendor above the title. Card layout only. |
| `showSaveButton` | `boolean` | `true` | Show the save/unsave button on cards. |
| `showQuickBuyButton` | `boolean` | `false` | Show the floating quick-buy button on the card image. Off until you turn it on. |
| `showBuyButton` | `boolean` | `false` | Show the solid buy button beneath each product card. Card layout always shows it — the switch isn't exposed in the Swish admin for this view, so the layout turns it on itself. |
| `showVariantTitle` | `boolean` | `true` | Show the variant title on cards. |
| `enableVariantChange` | `boolean` | `false` | Allow changing the variant from cards. |
| `showVariantOptionNames` | `boolean` | `true` | Show option names alongside values. |
| `hideCompareAtPrice` | `boolean` | `false` | Hide the strike-through compare-at price; only the active price renders. |
| `showImageToggle` | `boolean` | `false` | Show a switch above the grid that flips every card between its main image and the one the [`productImage` transform](https://swish.app/docs/guides/customize/transforms#product-image) picks. Shows only when that transform is set. |

## `translations`

Override default UI strings by language. Keys are language codes, values are objects mapping translation keys to strings.

```js theme={null}
translations: {
  en: {
    "saveButton.save": "Add to Wishlist",
    "saveButton.saved": "Saved",
  },
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.