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

# Custom Icons

> Replace the checkout's default icons with your own artwork, and ship extra icons for your custom components — all from a single uploaded SVG sheet

Your checkout's icons don't have to be ours. Upload one SVG sheet of `<symbol>` elements and the storefront serves it merged over the default set: a symbol whose id matches a default icon **replaces** it everywhere it appears, and any other symbol becomes an **extra icon** you can reference from custom components.

## How it works

Every checkout page references its icons from a per-store sheet served at `icons.svg` (relative to the checkout URL — e.g. `/{storeId}/icons.svg`, or `/checkout/icons.svg` behind your own domain's reverse proxy). The served document is the default set with your uploaded symbols merged in by id, so you customize icons with data, not code.

## Admin Configuration

1. **Navigate** to your store in the admin dashboard
2. **Open** **Settings** and click the **Icons** tab
3. **Drop** your SVG sheet — it is validated and every symbol is previewed in a grid with its id
4. **Upload** — changes reach shoppers within about a minute

The sheet is one SVG document whose direct children are `<symbol>` elements:

```xml icons-sheet.svg theme={"system"}
<svg xmlns="http://www.w3.org/2000/svg">
  <!-- id matches a default icon: REPLACES it across the checkout -->
  <symbol id="Delivery" viewBox="0 0 256 256" fill="currentColor" stroke-width="16">
    <path d="..." fill="none" stroke="currentColor" />
  </symbol>

  <!-- any other id: ADDED, available to custom components -->
  <symbol id="MyBrandBadge" viewBox="0 0 48 48">
    <path d="..." fill="#0061cc" />
  </symbol>
</svg>
```

## Default icon keys

Overriding works by exact id match. These are the default icons and their keys — upload a symbol with the same id (PascalCase) to replace one:

<Frame>
  <img src="https://mintcdn.com/ollie/NP3NIYUwErNqy7ve/ollie-shop/imgs/custom-icons-default-set.png?fit=max&auto=format&n=NP3NIYUwErNqy7ve&q=85&s=950e4a51611888f8cedcb87532aa35a6" alt="The default icon set with the PascalCase key of each icon" width="2000" height="1996" data-path="ollie-shop/imgs/custom-icons-default-set.png" />
</Frame>

## Using extra icons in custom components

Any symbol that doesn't match a default key is served alongside the defaults. Reference it from a [custom component](/ollie-shop/customization/custom-component) with a standard SVG `use` element and a **relative** href, so it resolves on every host and path:

```tsx theme={"system"}
<svg width="24" height="24">
  <use href="icons.svg#MyBrandBadge" />
</svg>
```

## Theming contract

Icons are colored with CSS custom properties that inherit into the symbol — set them on the referencing `<svg>` or any ancestor (your [theme tokens](/ollie-shop/configuration/theme) work here):

| Property              | What it controls                                    |
| --------------------- | --------------------------------------------------- |
| `--icon-fill`         | Fill color                                          |
| `--icon-stroke`       | Stroke color                                        |
| `--icon-bg`           | The background rectangle some icons carry           |
| `--icon-stroke-width` | Stroke width, **in the symbol's own viewBox units** |

Symbols authored in the common `currentColor` style (the convention of most icon libraries) work without changes — the checkout bridges `--icon-stroke`/`--icon-fill` through the inherited `color`. For full theming of your own artwork, follow the default sheet's pattern: keep a literal color as the attribute and put the themable value in a `style` attribute, e.g. `stroke="#212529" style="stroke:var(--icon-stroke,#212529)"`.

<Info>
  Stroke width does not scale across viewBoxes: an icon drawn in a `0 0 256 256` viewBox with no `stroke-width` renders hairline-thin at icon size. Either bake a proportional `stroke-width` on the symbol (e.g. `16` for a 256 viewBox) or author in a `0 0 24 24` viewBox like the defaults.
</Info>

## Validation and limits

The upload is validated for safety, not style — you'll get actionable errors for anything rejected:

* **File**: `image/svg+xml`, at most **1 MiB**
* **Ids**: start with a letter; letters, digits, hyphen and underscore only; unique within the sheet
* **Not allowed**: `<script>`, `<foreignObject>`, `<style>` elements, event-handler attributes (`on*`), and any external URL reference (`http(s)://`, protocol-relative, `javascript:`) — `<image>` elements must use `data:image/` URIs
* **Animation**: SMIL (`<animate>`, `<animateTransform>`) is allowed, except animations that retarget an `href`
* Internal ids (clip paths, gradients) that collide with existing ids cause that symbol to be dropped, protecting sibling icons

A symbol with any violation is dropped whole rather than silently pruned — a missing icon is noticeable, a half-broken one isn't.

## Concerns worth designing around

* **Keep the sheet to icons you actually use.** The merged sheet is fetched once and cached, but its size still sets the first-load cost — prefer curating the symbols something references over dropping in a full icon library. As a reference, the entire default set of 84 icons is about 27 KB compressed.
* **Give every symbol a `viewBox`** — without one the icon won't scale to the size the checkout renders it at.
* **Propagation is \~1 minute**: the sheet is cached briefly at several layers; don't expect an upload to be visible on the very next reload.
* **Replacing a default replaces it everywhere** — the same key may render in the cart, shipping, and payment steps. Check all three after overriding high-traffic keys like `Delivery`, `Cart`, or `Close`.
* **Raster brand marks** (embedded `data:image/` PNGs) work but don't theme — colors are baked into the image.
