material-ui-rs 0.5.3

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

use crate::Theme;
use crate::tokens;
use crate::utils::shadow_from_level;

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

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

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

pub fn transparent(_theme: &Theme) -> Style {
    Style {
        border: border::rounded(tokens::shape::CORNER_EXTRA_SMALL),
        ..Style::default()
    }
}

pub fn primary(theme: &Theme) -> Style {
    let primary = theme.colors().primary;

    Style {
        background: Some(Background::Color(primary.color)),
        text_color: Some(primary.text),
        border: border::rounded(tokens::shape::CORNER_EXTRA_SMALL),
        ..Style::default()
    }
}

pub fn primary_container(theme: &Theme) -> Style {
    let primary = theme.colors().primary;

    Style {
        background: Some(Background::Color(primary.container)),
        text_color: Some(primary.container_text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

pub fn secondary(theme: &Theme) -> Style {
    let secondary = theme.colors().secondary;

    Style {
        background: Some(Background::Color(secondary.color)),
        text_color: Some(secondary.text),
        border: border::rounded(tokens::shape::CORNER_EXTRA_SMALL),
        ..Style::default()
    }
}

pub fn secondary_container(theme: &Theme) -> Style {
    let secondary = theme.colors().secondary;

    Style {
        background: Some(Background::Color(secondary.container)),
        text_color: Some(secondary.container_text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

pub fn tertiary(theme: &Theme) -> Style {
    let tertiary = theme.colors().tertiary;

    Style {
        background: Some(Background::Color(tertiary.color)),
        text_color: Some(tertiary.text),
        border: border::rounded(tokens::shape::CORNER_EXTRA_SMALL),
        ..Style::default()
    }
}

pub fn tertiary_container(theme: &Theme) -> Style {
    let tertiary = theme.colors().tertiary;

    Style {
        background: Some(Background::Color(tertiary.container)),
        text_color: Some(tertiary.container_text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

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

    Style {
        background: Some(Background::Color(error.color)),
        text_color: Some(error.text),
        border: border::rounded(tokens::shape::CORNER_EXTRA_SMALL),
        ..Style::default()
    }
}

pub fn error_container(theme: &Theme) -> Style {
    let error = theme.colors().error;

    Style {
        background: Some(Background::Color(error.container)),
        text_color: Some(error.container_text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

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

    Style {
        background: Some(Background::Color(surface.color)),
        text_color: Some(surface.text),
        border: border::rounded(tokens::shape::CORNER_EXTRA_SMALL),
        ..Style::default()
    }
}

pub fn surface_container_lowest(theme: &Theme) -> Style {
    let surface = theme.colors().surface;

    Style {
        background: Some(Background::Color(surface.container.lowest)),
        text_color: Some(surface.text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

pub fn surface_container_low(theme: &Theme) -> Style {
    let surface = theme.colors().surface;

    Style {
        background: Some(Background::Color(surface.container.low)),
        text_color: Some(surface.text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

pub fn surface_container(theme: &Theme) -> Style {
    let surface = theme.colors().surface;

    Style {
        background: Some(Background::Color(surface.container.base)),
        text_color: Some(surface.text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

pub fn surface_container_high(theme: &Theme) -> Style {
    let surface = theme.colors().surface;

    Style {
        background: Some(Background::Color(surface.container.high)),
        text_color: Some(surface.text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

pub fn surface_container_highest(theme: &Theme) -> Style {
    let surface = theme.colors().surface;

    Style {
        background: Some(Background::Color(surface.container.highest)),
        text_color: Some(surface.text),
        border: border::rounded(tokens::shape::CORNER_SMALL),
        ..Style::default()
    }
}

pub fn inverse_surface(theme: &Theme) -> Style {
    let inverse = theme.colors().inverse;

    Style {
        background: Some(Background::Color(inverse.inverse_surface)),
        text_color: Some(inverse.inverse_surface_text),
        border: border::rounded(tokens::shape::CORNER_EXTRA_SMALL),
        ..Style::default()
    }
}

pub fn outlined(theme: &Theme) -> Style {
    let base = transparent(theme);

    Style {
        border: Border {
            color: theme.colors().outline.color,
            width: tokens::component::button::OUTLINED_OUTLINE_WIDTH,
            ..base.border
        },
        ..base
    }
}

pub fn elevated_card(theme: &Theme) -> Style {
    let colors = theme.colors();

    Style {
        background: Some(Background::Color(colors.surface.container.low)),
        text_color: Some(colors.surface.text),
        border: border::rounded(tokens::component::card::CONTAINER_SHAPE),
        shadow: shadow_from_level(
            tokens::component::card::ELEVATED_ELEVATION.active,
            colors.shadow,
        ),
        ..Style::default()
    }
}

pub fn filled_card(theme: &Theme) -> Style {
    let colors = theme.colors();

    Style {
        background: Some(Background::Color(colors.surface.container.highest)),
        text_color: Some(colors.surface.text),
        border: border::rounded(tokens::component::card::CONTAINER_SHAPE),
        shadow: shadow_from_level(
            tokens::component::card::FILLED_ELEVATION.active,
            colors.shadow,
        ),
        ..Style::default()
    }
}

pub fn outlined_card(theme: &Theme) -> Style {
    let colors = theme.colors();

    Style {
        background: Some(Background::Color(colors.surface.color)),
        text_color: Some(colors.surface.text),
        border: Border {
            color: colors.outline.variant,
            width: tokens::component::card::OUTLINED_OUTLINE_WIDTH,
            radius: tokens::component::card::CONTAINER_SHAPE.into(),
        },
        shadow: shadow_from_level(
            tokens::component::card::OUTLINED_ELEVATION.active,
            colors.shadow,
        ),
        ..Style::default()
    }
}

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