Skip to main content

dioxus_bulma/components/
panel.rs

1use crate::theme::BulmaColor;
2use crate::utils::build_class;
3use dioxus::prelude::*;
4
5#[derive(Props, Clone, PartialEq)]
6pub struct PanelProps {
7    #[props(default)]
8    pub color: Option<BulmaColor>,
9    #[props(default)]
10    pub id: Option<String>,
11    #[props(default)]
12    pub class: Option<String>,
13    #[props(default)]
14    pub style: Option<String>,
15    pub children: Element,
16}
17
18#[component]
19pub fn Panel(props: PanelProps) -> Element {
20    let base_classes = vec!["panel"];
21    let optional_classes = vec![
22        props.color.map(|c| format!("is-{}", c.as_str())),
23        props.class.clone(),
24    ];
25    
26    let final_class = build_class(&base_classes, &optional_classes);
27    let panel_style = props.style.as_deref().unwrap_or("");
28
29    rsx! {
30        nav {
31            class: "{final_class}",
32            style: "{panel_style}",
33            id: props.id.clone(),
34            {props.children}
35        }
36    }
37}
38
39#[derive(Props, Clone, PartialEq)]
40pub struct PanelHeadingProps {
41    #[props(default)]
42    pub id: Option<String>,
43    #[props(default)]
44    pub class: Option<String>,
45    #[props(default)]
46    pub style: Option<String>,
47    pub children: Element,
48}
49
50#[component]
51pub fn PanelHeading(props: PanelHeadingProps) -> Element {
52    let base_classes = vec!["panel-heading"];
53    let optional_classes = vec![props.class.clone()];
54    let final_class = build_class(&base_classes, &optional_classes);
55    let heading_style = props.style.as_deref().unwrap_or("");
56
57    rsx! {
58        p {
59            class: "{final_class}",
60            style: "{heading_style}",
61            id: props.id.clone(),
62            {props.children}
63        }
64    }
65}
66
67#[derive(Props, Clone, PartialEq)]
68pub struct PanelTabsProps {
69    #[props(default)]
70    pub id: Option<String>,
71    #[props(default)]
72    pub class: Option<String>,
73    #[props(default)]
74    pub style: Option<String>,
75    pub children: Element,
76}
77
78#[component]
79pub fn PanelTabs(props: PanelTabsProps) -> Element {
80    let base_classes = vec!["panel-tabs"];
81    let optional_classes = vec![props.class.clone()];
82    let final_class = build_class(&base_classes, &optional_classes);
83    let tabs_style = props.style.as_deref().unwrap_or("");
84
85    rsx! {
86        p {
87            class: "{final_class}",
88            style: "{tabs_style}",
89            id: props.id.clone(),
90            {props.children}
91        }
92    }
93}
94
95#[derive(Props, Clone, PartialEq)]
96pub struct PanelBlockProps {
97    #[props(default)]
98    pub active: Option<bool>,
99    #[props(default)]
100    pub href: Option<String>,
101    #[props(default)]
102    pub onclick: Option<EventHandler<MouseEvent>>,
103    /// If present, use router navigation instead of href
104    #[cfg(feature = "router")]
105    #[props(default, into)]
106    pub to: crate::router_helpers::MaybeNav,
107    #[props(default)]
108    pub id: Option<String>,
109    #[props(default)]
110    pub class: Option<String>,
111    #[props(default)]
112    pub style: Option<String>,
113    pub children: Element,
114}
115
116#[component]
117pub fn PanelBlock(props: PanelBlockProps) -> Element {
118    let active = props.active.unwrap_or(false);
119    
120    let base_classes = vec!["panel-block"];
121    let optional_classes = vec![
122        if active { Some("is-active".to_string()) } else { None },
123        props.class.clone(),
124    ];
125    
126    let final_class = build_class(&base_classes, &optional_classes);
127    let block_style = props.style.as_deref().unwrap_or("");
128
129    #[cfg(feature = "router")]
130    if let Some(nav_target) = props.to.0 {
131        return rsx! {
132            Link {
133                to: nav_target,
134                class: "{final_class}",
135                style: "{block_style}",
136                id: props.id.clone(),
137                onclick: move |evt| {
138                    if let Some(handler) = &props.onclick {
139                        handler.call(evt);
140                    }
141                },
142                {props.children}
143            }
144        };
145    }
146
147    rsx! {
148        if let Some(href) = props.href {
149            a {
150                class: "{final_class}",
151                style: "{block_style}",
152                id: props.id.clone(),
153                href: "{href}",
154                onclick: move |evt| {
155                    if let Some(handler) = &props.onclick {
156                        handler.call(evt);
157                    }
158                },
159                {props.children}
160            }
161        } else {
162            div {
163                class: "{final_class}",
164                style: "{block_style}",
165                id: props.id.clone(),
166                onclick: move |evt| {
167                    if let Some(handler) = &props.onclick {
168                        handler.call(evt);
169                    }
170                },
171                {props.children}
172            }
173        }
174    }
175}
176
177#[derive(Props, Clone, PartialEq)]
178pub struct PanelIconProps {
179    #[props(default)]
180    pub id: Option<String>,
181    #[props(default)]
182    pub class: Option<String>,
183    #[props(default)]
184    pub style: Option<String>,
185    pub children: Element,
186}
187
188#[component]
189pub fn PanelIcon(props: PanelIconProps) -> Element {
190    let base_classes = vec!["panel-icon"];
191    let optional_classes = vec![props.class.clone()];
192    let final_class = build_class(&base_classes, &optional_classes);
193    let icon_style = props.style.as_deref().unwrap_or("");
194
195    rsx! {
196        span {
197            class: "{final_class}",
198            style: "{icon_style}",
199            id: props.id.clone(),
200            {props.children}
201        }
202    }
203}