radix_leptos_primitives/components/
separator.rs1use crate::utils::{merge_classes, generate_id};
2use leptos::children::Children;
3use leptos::prelude::*;
4
5#[component]
7pub fn Separator(
8 #[prop(optional)] class: Option<String>,
9 #[prop(optional)] style: Option<String>,
10 #[prop(optional)] children: Option<Children>,
11 #[prop(optional)] orientation: Option<SeparatorOrientation>,
12 #[prop(optional)] decorative: Option<bool>,
13 #[prop(optional)] thickness: Option<SeparatorThickness>,
14 #[prop(optional)] color: Option<String>,
15) -> impl IntoView {
16 let orientation = orientation.unwrap_or_default();
17 let decorative = decorative.unwrap_or(true);
18 let thickness = thickness.unwrap_or_default();
19 let color = color.unwrap_or_default();
20
21 let class = merge_classes(vec!["separator", orientation.to_class(), thickness.to_class()]);
22 let aria_orientation = orientation.to_aria_orientation();
23
24 view! {
25 <div
26 class=class
27 style=style
28 role=if decorative { "none" } else { "separator" }
29 aria-orientation=aria_orientation
30 data-thickness=thickness.to_string()
31 data-color=color
32 >
33 {children.map(|c| c())}
34 </div>
35 }
36}
37
38#[component]
40pub fn SeparatorLine(
41 #[prop(optional)] class: Option<String>,
42 #[prop(optional)] style: Option<String>,
43 #[prop(optional)] orientation: Option<SeparatorOrientation>,
44 #[prop(optional)] thickness: Option<SeparatorThickness>,
45 #[prop(optional)] color: Option<String>,
46) -> impl IntoView {
47 let orientation = orientation.unwrap_or_default();
48 let thickness = thickness.unwrap_or_default();
49 let color = color.unwrap_or_default();
50
51 let class = merge_classes(
52 [
53 "separator-line",
54 orientation.to_class(),
55 thickness.to_class(),
56 class.as_deref().unwrap_or(""),
57 ]
58 .to_vec(),
59 );
60
61 let aria_orientation = orientation.to_aria_orientation();
62
63 view! {
64 <hr
65 class=class
66 style=style
67 role="separator"
68 aria-orientation=aria_orientation
69 data-thickness=thickness.to_string()
70 data-color=color
71 />
72 }
73}
74
75#[component]
77pub fn SeparatorText(
78 #[prop(optional)] class: Option<String>,
79 #[prop(optional)] style: Option<String>,
80 #[prop(optional)] children: Option<Children>,
81 #[prop(optional)] text: Option<String>,
82 #[prop(optional)] orientation: Option<SeparatorOrientation>,
83) -> impl IntoView {
84 let text = text.unwrap_or_default();
85 let orientation = orientation.unwrap_or_default();
86
87 let class = merge_classes(
88 [
89 "separator-text",
90 orientation.to_class(),
91 class.as_deref().unwrap_or(""),
92 ]
93 .to_vec(),
94 );
95
96 view! {
97 <div
98 class=class
99 style=style
100 role="separator"
101 aria-label=text
102 data-orientation=orientation.to_string()
103 >
104 {children.map(|c| c())}
105 </div>
106 }
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
111pub enum SeparatorOrientation {
112 #[default]
113 Horizontal,
114 Vertical,
115}
116
117impl SeparatorOrientation {
118 pub fn to_class(&self) -> &'static str {
119 match self {
120 SeparatorOrientation::Horizontal => "orientation-horizontal",
121 SeparatorOrientation::Vertical => "orientation-vertical",
122 }
123 }
124
125 pub fn to_string(&self) -> &'static str {
126 match self {
127 SeparatorOrientation::Horizontal => "horizontal",
128 SeparatorOrientation::Vertical => "vertical",
129 }
130 }
131
132 pub fn to_aria_orientation(&self) -> &'static str {
133 match self {
134 SeparatorOrientation::Horizontal => "horizontal",
135 SeparatorOrientation::Vertical => "vertical",
136 }
137 }
138}
139
140#[derive(Debug, Clone, Copy, PartialEq, Default)]
142pub enum SeparatorThickness {
143 #[default]
144 Thin,
145 Medium,
146 Thick,
147 Custom(f64),
148}
149
150impl SeparatorThickness {
151 pub fn to_class(&self) -> &'static str {
152 match self {
153 SeparatorThickness::Thin => "thickness-thin",
154 SeparatorThickness::Medium => "thickness-medium",
155 SeparatorThickness::Thick => "thickness-thick",
156 SeparatorThickness::Custom(_) => "thickness-custom",
157 }
158 }
159
160 pub fn to_string(&self) -> String {
161 match self {
162 SeparatorThickness::Thin => "thin".to_string(),
163 SeparatorThickness::Medium => "medium".to_string(),
164 SeparatorThickness::Thick => "thick".to_string(),
165 SeparatorThickness::Custom(thickness) => format!("custom-{}", thickness),
166 }
167 }
168}
169
170#[component]
172pub fn SeparatorGroup(
173 #[prop(optional)] class: Option<String>,
174 #[prop(optional)] style: Option<String>,
175 #[prop(optional)] children: Option<Children>,
176 #[prop(optional)] spacing: Option<SeparatorSpacing>,
177 #[prop(optional)] orientation: Option<SeparatorOrientation>,
178) -> impl IntoView {
179 let spacing = spacing.unwrap_or_default();
180 let orientation = orientation.unwrap_or_default();
181
182 let class = merge_classes(
183 [
184 "separator-group",
185 spacing.to_class(),
186 orientation.to_class(),
187 class.as_deref().unwrap_or(""),
188 ]
189 .to_vec(),
190 );
191
192 view! {
193 <div
194 class=class
195 style=style
196 role="group"
197 aria-label="Separator group"
198 data-spacing=spacing.to_string()
199 data-orientation=orientation.to_string()
200 >
201 {children.map(|c| c())}
202 </div>
203 }
204}
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
208pub enum SeparatorSpacing {
209 #[default]
210 Tight,
211 Normal,
212 Loose,
213}
214
215impl SeparatorSpacing {
216 pub fn to_class(&self) -> &'static str {
217 match self {
218 SeparatorSpacing::Tight => "spacing-tight",
219 SeparatorSpacing::Normal => "spacing-normal",
220 SeparatorSpacing::Loose => "spacing-loose",
221 }
222 }
223
224 pub fn to_string(&self) -> &'static str {
225 match self {
226 SeparatorSpacing::Tight => "tight",
227 SeparatorSpacing::Normal => "normal",
228 SeparatorSpacing::Loose => "loose",
229 }
230 }
231}
232
233#[cfg(test)]
234mod tests {
235 use proptest::prelude::*;
236 use wasm_bindgen_test::*;
237
238 wasm_bindgen_test_configure!(run_in_browser);
239
240 #[test]
242 fn test_separator_creation() {}
243 #[test]
244 fn test_separator_with_class() {}
245 #[test]
246 fn test_separator_with_style() {}
247 #[test]
248 fn test_separator_orientation() {}
249 #[test]
250 fn test_separator_decorative() {}
251 #[test]
252 fn test_separator_thickness() {}
253 #[test]
254 fn test_separator_color() {}
255
256 #[test]
258 fn test_separator_line_creation() {}
259 #[test]
260 fn test_separator_line_with_class() {}
261 #[test]
262 fn test_separator_line_orientation() {}
263 #[test]
264 fn test_separator_line_thickness() {}
265 #[test]
266 fn test_separator_line_color() {}
267
268 #[test]
270 fn test_separator_text_creation() {}
271 #[test]
272 fn test_separator_text_with_class() {}
273 #[test]
274 fn test_separator_text_text() {}
275 #[test]
276 fn test_separator_text_orientation() {}
277
278 #[test]
280 fn test_separator_orientation_default() {}
281 #[test]
282 fn test_separator_orientation_horizontal() {}
283 #[test]
284 fn test_separator_orientation_vertical() {}
285
286 #[test]
288 fn test_separator_thickness_default() {}
289 #[test]
290 fn test_separator_thickness_thin() {}
291 #[test]
292 fn test_separator_thickness_medium() {}
293 #[test]
294 fn test_separator_thickness_thick() {}
295 #[test]
296 fn test_separator_thickness_custom() {}
297
298 #[test]
300 fn test_separator_group_creation() {}
301 #[test]
302 fn test_separator_group_with_class() {}
303 #[test]
304 fn test_separator_group_spacing() {}
305 #[test]
306 fn test_separator_group_orientation() {}
307
308 #[test]
310 fn test_separator_spacing_default() {}
311 #[test]
312 fn test_separator_spacing_tight() {}
313 #[test]
314 fn test_separator_spacing_normal() {}
315 #[test]
316 fn test_separator_spacing_loose() {}
317
318 #[test]
320 fn test_merge_classes_empty() {}
321 #[test]
322 fn test_merge_classes_single() {}
323 #[test]
324 fn test_merge_classes_multiple() {}
325 #[test]
326 fn test_merge_classes_with_empty() {}
327
328 #[test]
330 fn test_separator_property_based() {
331 proptest!(|(____class in ".*", __style in ".*")| {
332
333 });
334 }
335
336 #[test]
337 fn test_separator_thickness_validation() {
338 proptest!(|(____thickness in 1.0..20.0f64)| {
339
340 });
341 }
342
343 #[test]
344 fn test_separator_orientation_validation() {
345 proptest!(|(____orientation in ".*")| {
346
347 });
348 }
349
350 #[test]
352 fn test_separator_accessibility() {}
353 #[test]
354 fn test_separator_orientation_behavior() {}
355 #[test]
356 fn test_separator_thickness_rendering() {}
357 #[test]
358 fn test_separator_group_layout() {}
359 #[test]
360 fn test_separator_responsive_behavior() {}
361
362 #[test]
364 fn test_separator_large_groups() {}
365 #[test]
366 fn test_separator_render_performance() {}
367 #[test]
368 fn test_separator_memory_usage() {}
369 #[test]
370 fn test_separator_layout_performance() {}
371}