palette-core
TOML-defined theme system with inheritance and multi-target export.
Themes are authored as TOML presets. Variants inherit from a base and override only what changes. The crate parses, merges, and converts them into typed palettes for any rendering target.
Quick start
1. Ship a single preset
Pick a built-in theme and render it for your target.
CSS
use load_preset;
let palette = load_preset?;
let css = format!;
}
Prefix is optional — pass Some("app") to namespace variables as --app-bg, --app-fg, etc. See CSS variables reference for the full list.
Terminal (ratatui)
use load_preset;
use to_terminal_theme;
let palette = load_preset?;
let theme = to_terminal_theme;
// theme.base.background, theme.syntax.keywords, etc.
egui
use load_preset;
use to_egui_visuals;
let palette = load_preset?;
ctx.set_visuals;
JSON
use load_preset;
let palette = load_preset?;
let json = palette.to_json?;
WASM
import from "palette-core";
const palette = ;
console.log; // "TokyoNight (Night)"
console.log; // CSS custom properties (no prefix)
const css = ; // no prefix
const prefixed = ; // --app-bg, --app-fg, etc.
Beyond single presets
The guide covers:
- Theme switching —
Registryfor listing presets, generating all themes as CSS[data-theme]selectors, swapping at runtime - Developer-defined presets — custom base themes and variants that inherit from built-ins
- End-user presets — loading user-supplied TOML files at runtime, with full inheritance support
Utilities
WCAG contrast validation
use ;
use validate_palette;
let palette = load_preset?;
let violations = validate_palette;
for v in &violations
Color manipulation
use Color;
let base = from_hex?;
let hover = base.lighten;
let disabled = base.desaturate;
let accent = base.rotate_hue;
let overlay = base.blend;
let ratio = base.contrast_ratio;
Methods: lighten, darken, saturate, desaturate, rotate_hue, blend, contrast_ratio, meets_level. Manipulation methods take absolute amounts (CSS model). Non-finite inputs return the color unchanged.
Platform overrides
let manifest = from_toml?;
let overrides = from_sections?;
// overrides["terminal"].background, overrides["web"].foreground, etc.
Features
| Feature | Dependency | What it adds |
|---|---|---|
terminal |
ratatui |
Palette → ratatui::style::Color maps |
egui |
egui |
Palette → egui::Visuals |
snapshot |
serde_json |
JSON serialization of Palette |
platform |
— | Parse [platform.terminal] / [platform.web] overrides |
wasm |
wasm-bindgen, js-sys |
JavaScript bindings via wasm-bindgen (includes snapshot) |
full |
all except wasm |
terminal + egui + snapshot + platform |
Core functionality (parsing, merge, CSS export, WCAG contrast, color manipulation) requires no optional dependencies.
Bundled presets
| Family | Presets |
|---|---|
| Ayu | ayu_dark, ayu_light, ayu_mirage |
| Catppuccin | catppuccin, catppuccin_frappe, catppuccin_latte, catppuccin_macchiato |
| Dracula | dracula |
| Everforest | everforest_dark, everforest_light |
| GitHub | github_dark, github_light |
| Gruvbox | gruvbox_dark, gruvbox_light |
| Kanagawa | kanagawa |
| Monokai | monokai |
| Nord | nord |
| One | one_dark, one_light |
| Rosé Pine | rose_pine, rose_pine_dawn, rose_pine_moon |
| Solarized | solarized_dark, solarized_light |
| TokyoNight | tokyonight, tokyonight_storm, tokyonight_day, tokyonight_moon |
All presets are embedded at compile time via include_str!. Use preset_ids() to list them.
Preset format
Base presets define all sections. Variants declare inherits in [meta] and override only differing values.
[]
= "My Theme Storm"
= "my_theme_storm"
= "1"
= "storm"
= "preset-variant"
= "my_theme"
[]
= "#24283b"
Sections: base, semantic, diff, surface, typography, syntax, editor, terminal.
License
Licensed under either of Apache License, Version 2.0 or MIT License at your option.