Skip to main content

dioxus_element_plug/components/
layout.rs

1use dioxus::prelude::*;
2
3// Layout CSS class constants
4pub const CONTAINER: &str = "el-container";
5pub const HEADER: &str = "el-header";
6pub const ASIDE: &str = "el-aside";
7pub const MAIN: &str = "el-main";
8pub const FOOTER: &str = "el-footer";
9pub const ROW: &str = "el-row";
10pub const COL: &str = "el-col";
11
12/// Container props
13#[derive(Props, Clone, PartialEq)]
14pub struct ContainerProps {
15    #[props(default)]
16    pub children: Element,
17
18    #[props(default)]
19    pub direction: Option<String>,
20
21    #[props(default)]
22    pub class: Option<String>,
23
24    #[props(default)]
25    pub style: Option<String>,
26}
27
28/// Container component for layout
29#[component]
30pub fn Container(props: ContainerProps) -> Element {
31    let mut class_names = vec![CONTAINER.to_string()];
32
33    if let Some(ref custom_class) = props.class {
34        class_names.push(custom_class.to_string());
35    }
36
37    let class_string = class_names.join(" ");
38    let style_string = props.style.as_ref().cloned().unwrap_or_default();
39
40    rsx! {
41        div {
42            class: "{class_string}",
43            style: "{style_string}",
44            {props.children}
45        }
46    }
47}
48
49/// Header props
50#[derive(Props, Clone, PartialEq)]
51pub struct HeaderProps {
52    #[props(default)]
53    pub children: Element,
54
55    #[props(default = 60)]
56    pub height: u32,
57
58    #[props(default)]
59    pub class: Option<String>,
60
61    #[props(default)]
62    pub style: Option<String>,
63}
64
65/// Header component
66#[component]
67pub fn Header(props: HeaderProps) -> Element {
68    let mut class_names = vec![HEADER.to_string()];
69
70    if let Some(ref custom_class) = props.class {
71        class_names.push(custom_class.to_string());
72    }
73
74    let class_string = class_names.join(" ");
75    let style_string = format!(
76        "height: {}px;{}",
77        props.height,
78        props.style.as_ref().cloned().unwrap_or_default()
79    );
80
81    rsx! {
82        header {
83            class: "{class_string}",
84            style: "{style_string}",
85            {props.children}
86        }
87    }
88}
89
90/// Aside props
91#[derive(Props, Clone, PartialEq)]
92pub struct AsideProps {
93    #[props(default)]
94    pub children: Element,
95
96    #[props(default = 200)]
97    pub width: u32,
98
99    #[props(default)]
100    pub class: Option<String>,
101
102    #[props(default)]
103    pub style: Option<String>,
104}
105
106/// Aside component
107#[component]
108pub fn Aside(props: AsideProps) -> Element {
109    let mut class_names = vec![ASIDE.to_string()];
110
111    if let Some(ref custom_class) = props.class {
112        class_names.push(custom_class.to_string());
113    }
114
115    let class_string = class_names.join(" ");
116    let style_string = format!(
117        "width: {}px;{}",
118        props.width,
119        props.style.as_ref().cloned().unwrap_or_default()
120    );
121
122    rsx! {
123        aside {
124            class: "{class_string}",
125            style: "{style_string}",
126            {props.children}
127        }
128    }
129}
130
131/// Main props
132#[derive(Props, Clone, PartialEq)]
133pub struct MainProps {
134    #[props(!optional)]
135    pub children: Element,
136
137    #[props(default)]
138    pub class: Option<String>,
139
140    #[props(default)]
141    pub style: Option<String>,
142}
143
144/// Main content component
145#[component]
146pub fn Main(props: MainProps) -> Element {
147    let mut class_names = vec![MAIN.to_string()];
148
149    if let Some(ref custom_class) = props.class {
150        class_names.push(custom_class.to_string());
151    }
152
153    let class_string = class_names.join(" ");
154    let style_string = props.style.as_ref().cloned().unwrap_or_default();
155
156    rsx! {
157        main {
158            class: "{class_string}",
159            style: "{style_string}",
160            {props.children}
161        }
162    }
163}
164
165/// Footer props
166#[derive(Props, Clone, PartialEq)]
167pub struct FooterProps {
168    #[props(default)]
169    pub children: Element,
170
171    #[props(default = 60)]
172    pub height: u32,
173
174    #[props(default)]
175    pub class: Option<String>,
176
177    #[props(default)]
178    pub style: Option<String>,
179}
180
181/// Footer component
182#[component]
183pub fn Footer(props: FooterProps) -> Element {
184    let mut class_names = vec![FOOTER.to_string()];
185
186    if let Some(ref custom_class) = props.class {
187        class_names.push(custom_class.to_string());
188    }
189
190    let class_string = class_names.join(" ");
191    let style_string = format!(
192        "height: {}px;{}",
193        props.height,
194        props.style.as_ref().cloned().unwrap_or_default()
195    );
196
197    rsx! {
198        footer {
199            class: "{class_string}",
200            style: "{style_string}",
201            {props.children}
202        }
203    }
204}
205
206/// Row props for grid system
207#[derive(Props, Clone, PartialEq)]
208pub struct RowProps {
209    #[props(!optional)]
210    pub children: Element,
211
212    #[props(default)]
213    pub gutter: Option<u32>,
214
215    #[props(default)]
216    pub justify: Option<String>,
217
218    #[props(default)]
219    pub align: Option<String>,
220
221    #[props(default)]
222    pub class: Option<String>,
223
224    #[props(default)]
225    pub style: Option<String>,
226}
227
228/// Row component for grid layout
229#[component]
230pub fn Row(props: RowProps) -> Element {
231    let mut class_names = vec![ROW.to_string()];
232
233    if let Some(ref justify) = props.justify {
234        class_names.push(format!("is-justify-{}", justify));
235    }
236
237    if let Some(ref align) = props.align {
238        class_names.push(format!("is-align-{}", align));
239    }
240
241    if let Some(ref custom_class) = props.class {
242        class_names.push(custom_class.to_string());
243    }
244
245    let class_string = class_names.join(" ");
246
247    let mut style_parts = vec![props.style.as_ref().cloned().unwrap_or_default()];
248
249    if let Some(gutter) = props.gutter {
250        let gutter_margin = -(gutter as i32 / 2);
251        style_parts.push(format!("margin-left: {}px; margin-right: {}px;", gutter_margin, gutter_margin));
252    }
253
254    let style_string = style_parts.join("");
255
256    rsx! {
257        div {
258            class: "{class_string}",
259            style: "{style_string}",
260            {props.children}
261        }
262    }
263}
264
265/// Col props for grid system
266#[derive(Props, Clone, PartialEq)]
267pub struct ColProps {
268    #[props(!optional)]
269    pub children: Element,
270
271    #[props(default)]
272    pub span: Option<u32>,
273
274    #[props(default)]
275    pub offset: Option<u32>,
276
277    #[props(default)]
278    pub push: Option<u32>,
279
280    #[props(default)]
281    pub pull: Option<u32>,
282
283    #[props(default)]
284    pub class: Option<String>,
285
286    #[props(default)]
287    pub style: Option<String>,
288}
289
290/// Column component for grid layout
291#[component]
292pub fn Col(props: ColProps) -> Element {
293    let mut class_names = vec![COL.to_string()];
294
295    if let Some(span) = props.span {
296        class_names.push(format!("el-col-{}", span));
297    }
298
299    if let Some(offset) = props.offset {
300        class_names.push(format!("el-col-offset-{}", offset));
301    }
302
303    if let Some(push) = props.push {
304        class_names.push(format!("el-col-push-{}", push));
305    }
306
307    if let Some(pull) = props.pull {
308        class_names.push(format!("el-col-pull-{}", pull));
309    }
310
311    if let Some(ref custom_class) = props.class {
312        class_names.push(custom_class.to_string());
313    }
314
315    let class_string = class_names.join(" ");
316    let style_string = props.style.as_ref().cloned().unwrap_or_default();
317
318    rsx! {
319        div {
320            class: "{class_string}",
321            style: "{style_string}",
322            {props.children}
323        }
324    }
325}