Color mode

This page is part of Themes in Depth and covers design tokens.

Design tokens

3-4. tokens

Core's ThemeDesignTokens has the following semantic groups. In stylesheets they are handled as --rb-* semantic CSS custom properties.

Components and plugins reference a meaning such as body color, background, accent, or border, rather than a theme-specific value such as "this theme's black" or "this theme's gray".

Diagram source
text
flowchart LR
    UI["Component / Plugin"]
    Token["--rb-color-ink"]
    ThemeA["Theme A<br/>#202020"]
    ThemeB["Theme B<br/>#d8dee9"]
 
    UI --> Token
    ThemeA --> Token
    ThemeB --> Token

This is what lets a theme be swapped without touching components.

Color:

Token CSS variable
paper --rb-color-paper
ink --rb-color-ink
muted --rb-color-muted
accent --rb-color-accent
border --rb-color-border
borderStrong --rb-color-border-strong
surface --rb-color-surface
surfaceHover --rb-color-surface-hover
overlay --rb-color-overlay
danger --rb-color-danger
success --rb-color-success
codeBackground --rb-color-code-background

Typography:

Token CSS variable
bodyFont --rb-font-body
headingFont --rb-font-heading
monoFont --rb-font-mono

Layout:

Token CSS variable
pageMaxWidth --rb-layout-page-max
articleMaxWidth --rb-layout-article-max
sidebarWidth --rb-layout-sidebar
contentGap --rb-layout-gap
css
@layer base {
  :is(:root, .rb-theme-root)[data-theme-name="<name>"] {
    --rb-color-paper: #fafafa;
    --rb-color-ink: #202020;
    --rb-color-accent: #555;
    --rb-font-body: system-ui, sans-serif;
    --rb-layout-article-max: 48rem;
  }
}

Note that the CSS variable names are kebab-case versions of the token names (borderStrong → --rb-color-border-strong, and so on); the input token name and the CSS variable differ.

Why semantic tokens: if components or plugins reference a specific theme's color names directly, the theme can no longer be swapped.

css
/* good */
.rr-example {
  color: var(--rb-color-ink);
  background: var(--rb-color-surface);
}
 
/* avoid */
.rr-example {
  color: #171717;
  background: #f6efe2;
}

Tokens with plugin-specific meaning are owned by the plugin as --rr-*, falling back to --rb-* when available:

css
--rr-example-background: var(--rb-color-surface);

History

1 changesCollapseExpand
1 + ---
2 + title: Design tokens
3 + sidebar:
4 + label: Design tokens
5 + order: 30
6 + ---
7 +
8 + This page is part of [Themes in Depth](../theme-system.md) and covers design tokens.
9 +
10 + # Design tokens
11 +
12 + ## 3-4. tokens
13 +
14 + Core's `ThemeDesignTokens` has the following semantic groups. In stylesheets they are handled as `--rb-*` semantic CSS custom properties.
15 +
16 + Components and plugins reference a **meaning** such as body color, background, accent, or border, rather than a theme-specific value such as "this theme's black" or "this theme's gray".
17 +
18 + ```mermaid
19 + flowchart LR
20 + UI["Component / Plugin"]
21 + Token["--rb-color-ink"]
22 + ThemeA["Theme A<br/>#202020"]
23 + ThemeB["Theme B<br/>#d8dee9"]
24 +
25 + UI --> Token
26 + ThemeA --> Token
27 + ThemeB --> Token
28 + ```
29 +
30 + This is what lets a theme be swapped without touching components.
31 +
32 + **Color:**
33 +
34 + | Token | CSS variable |
35 + | --- | --- |
36 + | `paper` | `--rb-color-paper` |
37 + | `ink` | `--rb-color-ink` |
38 + | `muted` | `--rb-color-muted` |
39 + | `accent` | `--rb-color-accent` |
40 + | `border` | `--rb-color-border` |
41 + | `borderStrong` | `--rb-color-border-strong` |
42 + | `surface` | `--rb-color-surface` |
43 + | `surfaceHover` | `--rb-color-surface-hover` |
44 + | `overlay` | `--rb-color-overlay` |
45 + | `danger` | `--rb-color-danger` |
46 + | `success` | `--rb-color-success` |
47 + | `codeBackground` | `--rb-color-code-background` |
48 +
49 + **Typography:**
50 +
51 + | Token | CSS variable |
52 + | --- | --- |
53 + | `bodyFont` | `--rb-font-body` |
54 + | `headingFont` | `--rb-font-heading` |
55 + | `monoFont` | `--rb-font-mono` |
56 +
57 + **Layout:**
58 +
59 + | Token | CSS variable |
60 + | --- | --- |
61 + | `pageMaxWidth` | `--rb-layout-page-max` |
62 + | `articleMaxWidth` | `--rb-layout-article-max` |
63 + | `sidebarWidth` | `--rb-layout-sidebar` |
64 + | `contentGap` | `--rb-layout-gap` |
65 +
66 + ```css
67 + @layer base {
68 + :is(:root, .rb-theme-root)[data-theme-name="<name>"] {
69 + --rb-color-paper: #fafafa;
70 + --rb-color-ink: #202020;
71 + --rb-color-accent: #555;
72 + --rb-font-body: system-ui, sans-serif;
73 + --rb-layout-article-max: 48rem;
74 + }
75 + }
76 + ```
77 +
78 + Note that the CSS variable names are kebab-case versions of the token names (`borderStrong` → `--rb-color-border-strong`, and so on); the input token name and the CSS variable differ.
79 +
80 + **Why semantic tokens**: if components or plugins reference a specific theme's color names directly, the theme can no longer be swapped.
81 +
82 + ```css
83 + /* good */
84 + .rr-example {
85 + color: var(--rb-color-ink);
86 + background: var(--rb-color-surface);
87 + }
88 +
89 + /* avoid */
90 + .rr-example {
91 + color: #171717;
92 + background: #f6efe2;
93 + }
94 + ```
95 +
96 + Tokens with plugin-specific meaning are owned by the plugin as `--rr-*`, falling back to `--rb-*` when available:
97 +
98 + ```css
99 + --rr-example-background: var(--rb-color-surface);
100 + ```
101 +