Skip to main content

stratum_components/layout/
divider.rs

1//! Styled Divider/Separator component.
2
3use crate::common::merge_classes;
4use stratum_core::aria::{AriaAttributes, AriaRole, Orientation};
5use stratum_core::render::RenderOutput;
6
7/// Properties for the Divider component.
8#[derive(Debug, Clone, PartialEq)]
9pub struct DividerProps {
10    pub orientation: Orientation,
11    pub decorative: bool,
12    pub class: Option<String>,
13}
14
15impl Default for DividerProps {
16    fn default() -> Self {
17        Self {
18            orientation: Orientation::Horizontal,
19            decorative: true,
20            class: None,
21        }
22    }
23}
24
25pub struct Divider;
26
27impl Divider {
28    pub fn classes(props: &DividerProps) -> String {
29        let base = match props.orientation {
30            Orientation::Horizontal => "shrink-0 bg-border h-[1px] w-full",
31            Orientation::Vertical => "shrink-0 bg-border h-full w-[1px]",
32        };
33        merge_classes(base, &props.class)
34    }
35
36    pub fn render(props: &DividerProps) -> RenderOutput {
37        let classes = Self::classes(props);
38        let mut aria = AriaAttributes::new()
39            .with_role(AriaRole::Separator)
40            .with_orientation(props.orientation);
41
42        if props.decorative {
43            aria.hidden = Some(true);
44        }
45
46        RenderOutput::new()
47            .with_tag("div")
48            .with_class(classes)
49            .with_aria(aria)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn divider_horizontal() {
59        let props = DividerProps::default();
60        let classes = Divider::classes(&props);
61        assert!(classes.contains("w-full"));
62        assert!(classes.contains("h-[1px]"));
63    }
64
65    #[test]
66    fn divider_vertical() {
67        let props = DividerProps {
68            orientation: Orientation::Vertical,
69            ..Default::default()
70        };
71        let classes = Divider::classes(&props);
72        assert!(classes.contains("w-[1px]"));
73        assert!(classes.contains("h-full"));
74    }
75
76    #[test]
77    fn divider_decorative_hidden() {
78        let props = DividerProps::default();
79        let output = Divider::render(&props);
80        assert_eq!(output.aria.hidden, Some(true));
81    }
82
83    #[test]
84    fn divider_non_decorative_visible() {
85        let props = DividerProps {
86            decorative: false,
87            ..Default::default()
88        };
89        let output = Divider::render(&props);
90        assert!(output.aria.hidden.is_none());
91    }
92}