1use crate::theme::use_theme;
2use dioxus::prelude::*;
3
4#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
5pub enum DividerOrientation {
6 Left,
7 #[default]
8 Center,
9 Right,
10}
11
12#[derive(Props, Clone, PartialEq)]
14pub struct DividerProps {
15 #[props(default)]
16 pub dashed: bool,
17 #[props(default)]
18 pub plain: bool,
19 #[props(default)]
20 pub vertical: bool,
21 #[props(default)]
22 pub orientation: DividerOrientation,
23 #[props(optional)]
24 pub orientation_margin: Option<String>,
25 #[props(optional)]
26 pub class: Option<String>,
27 #[props(optional)]
28 pub style: Option<String>,
29 #[props(optional)]
31 pub content: Option<Element>,
32}
33
34#[component]
36pub fn Divider(props: DividerProps) -> Element {
37 let DividerProps {
38 dashed,
39 plain,
40 vertical,
41 orientation,
42 orientation_margin,
43 class,
44 style,
45 content,
46 } = props;
47 let theme = use_theme();
48 let tokens = theme.tokens();
49
50 let has_content = content.is_some();
51
52 let mut class_list = vec!["adui-divider".to_string()];
53 if vertical {
54 class_list.push("adui-divider-vertical".into());
55 } else {
56 class_list.push("adui-divider-horizontal".into());
57 if has_content {
58 class_list.push(match orientation {
59 DividerOrientation::Left => "adui-divider-left".into(),
60 DividerOrientation::Center => "adui-divider-center".into(),
61 DividerOrientation::Right => "adui-divider-right".into(),
62 });
63 }
64 }
65 if dashed {
66 class_list.push("adui-divider-dashed".into());
67 }
68 if plain {
69 class_list.push("adui-divider-plain".into());
70 }
71 if let Some(extra) = class.as_ref() {
72 class_list.push(extra.clone());
73 }
74 let class_attr = class_list.join(" ");
75
76 let style_attr = format!(
77 "border-color:{};{}",
78 tokens.color_border,
79 style.unwrap_or_default()
80 );
81
82 if vertical {
83 return rsx! {
84 div {
85 class: "{class_attr}",
86 style: "{style_attr}",
87 role: "separator",
88 "aria-orientation": "vertical",
89 }
90 };
91 }
92
93 let margin = orientation_margin.unwrap_or_else(|| "16px".into());
94
95 rsx! {
96 div {
97 class: "{class_attr}",
98 style: "{style_attr}",
99 role: "separator",
100 "aria-orientation": "horizontal",
101 if let Some(node) = content {
102 span {
103 class: "adui-divider-inner-text",
104 style: format!("margin: 0 {margin};"),
105 {node}
106 }
107 }
108 }
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn divider_orientation_default() {
118 assert_eq!(DividerOrientation::default(), DividerOrientation::Center);
119 }
120
121 #[test]
122 fn divider_orientation_variants() {
123 assert_ne!(DividerOrientation::Left, DividerOrientation::Center);
124 assert_ne!(DividerOrientation::Center, DividerOrientation::Right);
125 assert_ne!(DividerOrientation::Left, DividerOrientation::Right);
126 }
127
128 #[test]
129 fn divider_orientation_equality() {
130 assert_eq!(DividerOrientation::Left, DividerOrientation::Left);
131 assert_eq!(DividerOrientation::Center, DividerOrientation::Center);
132 assert_eq!(DividerOrientation::Right, DividerOrientation::Right);
133 }
134
135 #[test]
136 fn divider_props_defaults() {
137 let props = DividerProps {
138 dashed: false,
139 plain: false,
140 vertical: false,
141 orientation: DividerOrientation::default(),
142 orientation_margin: None,
143 class: None,
144 style: None,
145 content: None,
146 };
147 assert_eq!(props.dashed, false);
148 assert_eq!(props.plain, false);
149 assert_eq!(props.vertical, false);
150 assert_eq!(props.orientation, DividerOrientation::Center);
151 }
152
153 #[test]
154 fn divider_orientation_clone() {
155 let original = DividerOrientation::Left;
156 let cloned = original;
157 assert_eq!(original, cloned);
158 }
159
160 #[test]
161 fn divider_orientation_all_variants() {
162 let left = DividerOrientation::Left;
164 let center = DividerOrientation::Center;
165 let right = DividerOrientation::Right;
166
167 assert_ne!(left, center);
168 assert_ne!(center, right);
169 assert_ne!(left, right);
170 }
171
172 #[test]
173 fn divider_orientation_debug() {
174 let left = DividerOrientation::Left;
175 let center = DividerOrientation::Center;
176 let right = DividerOrientation::Right;
177
178 let left_str = format!("{:?}", left);
179 let center_str = format!("{:?}", center);
180 let right_str = format!("{:?}", right);
181
182 assert!(left_str.contains("Left"));
183 assert!(center_str.contains("Center"));
184 assert!(right_str.contains("Right"));
185 }
186
187 #[test]
188 fn divider_props_with_all_fields() {
189 let props = DividerProps {
190 dashed: true,
191 plain: true,
192 vertical: true,
193 orientation: DividerOrientation::Left,
194 orientation_margin: Some("20px".into()),
195 class: Some("custom-class".into()),
196 style: Some("color: red;".into()),
197 content: None,
198 };
199 assert_eq!(props.dashed, true);
200 assert_eq!(props.plain, true);
201 assert_eq!(props.vertical, true);
202 assert_eq!(props.orientation, DividerOrientation::Left);
203 assert_eq!(props.orientation_margin, Some("20px".into()));
204 assert_eq!(props.class, Some("custom-class".into()));
205 }
206
207 #[test]
208 fn divider_props_dashed_only() {
209 let props = DividerProps {
210 dashed: true,
211 plain: false,
212 vertical: false,
213 orientation: DividerOrientation::Center,
214 orientation_margin: None,
215 class: None,
216 style: None,
217 content: None,
218 };
219 assert_eq!(props.dashed, true);
220 assert_eq!(props.plain, false);
221 }
222
223 #[test]
224 fn divider_props_plain_only() {
225 let props = DividerProps {
226 dashed: false,
227 plain: true,
228 vertical: false,
229 orientation: DividerOrientation::Center,
230 orientation_margin: None,
231 class: None,
232 style: None,
233 content: None,
234 };
235 assert_eq!(props.dashed, false);
236 assert_eq!(props.plain, true);
237 }
238
239 #[test]
240 fn divider_props_vertical() {
241 let props = DividerProps {
242 dashed: false,
243 plain: false,
244 vertical: true,
245 orientation: DividerOrientation::Center,
246 orientation_margin: None,
247 class: None,
248 style: None,
249 content: None,
250 };
251 assert_eq!(props.vertical, true);
252 }
253
254 #[test]
255 fn divider_props_orientation_left() {
256 let props = DividerProps {
257 dashed: false,
258 plain: false,
259 vertical: false,
260 orientation: DividerOrientation::Left,
261 orientation_margin: None,
262 class: None,
263 style: None,
264 content: None,
265 };
266 assert_eq!(props.orientation, DividerOrientation::Left);
267 }
268
269 #[test]
270 fn divider_props_orientation_right() {
271 let props = DividerProps {
272 dashed: false,
273 plain: false,
274 vertical: false,
275 orientation: DividerOrientation::Right,
276 orientation_margin: None,
277 class: None,
278 style: None,
279 content: None,
280 };
281 assert_eq!(props.orientation, DividerOrientation::Right);
282 }
283
284 #[test]
285 fn divider_props_clone() {
286 let props = DividerProps {
287 dashed: true,
288 plain: true,
289 vertical: false,
290 orientation: DividerOrientation::Left,
291 orientation_margin: Some("10px".into()),
292 class: Some("test".into()),
293 style: None,
294 content: None,
295 };
296 let cloned = props.clone();
297 assert_eq!(props.dashed, cloned.dashed);
298 assert_eq!(props.plain, cloned.plain);
299 assert_eq!(props.vertical, cloned.vertical);
300 assert_eq!(props.orientation, cloned.orientation);
301 assert_eq!(props.orientation_margin, cloned.orientation_margin);
302 assert_eq!(props.class, cloned.class);
303 }
304
305 #[test]
306 fn divider_props_with_custom_margin() {
307 let props = DividerProps {
308 dashed: false,
309 plain: false,
310 vertical: false,
311 orientation: DividerOrientation::Center,
312 orientation_margin: Some("24px".into()),
313 class: None,
314 style: None,
315 content: None,
316 };
317 assert_eq!(props.orientation_margin, Some("24px".into()));
318 }
319}