๐ What is Opaline?
Opaline is a theme engine that brings consistent, beautiful color to Ratatui terminal applications. Instead of scattering hex codes across your codebase, you define themes as TOML files with a palette โ token โ style โ gradient resolution pipeline. Switch themes at runtime with a single call โ every widget updates instantly.
TOML file โ ThemeFile (serde) โ Resolver (palette โ tokens โ styles โ gradients) โ Theme
Opaline ships with 20 professionally crafted themes spanning 8 colorscheme families, all enforced by a strict contract test suite that validates 40+ semantic tokens, 18 styles, and 5 gradients per theme.
โฆ Features
| Feature | Description |
|---|---|
| ๐จ 20 Builtin Themes | SilkCircuit, Catppuccin, Dracula, Nord, Rose Pine, Gruvbox, Solarized, Tokyo Night, Kanagawa, Everforest, One Dark |
| ๐ Semantic Tokens | 40+ tokens across text.*, bg.*, accent.*, git.*, diff.*, code.* namespaces |
| ๐ Multi-Stop Gradients | Smooth color interpolation with gradient_bar(), gradient_text_line(), and gradient_spans() |
| ๐ฅ๏ธ Deep Ratatui Integration | From impls, Styled trait, inherent span(), line(), text(), gradient_text() on Theme |
| ๐๏ธ ThemeSelector Widget | Drop-in theme picker with live preview, search filtering, and cancel/restore |
| ๐ฌ Color Manipulation | darken(), lighten(), desaturate() for deriving colors from theme palettes |
| ๐๏ธ ThemeBuilder | Programmatic theme construction without TOML โ perfect for runtime customization |
| ๐งฉ App-Level Derivation | Register app-specific tokens/styles with register_default_token() โ TOML overrides respected |
| ๐ Theme Discovery | Scan ~/.config/ for user themes, list metadata for picker UIs |
| ๐ Global State | Optional process-wide current()/set_theme() behind a feature flag |
| ๐ก๏ธ Strict Resolution | Cycle detection, unresolvable token errors, compile-time theme validation |
| ๐จ๏ธ CLI Adapter | colored crate integration for ANSI terminal output outside of Ratatui |
| โก Zero Cost Builtins | Themes embedded via include_str! at compile time โ no file I/O at runtime |
โก Quick Start
Add opaline to your Cargo.toml:
[]
= "0.1"
Load a theme and start styling:
use load_by_name;
// Load any of 20 builtin themes
let theme = load_by_name.expect;
// Use semantic colors and styles in your Ratatui widgets
let style = theme.style; // bold accent color
let color = theme.color; // OpalineColor
let span = theme.span; // styled Span
Run the interactive demo
Browse all 20 themes, see every style and gradient rendered in real-time.
๐จ Builtin Themes
| Family | Variants | Character |
|---|---|---|
| SilkCircuit | Neon, Soft, Glow, Vibrant, Dawn | Electric meets elegant โ the signature design language |
| Catppuccin | Mocha, Latte | Soothing pastels for dark and light |
| Rose Pine | Base, Moon, Dawn | Botanical elegance across three variants |
| Everforest | Dark, Light | Warm green forest tones |
| Tokyo Night | Default, Storm | Neo-Tokyo neon aesthetic |
| Dracula | โ | The classic dark syntax theme |
| Nord | โ | Arctic, north-bluish clean |
| Gruvbox | Dark | Retro groove with warm contrast |
| One Dark | โ | Atom's iconic syntax palette |
| Solarized | Light | Precision colors for machines and people |
| Kanagawa | Wave | The great wave off Kanagawa |
Every theme is contract-tested: 40+ semantic tokens, 18 required styles, 5 required gradients.
๐ฎ Usage
Colors and Styles
use Theme;
let theme = default; // SilkCircuit Neon
// Semantic color access
let primary = theme.color;
let bg = theme.color;
// Composed styles (fg + bg + modifiers)
let keyword = theme.style; // bold accent
let error = theme.style; // red foreground
let selected = theme.style; // accent on highlight bg
// Styled spans for inline text โ no trait import needed
let path = theme.span;
let hash = theme.span;
Gradients
use ;
let theme = default;
// Render a gradient progress bar
if let Some = theme.get_gradient
// Gradient-styled text (each character gets interpolated color)
let title = theme.gradient_text;
Theme Switching
use ;
// Enumerate all themes for a picker UI
let themes = list_available_themes;
for info in &themes
// Hot-swap themes at runtime
let dracula = load_by_name.unwrap;
let nord = load_by_name.unwrap;
ThemeBuilder (Programmatic)
use ThemeBuilder;
let theme = new
.palette
.palette
.palette
.token
.token
.token
.style
.build
.expect;
๐ช Custom Themes
Drop a .toml file in src/builtins/ โ it's auto-discovered at compile time. Or load from any path at runtime.
[]
= "My Theme"
= "your name"
= "dark" # or "light"
= "A custom theme"
[]
= "#1a1b26"
= "#c0caf5"
= "#7aa2f7"
= "#bb9af7"
[]
= "fg"
= "bg"
= "blue"
# ... 40+ tokens across text.*, bg.*, accent.*, git.*, diff.*, code.*, etc.
[]
= { = "accent.primary", = true }
# ... 18 required styles
[]
= ["blue", "purple"]
# ... 5 required gradients
The resolver validates everything at load time โ circular references, missing tokens, and invalid colors all produce clear error messages via OpalineError.
โ๏ธ Feature Flags
| Feature | Default | Description |
|---|---|---|
builtin-themes |
โ | 20 embedded TOML themes via include_str! |
gradients |
โ | Multi-stop gradient interpolation |
ratatui |
โ | From impls, inherent span()/line()/text()/gradient_text() |
cli |
โ | colored crate adapter for ANSI output |
global-state |
โ | Process-wide current()/set_theme() |
discovery |
โ | Load user themes from ~/.config/ |
widgets |
โ | Theme selector widget with live preview |
๐๏ธ Architecture
TOML โ ThemeFile (serde) โ Resolver โ Theme
โ โ โ
โ palette โ โโโ color("token.name") โ OpalineColor
โ tokens โ โโโ style("style_name") โ OpalineStyle
โ styles โ โโโ gradient("name") โ Gradient
โ gradients โ โโโ meta (name, author, variant)
โ โ
โ โโโ palette โ token resolution
โ โโโ token โ style resolution
โ โโโ cycle detection
โ โโโ gradient stop resolution
| Component | Purpose |
|---|---|
OpalineColor |
RGB color with hex/tuple/array/u32 conversions + lerp + darken/lighten/desaturate |
OpalineStyle |
Composed style (fg, bg, 9 modifiers) with builder pattern |
Gradient |
Multi-stop color interpolation with at(t) and generate(n) |
Theme |
Fully resolved theme with color(), style(), gradient() accessors |
ThemeBuilder |
Programmatic theme construction without TOML |
ThemeInfo |
Metadata for theme discovery and picker UIs |
OpalineError |
Typed errors for IO, parsing, resolution, and validation failures |
๐งช Development
Requires Rust 1.85+ (Edition 2024). unsafe_code = "forbid", clippy::pedantic deny.
๐ค Contributing
Contributions welcome! Adding a new builtin theme is as easy as dropping a .toml file in src/builtins/ โ it's auto-discovered at compile time. Run cargo test --all-features to validate against the contract test suite.
โ๏ธ License
Distributed under the MIT License. See LICENSE for details.
๐ Documentation ยท ๐ฆ API Reference ยท ๐ Report Bug ยท ๐ก Request Feature
Created by Stefanie Jane ๐
If you find this useful, buy me a Monster Ultra Violet! โก๏ธ