material-ui-rs 0.4.2

A Material3 inspired theme for `iced`
Documentation
use iced_widget::checkbox::{Catalog, Status, Style, StyleFn};
use iced_widget::core::{Background, Border, Color, border};

use crate::Theme;
use crate::tokens;
use crate::utils::{HOVERED_LAYER_OPACITY, state_layer};

impl Catalog for Theme {
    type Class<'a> = StyleFn<'a, Self>;

    fn default<'a>() -> Self::Class<'a> {
        Box::new(default)
    }

    fn style(&self, class: &Self::Class<'_>, status: Status) -> Style {
        class(self, status)
    }
}

pub fn styled(
    background_color: Color,
    background_unchecked: Option<Color>,
    icon_color: Color,
    border_color: Color,
    text_color: Option<Color>,
    is_checked: bool,
) -> Style {
    Style {
        background: Background::Color(if is_checked {
            background_color
        } else {
            background_unchecked.unwrap_or(Color::TRANSPARENT)
        }),
        icon_color,
        border: if is_checked {
            border::rounded(tokens::component::checkbox::CONTAINER_SHAPE)
        } else {
            Border {
                color: border_color,
                width: tokens::component::checkbox::UNSELECTED_OUTLINE_WIDTH,
                radius: tokens::component::checkbox::CONTAINER_SHAPE.into(),
            }
        },
        text_color,
    }
}

pub fn default(theme: &Theme, status: Status) -> Style {
    let surface = theme.colors().surface;
    let primary = theme.colors().primary;

    match status {
        Status::Active { is_checked } => styled(
            primary.color,
            None,
            primary.text,
            surface.text_variant,
            Some(surface.text),
            is_checked,
        ),
        Status::Hovered { is_checked } => styled(
            primary.color,
            Some(state_layer(surface.text, HOVERED_LAYER_OPACITY)),
            primary.text,
            surface.text,
            Some(surface.text),
            is_checked,
        ),
        Status::Disabled { is_checked } => styled(
            state_layer(
                surface.text,
                tokens::component::checkbox::SELECTED_DISABLED_CONTAINER_OPACITY,
            ),
            None,
            surface.color,
            state_layer(
                surface.text,
                tokens::component::checkbox::UNSELECTED_DISABLED_CONTAINER_OPACITY,
            ),
            Some(state_layer(
                surface.text,
                tokens::state::DISABLED_LABEL_TEXT_OPACITY,
            )),
            is_checked,
        ),
    }
}

pub fn error(theme: &Theme, status: Status) -> Style {
    let surface = theme.colors().surface;
    let error = theme.colors().error;

    match status {
        Status::Active { is_checked } => styled(
            error.color,
            None,
            error.text,
            error.color,
            Some(error.color),
            is_checked,
        ),
        Status::Hovered { is_checked } => styled(
            error.color,
            Some(state_layer(error.color, HOVERED_LAYER_OPACITY)),
            error.text,
            error.color,
            Some(error.color),
            is_checked,
        ),
        Status::Disabled { is_checked } => styled(
            state_layer(
                surface.text,
                tokens::component::checkbox::SELECTED_DISABLED_CONTAINER_OPACITY,
            ),
            None,
            surface.color,
            state_layer(
                surface.text,
                tokens::component::checkbox::UNSELECTED_DISABLED_CONTAINER_OPACITY,
            ),
            Some(state_layer(
                surface.text,
                tokens::state::DISABLED_LABEL_TEXT_OPACITY,
            )),
            is_checked,
        ),
    }
}

#[cfg(test)]
#[path = "../../../tests/design/style/checkbox.rs"]
mod tests;