# Bundle card styling

> CSS custom properties, parts and states for the AndOr bundle card (Frequently bought together), with Dawn and Horizon examples.

Source: https://backtrackhq.com/docs/widgets/bundle/styling/

This page is for theme developers. It lists every class, state and CSS
custom property of the bundle card, `<andor-bundle class="andor-bundle"
data-andor-widget="bundle">`.

The card comes from the **AndOr Offer picker** block and the pasted
`<andor-offer-picker>` tag. It uses AndOr's widget styles.
Liquid prints the card at its final size
with blank text, and the script fills it in.

## What each token changes

The numbers on the diagram match the table. The diagram is a simplified drawing. The full list of tokens is below.
(Diagram: The offer picker bundle card with two products and an Add button)
1. `--andor-bundle-head-color`: the heading
2. `--andor-bundle-text-color`: the message
3. `--andor-bundle-image-radius`: picture corners
4. `--andor-bundle-chip-background`: the chip fill
5. `--andor-bundle-now-color`: the bundle total
6. `--andor-bundle-button-background`: the button fill
7. `--andor-bundle-button-radius`: button corners

## How precedence works

Put your CSS in your theme's stylesheet or in the app embed's
**Custom CSS** box. To see which value wins, read
[Which value wins](https://backtrackhq.com/docs/developers/tokens/#which-value-wins).

The block's **Button color** is written inline on the host as
`--andor-bundle-accent`, but only when the merchant changed it from
`#c0392b`. Left on the default, the inline value is
`var(--andor-color-accent)`, so a `:root` rule or the brand color
reaches it. On a pasted tag, `data-accent` sets it.

> **Caution:** The picture size and the row heights are part of the
> printed size. Change them with the custom properties below, so the
> skeleton and the filled card stay the same size.

## Parts

| Class | What it is |
|---|---|
| `.andor-bundle` | The host |
| `.andor-bundle__head` | "Frequently bought together" |
| `.andor-bundle__text` | The offer's message |
| `.andor-bundle__pics` | The row of pictures, joined by "+" |
| `.andor-bundle__img` | One picture (a background image) |
| `.andor-bundle__list` | The product rows |
| `.andor-bundle__row` | One row. Rows with a checkbox also have `.andor-bundle__row--pick` |
| `.andor-bundle__pick` | The row's checkbox |
| `.andor-bundle__name` | The product name |
| `.andor-bundle__this` | "This item:" before this page's product |
| `.andor-bundle__price` | The row's price |
| `.andor-bundle__total` | The price line |
| `.andor-bundle__label` | The price line label ("Bundle price:") |
| `.andor-bundle__was` | The struck regular total |
| `.andor-bundle__now` | The bundle total |
| `.andor-bundle__chip` | The "Save 15%" chip |
| `.andor-bundle__rest` | The "Add bundle to cart" button |

A variant choice is a plain `select` inside `.andor-bundle__row--pick`.
When the price is not sure, `.andor-bundle__total` holds one sentence
("Save 15% when bought together") and no `__was`, `__now` or `__chip`.

## States and data attributes

| Attribute or class | On | Meaning |
|---|---|---|
| `data-andor-widget` | host | `bundle` |
| `data-andor-widget-id` | host | The block id |
| `data-andor-progress` | host | `locked`, or `won` once checkout applied the bundle |
| `data-andor-ready` | host | Filled in. Before that, the skeleton shimmers |
| `data-andor-kept="note"` | host | The card went away after it was applied. Only the line shows |
| `data-andor-state` | host | `active` or `hidden`. A styling hook |
| `.andor-bundle__img--off` | picture | Its row is unticked |
| `:checked` | `.andor-bundle__pick` | The row is in the bundle |
| `:disabled` | `.andor-bundle__pick` | This page's product, always in |
| `:disabled` | `.andor-bundle__rest` | Nothing left to add |
| `hidden` | row or picture | A product the script could not load |

## Custom properties

"Accent" below is the Button color: `--andor-bundle-accent`, then
`--andor-color-accent`, then `#c0392b`.

| Property | Default | What it does |
|---|---|---|
| `--andor-bundle-accent` | Block setting, inline | Accent |
| `--andor-bundle-space-block-start` | `0.75em` | Margin above |
| `--andor-bundle-space-block-end` | `0.75em` | Margin below |
| `--andor-bundle-color` | `inherit` | Text color |
| `--andor-bundle-font-size` | `inherit` | Base size |
| `--andor-bundle-head-color` | `inherit` | Heading color |
| `--andor-bundle-head-font-size` | `1.15em` | Heading size |
| `--andor-bundle-head-font-weight` | `700` | Heading weight |
| `--andor-bundle-text-space` | `0.5em` | Space under the message |
| `--andor-bundle-text-color` | `inherit` | Message color |
| `--andor-bundle-text-font-weight` | `inherit` | Message weight |
| `--andor-bundle-pic-size` | `5em` | A picture's size |
| `--andor-bundle-image-radius` | radius, then `4px` | Picture corners |
| `--andor-bundle-image-background` | `#f3f3f3` | Empty picture |
| `--andor-bundle-border-color` | border, then `#e6e6e6` | Rule over the total |
| `--andor-bundle-was-opacity` | `0.7` | Struck total fade |
| `--andor-bundle-now-font-size` | `1.2em` | Bundle total size |
| `--andor-bundle-now-color` | accent | Bundle total color |
| `--andor-bundle-chip-background` | accent | Chip fill |
| `--andor-bundle-chip-color` | on-accent, then `#ffffff` | Chip text |
| `--andor-bundle-chip-radius` | radius, then `4px` | Chip corners |
| `--andor-bundle-chip-font-size` | `0.8em` | Chip size |
| `--andor-bundle-button-padding` | `0.5em 1.1em` | Button padding |
| `--andor-bundle-button-border-color` | accent | Button border |
| `--andor-bundle-button-background` | accent | Button fill |
| `--andor-bundle-button-color` | on-accent, then `#ffffff` | Button text |
| `--andor-bundle-button-radius` | radius, then `4px` | Button corners |
| `--andor-bundle-button-font-weight` | `inherit` | Button weight |

"Radius", "border" and "on-accent" are the global tokens
`--andor-radius`, `--andor-color-border` and `--andor-color-on-accent`.

## Examples

Match Dawn's buttons. Dawn's colors are RGB numbers, so wrap them in
`rgb()` or `rgba()`:

```css
andor-bundle {
  --andor-bundle-button-background: rgb(var(--color-button));
  --andor-bundle-button-border-color: rgb(var(--color-button));
  --andor-bundle-button-color: rgb(var(--color-button-text));
  --andor-bundle-button-radius: var(--buttons-radius, 0);
  --andor-bundle-image-radius: var(--media-radius, 0);
  --andor-bundle-border-color: rgba(var(--color-foreground), 0.1);
}
```

Match Horizon's primary button:

```css
andor-bundle {
  --button: var(--color-primary-button-background);
  --andor-bundle-button-background: var(--button);
  --andor-bundle-button-border-color: var(--button);
  --andor-bundle-button-color: var(--color-primary-button-text);
  --andor-bundle-button-radius: var(--style-border-radius-buttons-primary);
  --andor-bundle-border-color: var(--color-border);
}
```
