1use dioxus::prelude::*;
2use dioxus_router::navigation::NavigationTarget;
3use dioxus_router::components::Link;
4
5#[derive(Clone, Props, PartialEq)]
6pub struct CardProps {
7 #[props(optional)]
8 id: String,
9 #[props(optional, default = "".to_string())]
10 class: String,
11 children: Element,
12}
13
14#[component]
15pub fn Card(props: CardProps) -> Element {
16 let mut class_list = vec!["card".to_string()];
17
18 if !props.class.is_empty() {
19 class_list.push(props.class.clone());
20 }
21
22 let class_list = class_list.join(" ");
23
24 rsx! {
25 div {
26 id: props.id,
27 class: class_list,
28 {props.children}
29 }
30 }
31}
32
33#[derive(Clone, Props, PartialEq)]
34pub struct CardHeaderProps {
35 #[props(optional)]
36 id: String,
37 #[props(optional, default = "".to_string())]
38 class: String,
39 children: Element,
40}
41
42#[component]
43pub fn CardHeader(props: CardHeaderProps) -> Element {
44 let mut class_list = vec!["card-header".to_string()];
45
46 if !props.class.is_empty() {
47 class_list.push(props.class.clone());
48 }
49
50 let class_list = class_list.join(" ");
51
52 rsx! {
53 div {
54 id: props.id,
55 class: class_list,
56 {props.children}
57 }
58 }
59}
60
61#[derive(Clone, Props, PartialEq)]
62pub struct CardBodyProps {
63 #[props(optional)]
64 id: String,
65 #[props(optional, default = "".to_string())]
66 class: String,
67 children: Element,
68}
69
70#[component]
71pub fn CardBody(props: CardBodyProps) -> Element {
72 let mut class_list = vec!["card-body".to_string()];
73
74 if !props.class.is_empty() {
75 class_list.push(props.class.clone());
76 }
77
78 let class_list = class_list.join(" ");
79
80 rsx! {
81 div {
82 id: props.id,
83 class: class_list,
84 {props.children}
85 }
86 }
87}
88
89#[derive(Clone, Props, PartialEq)]
90pub struct CardFooterProps {
91 #[props(optional)]
92 id: String,
93 #[props(optional, default = "".to_string())]
94 class: String,
95 children: Element,
96}
97
98#[component]
99pub fn CardFooter(props: CardFooterProps) -> Element {
100 let mut class_list = vec!["card-footer".to_string()];
101
102 if !props.class.is_empty() {
103 class_list.push(props.class.clone());
104 }
105
106 let class_list = class_list.join(" ");
107
108 rsx! {
109 div {
110 id: props.id,
111 class: class_list,
112 {props.children}
113 }
114 }
115}
116
117#[derive(Clone, Props, PartialEq)]
118pub struct CardTitleProps {
119 #[props(optional)]
120 id: String,
121 #[props(optional, default = "".to_string())]
122 class: String,
123 #[props(optional, default = "h5".to_string())]
124 tag: String,
125 children: Element,
126}
127
128#[component]
129pub fn CardTitle(props: CardTitleProps) -> Element {
130 let mut class_list = vec!["card-title".to_string()];
131
132 if !props.class.is_empty() {
133 class_list.push(props.class.clone());
134 }
135
136 let class_list = class_list.join(" ");
137
138 match props.tag.as_str() {
139 "h1" => rsx! { h1 { id: props.id, class: class_list, {props.children} } },
140 "h2" => rsx! { h2 { id: props.id, class: class_list, {props.children} } },
141 "h3" => rsx! { h3 { id: props.id, class: class_list, {props.children} } },
142 "h4" => rsx! { h4 { id: props.id, class: class_list, {props.children} } },
143 "h6" => rsx! { h6 { id: props.id, class: class_list, {props.children} } },
144 _ => rsx! { h5 { id: props.id, class: class_list, {props.children} } },
145 }
146}
147
148#[derive(Clone, Props, PartialEq)]
149pub struct CardTextProps {
150 #[props(optional)]
151 id: String,
152 #[props(optional, default = "".to_string())]
153 class: String,
154 children: Element,
155}
156
157#[component]
158pub fn CardText(props: CardTextProps) -> Element {
159 let mut class_list = vec!["card-text".to_string()];
160
161 if !props.class.is_empty() {
162 class_list.push(props.class.clone());
163 }
164
165 let class_list = class_list.join(" ");
166
167 rsx! {
168 p {
169 id: props.id,
170 class: class_list,
171 {props.children}
172 }
173 }
174}
175
176#[derive(Clone, Props, PartialEq)]
177pub struct CardImageProps {
178 #[props(optional)]
179 id: String,
180 #[props(optional, default = "".to_string())]
181 class: String,
182 #[props(optional, default = false)]
183 top: bool,
184 #[props(optional, default = false)]
185 bottom: bool,
186 src: String,
187 #[props(optional, default = "".to_string())]
188 alt: String,
189}
190
191#[component]
192pub fn CardImage(props: CardImageProps) -> Element {
193 let mut class_list = if props.top {
194 vec!["card-img-top".to_string()]
195 } else if props.bottom {
196 vec!["card-img-bottom".to_string()]
197 } else {
198 vec!["card-img".to_string()]
199 };
200
201 if !props.class.is_empty() {
202 class_list.push(props.class.clone());
203 }
204
205 let class_list = class_list.join(" ");
206
207 rsx! {
208 img {
209 id: props.id,
210 class: class_list,
211 src: props.src,
212 alt: props.alt,
213 }
214 }
215}
216
217#[derive(Clone, Props, PartialEq)]
218pub struct CardLinkProps {
219 #[props(optional)]
220 id: String,
221 #[props(optional, default = "".to_string())]
222 class: String,
223 #[props(optional)]
224 href: Option<String>,
225 #[props(optional)]
226 link_to: Option<NavigationTarget>,
227 children: Element,
228}
229
230#[component]
231pub fn CardLink(props: CardLinkProps) -> Element {
232 let mut class_list = vec!["card-link".to_string()];
233
234 if !props.class.is_empty() {
235 class_list.push(props.class.clone());
236 }
237
238 let class_list = class_list.join(" ");
239
240 match props.link_to {
241 Some(to) => rsx! {
242 Link {
243 id: props.id,
244 class: class_list,
245 to: to,
246 {props.children}
247 }
248 },
249 None => rsx! {
250 a {
251 id: props.id,
252 class: class_list,
253 href: props.href.unwrap_or_default(),
254 {props.children}
255 }
256 }
257 }
258}
259
260#[derive(Clone, Props, PartialEq)]
261pub struct CardGroupProps {
262 #[props(optional)]
263 id: String,
264 #[props(optional, default = "".to_string())]
265 class: String,
266 children: Element,
267}
268
269#[component]
270pub fn CardGroup(props: CardGroupProps) -> Element {
271 let mut class_list = vec!["card-group".to_string()];
272
273 if !props.class.is_empty() {
274 class_list.push(props.class.clone());
275 }
276
277 let class_list = class_list.join(" ");
278
279 rsx! {
280 div {
281 id: props.id,
282 class: class_list,
283 {props.children}
284 }
285 }
286}