# Customize

Give the storefront your shop's look and parts in four steps, from a few tokens to components of your own.

The components bring the behavior, the semantics and a plain look. Your shop brings the rest, as far as it needs: each step goes one deeper than the one before, and most shops stop after the first two. The examples build on [Your storefront](/docs/your-storefront).

### Set the tokens

Every component draws its colors, corners and type from `--orb-*` custom properties. A theme sets their values:

```css title="apps/shop/app/theme.css"
:root {
    --orb-color-accent: #2f4636;
    --orb-color-accent-soft: #e8efe9;
    --orb-color-focus: #2f4636;
    --orb-radius-control: 999px;
    --orb-font-sans: "Inter", system-ui, sans-serif;
}
```

Import it after the components' styles, so your values win:

```tsx title="apps/shop/app/root.tsx (trimmed)"
import "@orbsearch/react/orbsearch.css";
import "./theme.css";
```

Actions, focus rings and chosen values turn dark green, and fields, buttons and chips get round ends. Tokens apply at runtime, so a second look is the same tokens under a selector such as `[data-theme="dark"]`.

<Callout type="warn">
    The default colors meet WCAG 2.2 AA in pairs, such as `accent` text on `accent-soft`. Change both of a pair
    together; [Theming](/docs/theming#contrast-the-defaults-meet) lists them.
</Callout>

### Style a part by its slot

Where a token is not enough, select the part by its `data-slot` attribute. This sets every tile's price heavier, and quieter on a tile that is sold out:

```css title="apps/shop/app/theme.css"
[data-slot="tile-price"] {
    font-weight: 600;
}

[data-slot="product-tile"][data-sold-out] [data-slot="tile-price"] {
    color: var(--orb-color-ink-muted);
}
```

Some parts say their state too, such as `data-field` on a [facet](/docs/reference/glossary#facet): `[data-slot="facet"][data-field="color"]` is the color facet alone. [Theming](/docs/theming#slots-and-states) lists the slots and states.

### Swap a part

To change what a part holds, build your own from its parts. This tile adds a badge for what arrives within two days:

```tsx twoslash title="apps/shop/app/tile.tsx"
import { ProductTile, useTile, type TileProps } from "@orbsearch/react";

export function ShopTile(props: TileProps) {
    return (
        <ProductTile.Root {...props}>
            <ProductTile.Title />
            <ProductTile.Media>
                <ProductTile.Image />
                <ProductTile.Badges>
                    <QuickBadge />
                </ProductTile.Badges>
            </ProductTile.Media>
            <ProductTile.Price />
            <ProductTile.Brand />
        </ProductTile.Root>
    );
}

function QuickBadge() {
    const { product } = useTile();
    if (product.delivery === null || product.delivery.max > 2) return null;
    return <ProductTile.Badge>Schnell bei dir</ProductTile.Badge>;
}
```

"Schnell bei dir" means quick to you. Pass it as `<ListingPage listing={shown.listing} tile={ShopTile} />`, and every tile of the page uses it. Keep `ProductTile.Title` first: it holds the heading, the tile's one link and the focus "Load more" moves to.

A banner is swapped the same way from `Banner`'s parts. To change only a part's element or classes, its `render` prop keeps the semantics ([React components](/docs/react#change-an-element)).

### Build a component of your own

A facet display is a component of your own that the components draw a facet with. The home store's color facet asks for one by name, `"custom_display": "color_tiles"`:

```tsx twoslash title="apps/shop/app/color-tiles.tsx"
import { FacetGroup, ValueList, ValueName, type FacetDisplayProps } from "@orbsearch/react";

export function ColorTiles({ state }: FacetDisplayProps) {
    return (
        <FacetGroup state={state}>
            <ValueList
                state={state}
                className="color-tiles"
                row={(value) => (
                    <li key={value.code}>
                        <label>
                            <input {...state.getValueProps(value)} />
                            <ValueName value={value} />
                        </label>
                    </li>
                )}
            />
        </FacetGroup>
    );
}

// Three full rows of three before "Show N more".
ColorTiles.shown = 9;
```

Register it once, in a module-level object, as `<StorefrontProvider displays={{ color_tiles: ColorTiles }}>`. The filter bar, the panel and the sheet then draw the color facet with it. `getValueProps` makes each value a native checkbox or radio, so keyboard and screen readers keep working.

To own a whole part, copy its source into your shop with the shadcn CLI. The buy box is the part the registry holds today:

```sh title="Terminal"
npx shadcn@latest add ./node_modules/@orbsearch/react/registry/r/buy-box.json
```

The copy is yours to change, and it imports the rest from `@orbsearch/react`. Pass it to `ProductPage` as `buyBox={<BuyBox product={product} />}`, and keep its `data-slot` attributes, which tests and themes find it by.

## Next

- [React components](/docs/react): every part, what it takes and which displays exist.
- [Theming](/docs/theming): every token, the contrast pairs and the styles with Tailwind.
- [Accessibility](/docs/accessibility): what your parts keep for keyboard and screen reader users.
