Skip to main content

use_theme/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4/// Theme display mode.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
6pub enum ThemeMode {
7    Light,
8    Dark,
9    System,
10}
11
12impl ThemeMode {
13    pub fn as_str(self) -> &'static str {
14        match self {
15            Self::Light => "light",
16            Self::Dark => "dark",
17            Self::System => "system",
18        }
19    }
20
21    pub fn is_explicit(self) -> bool {
22        !matches!(self, Self::System)
23    }
24}
25
26/// A theme name.
27#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
28pub struct ThemeName(String);
29
30impl ThemeName {
31    pub fn new(value: impl Into<String>) -> Self {
32        Self(value.into())
33    }
34
35    pub fn as_str(&self) -> &str {
36        &self.0
37    }
38}
39
40impl AsRef<str> for ThemeName {
41    fn as_ref(&self) -> &str {
42        self.as_str()
43    }
44}
45
46/// A named theme variant.
47#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
48pub struct ThemeVariant(String);
49
50impl ThemeVariant {
51    pub fn new(value: impl Into<String>) -> Self {
52        Self(value.into())
53    }
54
55    pub fn as_str(&self) -> &str {
56        &self.0
57    }
58}
59
60impl AsRef<str> for ThemeVariant {
61    fn as_ref(&self) -> &str {
62        self.as_str()
63    }
64}
65
66/// Semantic roles commonly used by themes.
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
68pub enum SemanticThemeRole {
69    Background,
70    Foreground,
71    Primary,
72    Secondary,
73    Accent,
74    Muted,
75    Success,
76    Warning,
77    Danger,
78    Info,
79}
80
81impl SemanticThemeRole {
82    pub fn as_str(self) -> &'static str {
83        match self {
84            Self::Background => "background",
85            Self::Foreground => "foreground",
86            Self::Primary => "primary",
87            Self::Secondary => "secondary",
88            Self::Accent => "accent",
89            Self::Muted => "muted",
90            Self::Success => "success",
91            Self::Warning => "warning",
92            Self::Danger => "danger",
93            Self::Info => "info",
94        }
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::{SemanticThemeRole, ThemeMode, ThemeName, ThemeVariant};
101
102    #[test]
103    fn creates_theme_identity_values() {
104        let name = ThemeName::new("Acme");
105        let variant = ThemeVariant::new("high-contrast");
106
107        assert_eq!(name.as_str(), "Acme");
108        assert_eq!(variant.as_str(), "high-contrast");
109    }
110
111    #[test]
112    fn exposes_theme_mode_and_role_labels() {
113        assert_eq!(ThemeMode::Dark.as_str(), "dark");
114        assert!(ThemeMode::Light.is_explicit());
115        assert!(!ThemeMode::System.is_explicit());
116        assert_eq!(SemanticThemeRole::Danger.as_str(), "danger");
117    }
118}