# Theming (/docs/products/dash-dots/developers/theming)

To put your dot in your brand's colors, set a theme in `dot.ts`. Set your blue once and every button follows.

```ts title="dot.ts"
export default defineDot({
  pages: ['index'],
  theme: {
    scheme: 'system',
    colors: {
      primary: { light: '#0168CC', dark: '#6CB4FF' },
      background: { light: '#F4F7FB', dark: '#0B0F14' },
    },
    shape: 'soft',
  },
});
```

`scheme` follows the phone's light or dark mode when it's `system`, the default. Set `light` or `dark` to pick one. `shape` sets how round the corners are: `square`, `subtle`, `soft` (the default) or `rounded`.

Each color has a `light` and `dark` value:

| Color                                  | Where it shows                                               |
| -------------------------------------- | ------------------------------------------------------------ |
| `primary`                              | Primary buttons, links, selected chips, switches that are on |
| `background`                           | The page                                                     |
| `surface`                              | Cards, lists, sheets and fields                              |
| `text`                                 | Body text                                                    |
| `muted`                                | Quiet fills: secondary buttons, chips                        |
| `border`                               | Lines around cards and fields                                |
| `subtle`                               | Quieter text: captions, hints                                |
| `info`, `success`, `warning`, `danger` | The tones: colored text, soft tints, messages and buttons    |

Without a theme, your dot looks like the rest of Dash. Many dots only set `primary`.

## Colors Dash fills in

Set as few colors as you can, and Dash fills in the rest. Give it a `background` and it works out cards, borders and quieter text to match. Leave out `text` and Dash picks dark or light text, whichever reads on your background. If you set a text color or a tone that's hard to read, `monime dot dev` warns you. Where `primary` wouldn't read, outline and ghost buttons, links and tabs use the text color.

## Custom colors

Name your own colors in `colors.custom`, then use them as a `View`'s `background` or a `Text`'s `tone`:

```ts title="dot.ts"
export default defineDot({
  pages: ['index', 'events'],
  theme: {
    colors: {
      custom: {
        gold: { light: '#F5C542', dark: '#D4A72C' },
        ink: { light: '#1C1C1E', dark: '#1C1C1E' },
      },
    },
  },
});
```

```xml title="pages/index/view.dml"
<View background="gold" radius="full" padding="small">
  <Text weight="medium" tone="ink">Gold member</Text>
</View>
```

Write names in camelCase, and don't reuse a built-in one like `surface`. Check custom colors in light and dark mode yourself.

## Fonts and text size

A dot uses the phone's own fonts, so nothing is downloaded and you can't add your own.

```ts title="dot.ts"
theme: {
  font: 'rounded',
  headingFont: 'serif',
  headingWeight: 'medium',
  textSize: 'large',
},
```

- `font` is `system` (the default), `rounded`, `serif` or `mono`. A phone with no rounded font, like most Android phones, uses its system font.
- `headingFont` and `headingWeight` set headings apart: a `Text`'s `display`, `title` and `subtitle`, and the titles of sheets and empty states. The weight is `regular`, `medium` or `bold`. A `Text`'s own `weight` wins.
- `textSize` is `small`, `regular` (the default) or `large`, which makes text a tenth smaller or larger. What's typed into fields keeps its size, and so do amounts, codes and small count pills.

## Spacing and shadows

`density` sets how much room the gaps and padding you name take. `compact` is three quarters of `regular`, the default, and `comfortable` is a quarter more. A card's own padding follows it too. The spacing inside a component, like a button's, stays as it is.

`elevation: 'raised'` gives every card and list a soft shadow in place of its hairline. A `View`'s own `elevation` and `border` still win, and a card with `elevation="none"` keeps its hairline.

A `Scroll` keeps room for `low` shadows, and a `Carousel` for every shadow, so the cards inside them aren't cut off.

```ts title="dot.ts"
theme: {
  density: 'comfortable',
  elevation: 'raised',
},
```

## Component defaults

Set a look once in `theme.components`, for every use of a component or for one of its variants:

```ts title="dot.ts"
theme: {
  components: {
    Button: { size: 'large' },
    View: { variants: { card: { elevation: 'low', border: 'none' } } },
  },
},
```

Now every `Button` is large, and every card has a soft shadow and no outline. A prop in the markup still wins, so `<Button size="small">` stays small. A variant's default wins over the component's.

Defaults can set props that choose a look, like `size`, `tone` or `padding`. They can't set what a component shows, like `icon` or `status`. While you develop, the dot won't start if a default isn't one the component takes, and the error says what is.

## Your own icons

Add your own icons to `theme.icons`, as SVG files in `statics/`:

```ts title="dot.ts"
theme: {
  icons: { 'ticket-stub': 'statics/icons/ticket-stub.svg' },
},
```

Then use the name wherever Dot's icons go:

```xml title="pages/index/view.dml"
<Icon name="ticket-stub" tone="success" />
<Chip label="VIP" icon="ticket-stub" />
```

- An icon is drawn in one color, its `tone`, whatever colors the file has.
- Write names as lowercase words joined by dashes, and don't reuse the name of one of [Dot's icons](/docs/products/dash-dots/reference/components#icon-names).
- The build refuses an SVG that holds scripts, stylesheets or links, or that isn't UTF-8. If yours is refused, export it from your design tool as plain shapes.

## Gradients

Name a gradient between two colors of your theme, then use it as a `View`'s `background`:

```ts title="dot.ts"
theme: {
  colors: {
    custom: {
      gold: { light: '#F5C542', dark: '#D4A72C' },
      ink: { light: '#1C1C1E', dark: '#1C1C1E' },
    },
  },
  gradients: {
    goldenHour: { from: 'gold', to: 'warning', direction: 'diagonal' },
  },
},
```

```xml title="pages/ticket/view.dml"
<View background="goldenHour" radius="large" padding="large">
  <Text variant="title" tone="ink">Salone Sounds Live</Text>
</View>
```

Each end is a theme color, like `primary` or `warning`, or one of your custom colors. `direction` is `down` (the default), `right` or `diagonal`. Pick text that reads on both ends.

## Page colors

One page can have its own colors, like a ticket page in the colors of the show. Add `configs.colors` to its `definePage`:

```ts title="pages/ticket/controller.ts"
export default definePage({
  initialState: state,
  configs: {
    colors: {
      background: { light: '#FFF3E0', dark: '#2B1A0E' },
    },
  },
});
```

A page can set any color in the table at the top of this page, tones included, each written as `#RRGGBB`. The colors it leaves out stay as the theme has them.

To change colors while the page runs, like turning a receipt green once the payment goes through, call `this.setColors()`:

```ts
this.setColors({ background: { light: '#E8F5E9', dark: '#0F2414' } });
```

Give both a `light` and a `dark` value, or the other mode keeps the color it had. To go back to the theme's color, set both to `undefined`:

```ts
this.setColors({ background: { light: undefined, dark: undefined } });
```

To change the whole dot's theme as it starts, call `this.setTheme()` in the `onLaunch` hook in `dot.ts`. Use it to apply a choice the person made earlier, like dark mode picked on your settings page. It replaces the whole theme, so spread the current one in: `this.setTheme({ ...this.theme, scheme: 'dark' })`. Dash's bars at the top and bottom have their own settings, in [Navigation](/docs/products/dash-dots/developers/navigation#dashs-bars).
