rustyle_css/components/
modal.rs

1//! Modal component styles
2//!
3//! Provides type-safe modal/dialog styling with variants and sizes.
4
5use super::{ComponentStyle, Size, Variant};
6use crate::css::{Color, Radius, Spacing};
7use crate::tokens::{BorderTokens, ColorTokens, SpacingTokens};
8
9/// Modal style configuration
10#[derive(Clone, Debug)]
11pub struct ModalStyle {
12    pub variant: Variant,
13    pub size: Size,
14    pub tokens: Option<ModalTokens>,
15}
16
17/// Modal design tokens
18#[derive(Clone, Debug)]
19pub struct ModalTokens {
20    pub colors: ColorTokens,
21    pub spacing: SpacingTokens,
22    pub borders: BorderTokens,
23}
24
25impl ModalStyle {
26    /// Create a new modal style
27    pub fn new(variant: Variant, size: Size) -> Self {
28        Self {
29            variant,
30            size,
31            tokens: None,
32        }
33    }
34
35    /// Set custom tokens
36    pub fn tokens(mut self, tokens: ModalTokens) -> Self {
37        self.tokens = Some(tokens);
38        self
39    }
40
41    fn background_color(&self) -> Color {
42        let default_colors = ColorTokens::default();
43        let colors = self
44            .tokens
45            .as_ref()
46            .map(|t| &t.colors)
47            .unwrap_or(&default_colors);
48
49        colors.background.elevated.clone()
50    }
51
52    fn border_color(&self) -> Color {
53        let default_colors = ColorTokens::default();
54        let colors = self
55            .tokens
56            .as_ref()
57            .map(|t| &t.colors)
58            .unwrap_or(&default_colors);
59
60        colors.secondary.c300.clone()
61    }
62
63    fn padding(&self) -> Spacing {
64        let default_spacing = SpacingTokens::default();
65        let spacing = self
66            .tokens
67            .as_ref()
68            .map(|t| &t.spacing)
69            .unwrap_or(&default_spacing);
70
71        match &self.size {
72            Size::Small => Spacing::all(spacing.md.clone()),
73            Size::Medium => Spacing::all(spacing.lg.clone()),
74            Size::Large => Spacing::all(spacing.xl.clone()),
75            Size::ExtraLarge => Spacing::all(spacing.xl2.clone()),
76        }
77    }
78
79    fn border_radius(&self) -> Radius {
80        let default_borders = BorderTokens::default();
81        let borders = self
82            .tokens
83            .as_ref()
84            .map(|t| &t.borders)
85            .unwrap_or(&default_borders);
86
87        match &self.size {
88            Size::Small => Radius::all(borders.radius.base.clone()),
89            Size::Medium => Radius::all(borders.radius.lg.clone()),
90            Size::Large => Radius::all(borders.radius.xl.clone()),
91            Size::ExtraLarge => Radius::all(borders.radius.xl.clone()),
92        }
93    }
94
95    fn max_width(&self) -> String {
96        match &self.size {
97            Size::Small => "400px".to_string(),
98            Size::Medium => "600px".to_string(),
99            Size::Large => "800px".to_string(),
100            Size::ExtraLarge => "1200px".to_string(),
101        }
102    }
103}
104
105impl ComponentStyle for ModalStyle {
106    fn to_css(&self) -> String {
107        let mut css = String::new();
108
109        css.push_str(&format!(
110            "background-color: {}; ",
111            self.background_color().to_css()
112        ));
113        css.push_str(&format!(
114            "border: 1px solid {}; ",
115            self.border_color().to_css()
116        ));
117        css.push_str(&format!(
118            "border-radius: {}; ",
119            self.border_radius().to_css()
120        ));
121        css.push_str(&format!("padding: {}; ", self.padding().to_css()));
122        css.push_str(&format!("max-width: {}; ", self.max_width()));
123        css.push_str("width: 100%; ");
124        css.push_str("position: fixed; ");
125        css.push_str("top: 50%; ");
126        css.push_str("left: 50%; ");
127        css.push_str("transform: translate(-50%, -50%); ");
128        css.push_str("z-index: 1000; ");
129        css.push_str("box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); ");
130
131        css
132    }
133
134    fn class_name(&self) -> &str {
135        "rustyle-modal"
136    }
137}
138
139impl Default for ModalStyle {
140    fn default() -> Self {
141        Self::new(Variant::Primary, Size::Medium)
142    }
143}