use floem::{
peniko::Color,
style::{CursorStyle, Style, StyleValue},
style_class,
views::{PlaceholderTextClass, RadioButtonClass, RadioButtonDotClass},
};
use crate::{theme::Theme, BORDER_RADIUS};
style_class!(pub Button);
style_class!(pub Label);
style_class!(pub TextInput);
style_class!(pub ToggleButton);
style_class!(pub RadioButton);
style_class!(pub BadgeOne);
style_class!(pub BadgeTwo);
style_class!(pub BadgeThree);
style_class!(pub BadgeFour);
style_class!(pub BadgeFive);
fn parse_color(color: &str) -> Color {
#[allow(clippy::expect_fun_call)]
Color::parse(color).expect(format!("failed to parse {color}").as_str())
}
pub fn construct_theme(theme: Theme) -> Style {
Style::new()
.class(Button, button(theme))
.class(Label, label(theme))
.class(TextInput, text_input(theme))
.class(ToggleButton, toggle_button(theme))
.class(RadioButton, radio_button(theme))
.class(
BadgeOne,
badge(parse_color(theme.base00), parse_color(theme.base0a)),
)
.class(
BadgeTwo,
badge(parse_color(theme.base00), parse_color(theme.base0b)),
)
.class(
BadgeThree,
badge(parse_color(theme.base00), parse_color(theme.base0c)),
)
.class(
BadgeFour,
badge(parse_color(theme.base00), parse_color(theme.base0d)),
)
.class(BadgeFive, |s| {
let badge_style =
badge(parse_color(theme.base03), parse_color(theme.base00))(s.clone());
s.apply(badge_style)
.border(0.5)
.border_color(parse_color(theme.base03))
})
}
fn button(theme: Theme) -> impl FnOnce(Style) -> Style {
|s| {
s.border_radius(BORDER_RADIUS)
.border(1.0)
.border_color(parse_color(theme.base03))
.background(parse_color(theme.base00))
.color(parse_color(theme.base05))
.hover(|s| {
s.background(parse_color(theme.base01))
.color(parse_color(theme.base05))
})
.active(|s| {
s.background(parse_color(theme.base0a))
.color(parse_color(theme.base00))
})
.focus(|s| {
s.background(parse_color(theme.base01))
.color(parse_color(theme.base05))
.hover(|s| s.background(parse_color(theme.base00)))
.border_color(parse_color(theme.base03))
})
.disabled(|s| s.background(parse_color(theme.base01).multiply_alpha(0.6)))
}
}
fn label(theme: Theme) -> impl FnOnce(Style) -> Style {
|s| s.color(parse_color(theme.base05))
}
fn text_input(theme: Theme) -> impl FnOnce(Style) -> Style {
|s| {
s.color(parse_color(theme.base05))
.border_radius(BORDER_RADIUS)
.border_color(parse_color(theme.base03))
.background(parse_color(theme.base00))
.hover(|s| s.background(parse_color(theme.base00)))
.focus(|s| {
s.hover(|s| s.background(parse_color(theme.base00)))
.border_color(parse_color(theme.base0a))
})
.cursor_color(StyleValue::Val(parse_color(theme.base05).into()))
.cursor(CursorStyle::Text)
.disabled(|s| {
s.color(parse_color(theme.base05).multiply_alpha(0.6))
.background(parse_color(theme.base03).multiply_alpha(0.6))
})
.class(PlaceholderTextClass, |s| s.color(parse_color(theme.base03)))
}
}
fn toggle_button(theme: Theme) -> impl FnOnce(Style) -> Style {
|s| {
{
s.border_radius(BORDER_RADIUS)
.background(parse_color(theme.base00))
.color(parse_color(theme.base05))
.border_color(parse_color(theme.base03))
.hover(|s| s.background(parse_color(theme.base00)))
.focus(|s| {
s.hover(|s| s.background(parse_color(theme.base00)))
.border_color(parse_color(theme.base0a))
})
.disabled(|s| {
s.color(parse_color(theme.base05).multiply_alpha(0.6))
.background(parse_color(theme.base03).multiply_alpha(0.6))
})
.active(|s| s.background(parse_color(theme.base02)))
}
}
}
fn radio_button(theme: Theme) -> impl FnOnce(Style) -> Style {
|s| {
s.class(RadioButtonClass, |s| {
s.background(parse_color(theme.base00))
.border_color(parse_color(theme.base03))
.hover(|s| s.background(parse_color(theme.base00)))
.focus(|s| {
s.hover(|s| s.background(parse_color(theme.base00)))
.border_color(parse_color(theme.base0a))
})
.disabled(|s| {
s.color(parse_color(theme.base05).multiply_alpha(0.6))
.background(parse_color(theme.base03).multiply_alpha(0.6))
})
.active(|s| s.background(parse_color(theme.base02)))
})
.class(RadioButtonDotClass, |s| {
s.background(parse_color(theme.base0a))
})
}
}
fn badge(text_color: Color, badge_color: Color) -> impl FnOnce(Style) -> Style {
move |s| {
s.border_radius(BORDER_RADIUS)
.color(text_color)
.background(badge_color)
.height(17)
.width(75)
.padding_top(2)
.padding_left(5)
}
}