Skip to content

hyperb1iss/opaline

Repository files navigation


✦ opaline

A token-based theme engine for Rust applications
39 builtin themes · semantic tokens · multi-stop gradients · ratatui · egui · 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, 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

Feature Description
🎨 39 Builtin Themes SilkCircuit, Catppuccin, GitHub, Monokai Pro, Ayu, Night Owl, Flexoki, Palenight, Dracula, Nord, Rose Pine, Gruvbox, Solarized, Tokyo Night, Kanagawa, Everforest, One Dark/Light
🔗 Semantic Tokens 26 core tokens across generic text.*, bg.*, accent.*, border.*, and 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
🎮 egui Integration Color32 conversion, full Visuals generation from theme tokens
⌨️ Crossterm Adapter Direct Color/ContentStyle conversion with gradient rendering
🌈 owo-colors Adapter Zero-allocation terminal coloring with Style conversion
🖌️ Syntax Highlighting Generate syntect themes — powers bat, delta, and more
🌐 CSS Generation Custom properties + classes for web frameworks (Leptos, Yew, Dioxus, Tauri)
🎛️ 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
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:

[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
Family Variants Character
SilkCircuit Neon, Soft, Glow, Vibrant, Dawn Electric meets elegant — the signature design language
Catppuccin Mocha, Macchiato, Frappé, Latte Soothing pastels across four flavors
GitHub Dark Dimmed, Light Clean, familiar, institutional
Monokai Pro Classic The iconic warm vivid syntax palette
Ayu Dark, Mirage, Light Calm, modern, bright across three modes
Night Owl Dark, Light Accessibility-designed deep blue
Flexoki Dark, Light Ink-on-paper aesthetic, Oklab-designed
Palenight Soft purple-blue pastel sci-fi
Rose Pine Base, Moon, Dawn Botanical elegance across three variants
Everforest Dark, Light Warm green forest tones
Tokyo Night Default, Storm, Moon Neo-Tokyo neon aesthetic
Kanagawa Wave, Dragon, Lotus The great wave — dark, darker, light
Dracula The classic dark syntax theme
Nord Arctic, north-bluish clean
Gruvbox Dark, Light Retro groove with warm contrast
Solarized Dark, Light Precision colors for machines and people
One Dark, Light Atom'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

Feature Default Description
builtin-themes 39 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
crossterm Direct crossterm Color/ContentStyle adapter
owo-colors Zero-allocation terminal coloring
css CSS custom properties + classes generation
syntect Syntax highlighting theme generation
egui egui Visuals/Color32 adapter
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

cargo check                               # Fast type check
cargo clippy --all-targets --all-features  # Pedantic lint gate
cargo test --all-features                  # Full test suite (203 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

Project Description
git-iris AI-powered Git workflow assistant with Iris Studio TUI
unifly CLI + 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! ⚡️

About

✦ A token-based theme engine for Ratatui TUI applications

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors