use michiu_ui::prelude::*;
use std::borrow::Cow;
#[derive(Debug, Clone, PartialEq)]
pub struct Theme {
pub is_dark: bool,
pub primary_hsl: (f32, f32, f32),
pub background_hsl: (f32, f32, f32),
pub primary: Color,
pub primary_hover: Color,
pub secondary: Color,
pub secondary_hover: Color,
pub background: Color,
pub background_hover: Color,
pub surface: Color,
pub border: Color,
pub border_hover: Color,
pub text: Color,
pub text_muted: Color,
pub font_family: Cow<'static, str>,
pub font_size_sm: f32,
pub font_size_base: f32,
pub font_size_lg: f32,
}
impl Theme {
pub fn from_hsl(
is_dark: bool,
primary_hsl: (f32, f32, f32),
background_hsl: (f32, f32, f32),
) -> Self {
let (hp, sp, lp) = primary_hsl;
let (hb, sb, lb) = background_hsl;
let primary = hsl(hp, sp, lp);
let primary_hover = if is_dark {
hsl(hp, sp, (lp + 8.0).min(100.0)) } else {
hsl(hp, sp, (lp - 8.0).max(0.0)) };
let hs = (hp + 30.0) % 360.0;
let ss = (sp * 0.65).clamp(0.0, 100.0);
let ls = if is_dark {
(lp * 0.9).clamp(40.0, 70.0) } else {
(lp * 1.1).clamp(30.0, 60.0) };
let secondary = hsl(hs, ss, ls);
let secondary_hover = if is_dark {
hsl(hs, ss, (ls + 8.0).min(100.0))
} else {
hsl(hs, ss, (ls - 8.0).max(0.0))
};
let background = hsl(hb, sb, lb);
let background_hover = if is_dark {
hsl(hb, sb, (lb + 4.0).min(100.0)) } else {
hsl(hb, sb, (lb - 5.0).max(0.0)) };
let surface = if is_dark {
hsl(hb, sb * 0.9, (lb + 5.0).min(100.0))
} else {
hsl(hb, sb * 0.5, (lb + 1.0).min(98.0)) };
let border = if is_dark {
hsl(hb, sb * 0.8, (lb + 15.0).min(100.0)) } else {
hsl(hb, sb * 0.8, (lb - 16.0).max(0.0)) };
let border_hover = if is_dark {
hsl(hb, sb * 0.8, (lb + 25.0).min(100.0)) } else {
hsl(hb, sb * 0.8, (lb - 26.0).max(0.0)) };
let text = if is_dark {
hsl(hb, sb * 0.2, 95.0) } else {
hsl(hb, sb * 0.3, 12.0) };
let text_muted = if is_dark {
hsl(hb, sb * 0.25, 65.0) } else {
hsl(hb, sb * 0.25, 50.0) };
let font_family = "Segoe UI".into();
let font_size_sm = 12.0;
let font_size_base = 14.0;
let font_size_lg = 18.0;
Self {
is_dark,
primary_hsl,
background_hsl,
primary,
primary_hover,
secondary,
secondary_hover,
background,
background_hover,
surface,
border,
border_hover,
text,
text_muted,
font_family,
font_size_sm,
font_size_base,
font_size_lg,
}
}
pub fn dark() -> Self {
Self::from_hsl(true, (318.0, 56.0, 59.0), (224.0, 15.0, 10.0))
}
pub fn light() -> Self {
Self::from_hsl(false, (318.0, 56.0, 59.0), (220.0, 10.0, 92.0))
}
#[expect(unused)]
pub fn with_primary_hsl(self, h: f32, s: f32, l: f32) -> Self {
Self::from_hsl(self.is_dark, (h, s, l), self.background_hsl)
}
#[expect(unused)]
pub fn with_background_hsl(self, h: f32, s: f32, l: f32) -> Self {
Self::from_hsl(self.is_dark, self.primary_hsl, (h, s, l))
}
}