Skip to main content

ThemeSpec

Struct ThemeSpec 

Source
pub struct ThemeSpec {
    pub name: String,
    pub light: Option<ThemeVariant>,
    pub dark: Option<ThemeVariant>,
}
Expand description

A complete native theme with a name and optional light/dark variants.

This is the top-level type that theme files deserialize into and that platform readers produce.

§Examples

use native_theme::ThemeSpec;

// Load a bundled preset
let theme = ThemeSpec::preset("dracula").unwrap();
assert_eq!(theme.name, "Dracula");

// Parse from a TOML string
let toml = r##"
name = "Custom"
[light.defaults]
accent = "#ff6600"
"##;
let custom = ThemeSpec::from_toml(toml).unwrap();
assert_eq!(custom.name, "Custom");

// Merge themes (overlay wins for populated fields)
let mut base = ThemeSpec::preset("catppuccin-mocha").unwrap();
base.merge(&custom);
assert_eq!(base.name, "Catppuccin Mocha"); // base name is preserved

Fields§

§name: String

Theme name (e.g., “Breeze”, “Adwaita”, “Windows 11”).

§light: Option<ThemeVariant>

Light variant of the theme.

§dark: Option<ThemeVariant>

Dark variant of the theme.

Implementations§

Source§

impl ThemeSpec

Source

pub fn new(name: impl Into<String>) -> Self

Create a new theme with the given name and no variants.

Source

pub fn merge(&mut self, overlay: &Self)

Merge an overlay theme into this theme.

The base name is kept. For each variant (light/dark):

  • If both base and overlay have a variant, they are merged recursively.
  • If only the overlay has a variant, it is cloned into the base.
  • If only the base has a variant (or neither), no change.
Source

pub fn pick_variant(&self, is_dark: bool) -> Option<&ThemeVariant>

Pick the appropriate variant for the given mode, with cross-fallback.

When is_dark is true, prefers dark and falls back to light. When is_dark is false, prefers light and falls back to dark. Returns None only if the theme has no variants at all.

Source

pub fn into_variant(self, is_dark: bool) -> Option<ThemeVariant>

Extract a variant by consuming the theme, avoiding a clone.

When is_dark is true, returns the dark variant (falling back to light). When false, returns light (falling back to dark). Returns None only if the theme has no variants at all.

Use this when you own the ThemeSpec and don’t need it afterward. For read-only inspection, use pick_variant().

§Examples
let theme = native_theme::ThemeSpec::preset("dracula").unwrap();
let variant = theme.into_variant(true).unwrap();
let resolved = variant.into_resolved().unwrap();
Source

pub fn is_empty(&self) -> bool

Returns true if the theme has no variants set.

Source

pub fn preset(name: &str) -> Result<Self>

Load a bundled theme preset by name.

Returns the preset as a fully populated ThemeSpec with both light and dark variants.

§Errors

Returns crate::Error::Unavailable if the preset name is not recognized.

§Examples
let theme = native_theme::ThemeSpec::preset("catppuccin-mocha").unwrap();
assert!(theme.light.is_some());
Source

pub fn from_toml(toml_str: &str) -> Result<Self>

Parse a TOML string into a ThemeSpec.

§TOML Format

Theme files use the following structure. All fields are Option<T> – omit any field you don’t need. Unknown fields are silently ignored. Hex colors accept #RRGGBB or #RRGGBBAA format.

name = "My Theme"

[light.defaults]
accent = "#4a90d9"
background = "#fafafa"
foreground = "#2e3436"
surface = "#ffffff"
border = "#c0c0c0"
muted = "#929292"
shadow = "#00000018"
danger = "#dc3545"
warning = "#f0ad4e"
success = "#28a745"
info = "#4a90d9"
selection = "#4a90d9"
selection_foreground = "#ffffff"
link = "#2a6cb6"
focus_ring_color = "#4a90d9"
disabled_foreground = "#c0c0c0"
radius = 6.0
radius_lg = 12.0
frame_width = 1.0
disabled_opacity = 0.5
border_opacity = 0.15
shadow_enabled = true

[light.defaults.font]
family = "sans-serif"
size = 10.0

[light.defaults.mono_font]
family = "monospace"
size = 10.0

[light.defaults.spacing]
xxs = 2.0
xs = 4.0
s = 6.0
m = 12.0
l = 18.0
xl = 24.0
xxl = 36.0

[light.button]
background = "#e8e8e8"
foreground = "#2e3436"
min_height = 32.0
padding_horizontal = 12.0
padding_vertical = 6.0

[light.tooltip]
background = "#2e3436"
foreground = "#f0f0f0"
padding_horizontal = 6.0
padding_vertical = 6.0

# [dark.*] mirrors the same structure as [light.*]
§Errors

Returns crate::Error::Format if the TOML is invalid.

§Examples
let toml = r##"
name = "My Theme"
[light.defaults]
accent = "#ff0000"
"##;
let theme = native_theme::ThemeSpec::from_toml(toml).unwrap();
assert_eq!(theme.name, "My Theme");
Source

pub fn from_toml_with_base(toml_str: &str, base: &str) -> Result<Self>

Parse custom TOML and merge onto a base preset.

This is the recommended way to create custom themes. The base preset provides geometry, spacing, and widget defaults. The custom TOML overrides colors, fonts, and any other fields.

§Errors

Returns crate::Error::Unavailable if the base preset name is not recognized, or crate::Error::Format if the custom TOML is invalid.

§Examples
let theme = native_theme::ThemeSpec::from_toml_with_base(
    r##"name = "My Theme"
[dark.defaults]
accent = "#ff6600"
background = "#1e1e1e"
foreground = "#e0e0e0""##,
    "material",
).unwrap();
assert!(theme.dark.is_some());
Source

pub fn from_file(path: impl AsRef<Path>) -> Result<Self>

Load a ThemeSpec from a TOML file.

§Errors

Returns crate::Error::Unavailable if the file cannot be read.

§Examples
let theme = native_theme::ThemeSpec::from_file("my-theme.toml").unwrap();
Source

pub fn list_presets() -> &'static [&'static str]

List all available bundled preset names.

§Examples
let names = native_theme::ThemeSpec::list_presets();
assert_eq!(names.len(), 16);
Source

pub fn list_presets_for_platform() -> Vec<&'static str>

List preset names appropriate for the current platform.

Platform-specific presets (kde-breeze, adwaita, windows-11, macos-sonoma, ios) are only included on their native platform. Community themes are always included.

§Examples
let names = native_theme::ThemeSpec::list_presets_for_platform();
// On Linux KDE: includes kde-breeze, adwaita, plus all community themes
// On Windows: includes windows-11 plus all community themes
assert!(!names.is_empty());
Source

pub fn to_toml(&self) -> Result<String>

Serialize this theme to a TOML string.

§Errors

Returns crate::Error::Format if serialization fails.

§Examples
let theme = native_theme::ThemeSpec::preset("catppuccin-mocha").unwrap();
let toml_str = theme.to_toml().unwrap();
assert!(toml_str.contains("name = \"Catppuccin Mocha\""));
Source

pub fn lint_toml(toml_str: &str) -> Result<Vec<String>>

Check a TOML string for unrecognized field names.

Parses the TOML as a generic table and walks all keys, comparing against the known fields for each section. Returns a Vec<String> of warnings for any keys that don’t match a known field. An empty vec means all keys are recognized.

This is an opt-in linting tool for theme authors. It does NOT affect from_toml() behavior (which silently ignores unknown fields via serde).

§Errors

Returns Err if the TOML string cannot be parsed at all.

§Examples
let warnings = native_theme::ThemeSpec::lint_toml(r##"
name = "Test"
[light.defaults]
backround = "#ffffff"
"##).unwrap();
assert_eq!(warnings.len(), 1);
assert!(warnings[0].contains("backround"));

Trait Implementations§

Source§

impl Clone for ThemeSpec

Source§

fn clone(&self) -> ThemeSpec

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ThemeSpec

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ThemeSpec

Source§

fn default() -> ThemeSpec

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for ThemeSpec

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for ThemeSpec

Source§

fn eq(&self, other: &ThemeSpec) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for ThemeSpec

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for ThemeSpec

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,