OPALINE(1)

NAME

opaline✦ A token-based theme engine for Rust TUI applications

SYNOPSIS

INFO

78 stars
1 forks
0 views

DESCRIPTION

✦ A token-based theme engine for Rust TUI applications

README


✦ opaline

A token-based theme engine for Rust applications
39 builtin themes · semantic tokens · multi-stop gradients · ratatui · egui · iced · crossterm · syntect · CSS

Crates.io docs.rs CI 39 Themes License

Docsllms.txtQuick StartFeaturesThemesUsageCustom ThemesContributing


SilkCircuit Neon SilkCircuit Dawn

SilkCircuit Neon (dark) and SilkCircuit Dawn (light) — two of 39 builtin themes


💜 What is Opaline?

Opaline is a theme engine that brings consistent, beautiful color to Rust 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.

Opaline ships adapters for ratatui, egui, iced, crossterm, owo-colors, syntect, and CSS — one theme definition, every rendering target.

TOML file → ThemeFile (serde) → Resolver (palette → tokens → styles → gradients) → Theme

Opaline ships with 39 professionally crafted themes spanning 17 colorscheme families, all enforced by a strict contract test suite that validates 26 core semantic tokens, 13 required styles, and 5 gradients per theme.

✦ Features

FeatureDescription
🎨 39 Builtin ThemesSilkCircuit, Catppuccin, GitHub, Monokai Pro, Ayu, Night Owl, Flexoki, Palenight, Dracula, Nord, Rose Pine, Gruvbox, Solarized, Tokyo Night, Kanagawa, Everforest, One Dark/Light
🔗 Semantic Tokens26 core tokens across generic text.*, bg.*, accent.*, border.*, and code.* namespaces
🌊 Multi-Stop GradientsSmooth color interpolation with gradient_bar(), gradient_text_line(), and gradient_spans()
🖥️ Deep Ratatui IntegrationFrom impls, Styled trait, inherent span(), line(), text(), gradient_text() on Theme
🎮 egui IntegrationColor32 conversion, full Visuals generation from theme tokens
🪄 iced IntegrationColor conversion plus Palette/Custom theme generation from theme tokens
⌨️ Crossterm AdapterDirect Color/ContentStyle conversion with gradient rendering
🌈 owo-colors AdapterZero-allocation terminal coloring with Style conversion
🖌️ Syntax HighlightingGenerate syntect themes — powers bat, delta, and more
🌐 CSS GenerationCustom properties + classes for web frameworks (Leptos, Yew, Dioxus, Tauri)
🎛️ ThemeSelector WidgetDrop-in theme picker with live preview, search filtering, and cancel/restore
🔬 Color Manipulationdarken(), lighten(), desaturate() for deriving colors from theme palettes
🏗️ ThemeBuilderProgrammatic theme construction without TOML — perfect for runtime customization
🧩 App-Level DerivationRegister app-specific tokens/styles with register_default_token() — TOML overrides respected
🔍 Theme DiscoveryScan ~/.config/ for user themes, list metadata for picker UIs
🌐 Global StateOptional process-wide current()/set_theme() behind a feature flag
🛡️ Strict ResolutionCycle detection, unresolvable token errors, compile-time theme validation
🖨️ CLI Adaptercolored crate integration for ANSI terminal output
Zero Cost BuiltinsThemes embedded via include_str! at compile time — no file I/O at runtime

⚡ Quick Start

Add opaline to your Cargo.toml:

[dependencies]
opaline = "0.2"

Load a theme and start styling:

use opaline::load_by_name;

// Load any builtin theme let theme = load_by_name("catppuccin-mocha").expect("theme exists");

// Use semantic colors and styles in your Ratatui widgets let style = theme.style("keyword"); // bold accent color let color = theme.color("accent.primary"); // OpalineColor let span = theme.span("muted", "src/main.rs"); // styled Span

Run the interactive demo

cargo run --example theme-showcase

Browse all 39 themes, see every style and gradient rendered in real-time.

🎨 Builtin Themes

Catppuccin Mocha Rose Pine
Catppuccin Latte Everforest Light
FamilyVariantsCharacter
SilkCircuitNeon, Soft, Glow, Vibrant, DawnElectric meets elegant — the signature design language
CatppuccinMocha, Macchiato, Frappé, LatteSoothing pastels across four flavors
GitHubDark Dimmed, LightClean, familiar, institutional
Monokai ProClassicThe iconic warm vivid syntax palette
AyuDark, Mirage, LightCalm, modern, bright across three modes
Night OwlDark, LightAccessibility-designed deep blue
FlexokiDark, LightInk-on-paper aesthetic, Oklab-designed
PalenightSoft purple-blue pastel sci-fi
Rose PineBase, Moon, DawnBotanical elegance across three variants
EverforestDark, LightWarm green forest tones
Tokyo NightDefault, Storm, MoonNeo-Tokyo neon aesthetic
KanagawaWave, Dragon, LotusThe great wave — dark, darker, light
DraculaThe classic dark syntax theme
NordArctic, north-bluish clean
GruvboxDark, LightRetro groove with warm contrast
SolarizedDark, LightPrecision colors for machines and people
OneDark, LightAtom's iconic syntax palette

Every theme is contract-tested: 26 core semantic tokens, 13 required styles, 5 required gradients.

🔮 Usage

Colors and Styles

use opaline::Theme;

let theme = Theme::default(); // SilkCircuit Neon

// Semantic color access let primary = theme.color("accent.primary"); let bg = theme.color("bg.base");

// Composed styles (fg + bg + modifiers) let keyword = theme.style("keyword"); // bold accent let error = theme.style("error_style"); // red foreground let selected = theme.style("active_selected"); // accent on highlight bg

// Styled spans for inline text — no trait import needed let path = theme.span("muted", "src/lib.rs"); let keyword_span = theme.span("keyword", "fn");

Gradients

use opaline::{Theme, gradient_bar};

let theme = Theme::default();

// Render a gradient progress bar if let Some(gradient) = theme.get_gradient("aurora") { let bar = gradient_bar(40, '█', gradient); // Line with per-char colors }

// Gradient-styled text (each character gets interpolated color) let title = theme.gradient_text("primary", "Opaline Theme Engine");

Theme Switching

use opaline::{list_available_themes, load_by_name};

// Enumerate all themes for a picker UI let themes = list_available_themes(); for info in &themes { let author = if info.author.is_empty() { "—" } else { &info.author }; println!("{} ({:?}) by {}", info.display_name, info.variant, author); }

// Hot-swap themes at runtime let dracula = load_by_name("dracula").unwrap(); let nord = load_by_name("nord").unwrap();

ThemeBuilder (Programmatic)

use opaline::{OpalineColor, OpalineStyle, Theme};

let theme = Theme::builder("My Theme") .palette("bg", OpalineColor::new(26, 27, 38)) .palette("fg", OpalineColor::new(192, 202, 245)) .palette("blue", OpalineColor::new(122, 162, 247)) .token("text.primary", OpalineColor::new(192, 202, 245)) .token("bg.base", OpalineColor::new(26, 27, 38)) .token("accent.primary", OpalineColor::new(122, 162, 247)) .style("keyword", OpalineStyle::fg(OpalineColor::new(122, 162, 247)).bold()) .build();

🪄 Custom Themes

Add a builtin theme by dropping a .toml file in src/builtins/. For user themes, load from any path at runtime or place the file in your app's theme directory.

[meta]
name = "My Theme"
author = "your name"
variant = "dark"   # or "light"
description = "A custom theme"

[palette] bg = "#1a1b26" fg = "#c0caf5" blue = "#7aa2f7" purple = "#bb9af7"

[tokens] "text.primary" = "fg" "bg.base" = "bg" "bg.selection" = "bg" "accent.primary" = "blue"

... 26 required core tokens across text., bg., accent., border., code.*, etc.

[styles] keyword = { fg = "accent.primary", bold = true }

... 13 required core styles

[gradients] primary = ["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

FeatureDefaultDescription
builtin-themes39 embedded TOML themes via include_str!
gradientsMulti-stop gradient interpolation
ratatuiFrom impls, inherent span()/line()/text()/gradient_text()
clicolored crate adapter for ANSI output
crosstermDirect crossterm Color/ContentStyle adapter
owo-colorsZero-allocation terminal coloring
cssCSS custom properties + classes generation
syntectSyntax highlighting theme generation
eguiegui Visuals/Color32 adapter
icediced Custom/Palette/Color adapter
global-stateProcess-wide current()/set_theme()
discoveryLoad user themes from ~/.config/
widgetsTheme 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
ComponentPurpose
OpalineColorRGB color with hex/tuple/array/u32 conversions + lerp + darken/lighten/desaturate
OpalineStyleComposed style (fg, bg, 9 modifiers) with builder pattern
GradientMulti-stop color interpolation with at(t) and generate(n)
ThemeFully resolved theme with color(), style(), gradient() accessors
ThemeBuilderProgrammatic theme construction without TOML
ThemeInfoMetadata for theme discovery and picker UIs
OpalineErrorTyped errors for IO, parsing, resolution, and validation failures

🧪 Development

cargo check                               # Fast type check
cargo clippy --all-targets --all-features  # Pedantic lint gate
cargo test --all-features                  # Full test suite (210 tests)
cargo doc --all-features --open            # Generate docs
cargo run --example theme-showcase         # Interactive TUI demo

Requires Rust 1.85+ (Edition 2024). unsafe_code = "forbid", clippy::pedantic deny.

🚀 Used By

ProjectDescription
git-irisAI-powered Git workflow assistant with Iris Studio TUI
uniflyCLI + TUI for UniFi network management

🤝 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! ⚡️

SEE ALSO

clihub5/9/2026OPALINE(1)