Code Tokens
@themvora/core — syntax highlighting tokens
Themvora includes a dedicated code token group for syntax highlighting. Every token maps to a --theme-code-* CSS variable that Shiki (or any highlighter) can consume directly — so your code blocks re-theme automatically when the user switches themes, families, or modes.
1Define code tokens in your theme
import { defineTheme } from "@themvora/core";
const brand = defineTheme({
name: "brand-dark",
meta: { family: "brand", mode: "dark" },
tokens: {
colors: {
background: "#0d1117",
foreground: "#e6edf3",
primary: "#58a6ff",
primaryForeground: "#0d1117",
// ... other semantic colors
},
typography: {
fontFamilies: { mono: "JetBrains Mono, ui-monospace, monospace" },
},
code: {
background: "#161b22",
foreground: "#e6edf3",
comment: "#8b949e",
keyword: "#ff7b72",
string: "#a5d6ff",
number: "#79c0ff",
function: "#d2a8ff",
variable: "#e6edf3",
type: "#ffa657",
property: "#79c0ff",
operator: "#ff7b72",
punctuation: "#8b949e",
tag: "#ff7b72",
attribute: "#79c0ff",
lineNumber: "#484f58",
selection: "rgba(88, 166, 255, 0.3)",
highlight: "rgba(255, 255, 255, 0.08)",
gutter: "#161b22",
},
},
});These tokens produce CSS variables like --theme-code-background,--theme-code-keyword,--theme-code-string, and so on — ready for any syntax highlighter.
2Code token reference
| Token | CSS Variable | Purpose | Fallback |
|---|---|---|---|
background | --theme-code-background | Code block background | muted / background mix |
foreground | --theme-code-foreground | Default text color in code | foreground |
comment | --theme-code-comment | Comments, docstrings | foreground @ 55% |
keyword | --theme-code-keyword | Keywords, control flow, storage | primary |
string | --theme-code-string | String literals, templates | primary + green mix |
number | --theme-code-number | Numeric literals | primary + orange mix |
function | --theme-code-function | Function/method names | primary + blue mix |
variable | --theme-code-variable | Variables, parameters | foreground |
type | --theme-code-type | Types, classes, interfaces | primary + purple mix |
property | --theme-code-property | Object properties | foreground + primary mix |
operator | --theme-code-operator | Operators, punctuation | foreground + primary mix |
punctuation | --theme-code-punctuation | Brackets, commas, semicolons | foreground @ 70% |
tag | --theme-code-tag | HTML/JSX/Vue/Astro tag names | primary + pink mix |
attribute | --theme-code-attribute | Attribute names in markup | foreground + primary mix |
lineNumber | --theme-code-lineNumber | Line number gutter color | muted-foreground |
selection | --theme-code-selection | Text selection background | primary @ 30% |
highlight | --theme-code-highlight | Highlighted line background | white @ 8% |
gutter | --theme-code-gutter | Line number gutter background | code background |
border | --theme-code-border | Code block border color | border |
3Enable code tokens in your app
The docs app uses Shiki with a custom theme that reads --theme-code-*variables. Here's the pattern to connect any highlighter:
/* In your global CSS — these map to --theme-code-* variables */
.code-block {
/* These become --tv-syntax-* variables used by Shiki */
--tv-code-bg: var(--theme-code-background, var(--theme-color-muted));
--tv-syntax-plain: var(--theme-code-foreground, var(--theme-color-foreground));
--tv-syntax-comment: var(--theme-code-comment, color-mix(...));
--tv-syntax-keyword: var(--theme-code-keyword, var(--theme-color-primary));
--tv-syntax-string: var(--theme-code-string, color-mix(...));
--tv-syntax-number: var(--theme-code-number, color-mix(...));
--tv-syntax-function: var(--theme-code-function, color-mix(...));
--tv-syntax-type: var(--theme-code-type, color-mix(...));
--tv-syntax-tag: var(--theme-code-tag, color-mix(...));
--tv-syntax-attr: var(--theme-code-attribute, color-mix(...));
--tv-syntax-variable: var(--theme-code-variable, var(--theme-color-foreground));
--tv-syntax-property: var(--theme-code-property, color-mix(...));
--tv-syntax-operator: var(--theme-code-operator, color-mix(...));
--tv-syntax-punctuation: var(--theme-code-punctuation, color-mix(...));
--tv-syntax-diff-add: var(--theme-code-lineNumber, color-mix(...));
--tv-syntax-diff-remove: var(--theme-code-selection, color-mix(...));
--tv-syntax-danger: var(--theme-code-highlight, var(--theme-color-destructive));
}4Best practices
Define both light and dark variants
Code tokens should adapt to the theme mode. A dark theme needs a dark code background (#161b22), while a light theme needs a light one (#f6f8fa). Use extendThemeto share the base and override just the code group:
const base = defineTheme({
name: "base",
tokens: {
code: {
comment: "#6a737d",
keyword: "#d73a49",
string: "#032f62",
// ...shared tokens
},
},
});
const light = extendTheme("brand-light", base, {
meta: { mode: "light" },
tokens: {
code: {
background: "#f6f8fa",
foreground: "#24292e",
selection: "rgba(0, 0, 0, 0.1)",
},
},
});
const dark = extendTheme("brand-dark", base, {
meta: { mode: "dark" },
tokens: {
code: {
background: "#161b22",
foreground: "#e6edf3",
selection: "rgba(88, 166, 255, 0.3)",
},
},
});Use semantic fallbacks in CSS
Always provide fallbacks using semantic color tokens so code blocks stay readable even if a theme doesn't define code tokens. The CSS mapping in Section 3 demonstrates the pattern — each --tv-syntax-* variable falls back to a --theme-color-* token via var() or color-mix().
Generate from a seed color
Use generateTheme to create a complete theme pair (including harmonized code tokens) from a single brand color. See the Custom Themes guide for the full generation API.