use core::fmt::{self, Debug};
use waterui::accessibility::AccessibilityRole;
use waterui::widget::{Card as WaterCard, CardStyle};
use waterui::{AnyView, Environment, Str, View, ViewExt as _};
#[derive(Clone)]
pub struct MaterialCard<Content> {
content: Content,
style: CardStyle,
accessibility_label: Option<Str>,
}
impl<Content> Debug for MaterialCard<Content> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MaterialCard")
.field("style", &self.style)
.field("accessibility_label", &self.accessibility_label)
.finish_non_exhaustive()
}
}
impl<Content> MaterialCard<Content> {
#[must_use]
pub const fn new(content: Content) -> Self {
Self {
content,
style: CardStyle::Filled,
accessibility_label: None,
}
}
#[must_use]
pub const fn elevated(mut self) -> Self {
self.style = CardStyle::Elevated;
self
}
#[must_use]
pub const fn filled(mut self) -> Self {
self.style = CardStyle::Filled;
self
}
#[must_use]
pub const fn outlined(mut self) -> Self {
self.style = CardStyle::Outlined;
self
}
#[must_use]
pub fn label(mut self, label: impl Into<Str>) -> Self {
self.accessibility_label = Some(label.into());
self
}
}
impl<Content> View for MaterialCard<Content>
where
Content: View,
{
fn body(self, _env: &Environment) -> impl View {
let card = WaterCard::new(self.content)
.style(self.style)
.a11y_role(AccessibilityRole::Group);
match self.accessibility_label {
Some(label) => AnyView::new(card.a11y_label(label)),
None => AnyView::new(card),
}
}
}
#[must_use]
pub const fn material_card<Content>(content: Content) -> MaterialCard<Content> {
MaterialCard::new(content)
}
#[cfg(test)]
mod tests {
use crate::MaterialTheme;
use waterui::widget::CardStyle;
#[test]
fn material_card_tokens_match_compose_card_tokens() {
let theme = crate::layout::card::theme(&MaterialTheme::new().colors());
assert_eq!(theme.default_style, CardStyle::Filled);
assert_eq!(theme.elevated.corner_radius, 12.0);
assert_eq!(theme.filled.corner_radius, 12.0);
assert_eq!(theme.outlined.corner_radius, 12.0);
assert_eq!(theme.outlined.outline_width, 1.0);
assert_eq!(theme.elevated.shadow_radius, 1.5);
assert_eq!(theme.elevated.shadow_offset_y, 0.5);
assert_eq!(theme.filled.shadow_radius, 0.0);
assert_eq!(theme.outlined.shadow_radius, 0.0);
}
}