rustyle_css/components/
card.rs

1//! Card component styles
2//!
3//! Provides type-safe card styling with elevation system integration.
4
5use super::{ComponentStyle, Size};
6use crate::css::{Color, Radius, Spacing};
7use crate::tokens::{BorderTokens, ColorTokens, ShadowTokens, SpacingTokens};
8
9/// Card style configuration
10#[derive(Clone, Debug)]
11pub struct CardStyle {
12    pub size: Size,
13    pub elevation: Option<String>,
14    pub tokens: Option<CardTokens>,
15}
16
17/// Card design tokens
18#[derive(Clone, Debug)]
19pub struct CardTokens {
20    pub colors: ColorTokens,
21    pub spacing: SpacingTokens,
22    pub shadows: ShadowTokens,
23    pub borders: BorderTokens,
24}
25
26impl CardStyle {
27    /// Create a new card style
28    pub fn new(size: Size) -> Self {
29        Self {
30            size,
31            elevation: None,
32            tokens: None,
33        }
34    }
35
36    /// Set elevation level
37    pub fn elevation(mut self, level: &str) -> Self {
38        self.elevation = Some(level.to_string());
39        self
40    }
41
42    /// Set custom tokens
43    pub fn tokens(mut self, tokens: CardTokens) -> Self {
44        self.tokens = Some(tokens);
45        self
46    }
47
48    /// Get background color
49    fn background_color(&self) -> Color {
50        let default_colors = ColorTokens::default();
51        let colors = self
52            .tokens
53            .as_ref()
54            .map(|t| &t.colors)
55            .unwrap_or(&default_colors);
56
57        colors.background.base.clone()
58    }
59
60    /// Get padding based on size
61    fn padding(&self) -> Spacing {
62        let default_spacing = SpacingTokens::default();
63        let spacing = self
64            .tokens
65            .as_ref()
66            .map(|t| &t.spacing)
67            .unwrap_or(&default_spacing);
68
69        match &self.size {
70            Size::Small => Spacing::all(spacing.sm.clone()),
71            Size::Medium => Spacing::all(spacing.md.clone()),
72            Size::Large => Spacing::all(spacing.lg.clone()),
73            Size::ExtraLarge => Spacing::all(spacing.xl.clone()),
74        }
75    }
76
77    /// Get border radius
78    fn border_radius(&self) -> Radius {
79        let default_borders = BorderTokens::default();
80        let borders = self
81            .tokens
82            .as_ref()
83            .map(|t| &t.borders)
84            .unwrap_or(&default_borders);
85
86        Radius::all(borders.radius.md.clone())
87    }
88
89    /// Get box shadow based on elevation
90    fn box_shadow(&self) -> String {
91        let default_shadows = ShadowTokens::default();
92        let shadows = self
93            .tokens
94            .as_ref()
95            .map(|t| &t.shadows)
96            .unwrap_or(&default_shadows);
97
98        let level = self.elevation.as_deref().unwrap_or("md");
99        shadows.get(level).to_css()
100    }
101}
102
103impl ComponentStyle for CardStyle {
104    fn to_css(&self) -> String {
105        let mut css = String::new();
106
107        css.push_str(&format!(
108            "background-color: {}; ",
109            self.background_color().to_css()
110        ));
111        css.push_str(&format!("padding: {}; ", self.padding().to_css()));
112        css.push_str(&format!(
113            "border-radius: {}; ",
114            self.border_radius().to_css()
115        ));
116        css.push_str(&format!("box-shadow: {}; ", self.box_shadow()));
117        css.push_str("border: 1px solid rgba(0, 0, 0, 0.1); ");
118
119        css
120    }
121
122    fn class_name(&self) -> &str {
123        "rustyle-card"
124    }
125}
126
127impl Default for CardStyle {
128    fn default() -> Self {
129        Self::new(Size::Medium)
130    }
131}