---
title: "Theming"
id: "guide:theming"
---

<Message status="info">
  For individual design tokens, see the design system documentations as well.
</Message>

<DocLinkCardGrid
  links={[
    { id: "design-system:colors" },
    { id: "design-system:typography" },
    { id: "design-system:misc" },
  ]}
/>

## Overview

All of Camome's design tokens (colors, fonts, radii, etc.) are exported as [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) so that you can easily customize the appearance for your brand.

Dark theme is supported by default.

## Default Theme

The default theme file can be imported from `@camome/system/theme.css`, `@camome/system.theme.min.css`, or [unpkg.com](https://unpkg.com/@camome/system@latest/dist/theme.css). If you don't need to customize it, use it directly.

## Configuration File (Optional)

Create a `camome.config.js` file in the project root.

```tsx:camome.config.js
import { defineConfig } from "@camome/system";

export default defineConfig({
  themes: {
    light: {
      color: {
        primary: {
          0: "#faf5ff",
          1: "#f3e8ff",
          2: "#e9d5ff",
          3: "#d8b4fe",
          4: "#c084fc",
          5: "#a855f7",
          6: "#9333ea",
          7: "#7e22ce",
          8: "#6b21a8",
          9: "#581c87",
        },
      },
      Switch: {
        bgOn: (get) => get("color.success.emphasis"),
        bgOff: (get) => get("color.danger.emphasis"),
        fontOff: (get) => get("color.font.onEmphasis"),
      },
    },
  },
});
```

In this example, the primary color is changed to purple, so custom accent colors are applied to all components such as buttons and checkboxes at once.

`Switch` properties are an example of component-level tokens. Many components use generic tokens such as `color.<color-scheme>.<variant>...`, so there is no need to set them individually, but complex components have their own tokens.

<Message status="info">
  {/* prettier-ignore-start */}
  For example, `<Button colorScheme="danger" variant="solid" />` uses `color.danger.solid.bg`
  and so on, and these are also shared with `<Tag
    colorScheme="danger"
    variant="solid"
  />
  `. Currently, it is not possible to change these individually for each
  component (mainly to keep the size of global CSS small).
  {/* prettier-ignore-end */}
</Message>

### Get another token in theme config

Like the above `Switch` example, if you want to refer to another token in theme config, pass a callback function that accepts `get(path: string)` as the first parameter.

```js:camome.config.js
import { alpha } from "./color-utils";

/** @type { import("@camome/system").Config;} */
export default {
  themes: {
    light: {
      color: {
        primary: {
          subtle: (get) => alpha(get("color.primary.5"), 0.5),
        },
      },
    },
  },
};
```

In this example, semi-transparent version of `color.primary.5` is passed to `color.primary.subtle`. Even if `color.primary.subtle` is referencing to another token, `get` function is invoked recursively until it resolves to an actual value.

<Message status="warn">Be careful with circular reference.</Message>

<Message status="info">
  Because some of the tokens in the default theme are referencing, changes to
  color shades (like `primary.color.5`) _cascade_ down other tokens.
</Message>

## Camome CLI

You can use Camome CLI to generate a custom theme with the definition of the configuration file.

```bash
npx camome theme
```

The following options are available:

- `--output`: Path of CSS generation destination (defaults to `theme.css`)
- `--config`: Path of configuration file (defaults to `camome.config.js`)

<Message status="info">
  `--watch` Mode and integration with bundlers are under consideration.
  Currently, please run the command each time you change the theme.
</Message>

## Overriding Components

At the top of Camome's `theme.css`, priority of [CSS Cascade Layers](https://developer.mozilla.org/ja/docs/Web/CSS/@layer) is declared as follows:

```css
@layer cmm.reset, cmm.theme, cmm.base, cmm.components;
```

Thanks to this line, CSS styles declared after `theme.css` will always win regardless of specificity or order (as long as they are not inside the layers mentioned above). You can create a layer like `cmm.custom` but it is completely optional.

```css:globals.css
/* Override styles of Button
   (Outside of @layer always wins over inside) */
.Button {
  border-radius: 999px;
}

/* Optional */
@layer cmm.custom {...}
```

## Dark theme

Camome supports both `light` and `dark` themes, which can be specified by the `data-theme` attribute.

```html:index.html
<!DOCTYPE html>
<html data-theme="<light or dark>">
  <!-- Content -->
</html>
```

Tokens for each theme is defined as follows in `theme.css`:

```css:theme.css
@layer cmm.theme {
  :root[data-theme="light"] {
    --cmm-color-primary-font: var(--cmm-color-primary-7);
    --cmm-color-primary-emphasis: var(--cmm-color-primary-6);
    {...}
  }
  /* And dark theme as well... */
}
```

To style according to each theme in your own CSS:

```css
:root[data-theme="dark"] .your-class {
  /* Your styles for dark theme... */
}
```

<Message status="info">
  `light` and `dark` can be customized independently. Please refer to the
  [configuration file](#configuration-file-optional) section.
</Message>

## Font

While OS's system fonts are specified in default themes, demos in this docs are using [Inter](https://fonts.google.com/specimen/Inter) for latin characters. For changing fonts, see <DocLink id="design-system:typography"/>.
