Skip to main content

tablo_ui/components/primitives/
separator.rs

1// SYNC: topcoat-ui-registry@0.11.0 sha256:7ba5a7628128e1811e960884bd56da34f754c1d516230b4442dfbc1cb97e73e9 — do not hand-edit. Sync via `cargo xtask sync-topcoat-ui` (ADR-0007).
2use topcoat::{
3    Result,
4    view::{Attributes, PromotedStr, StaticClass, View, class, component, view},
5};
6
7/// The direction a [`separator`] runs in.
8///
9/// [`Default`] is `SeparatorOrientation::Horizontal`, used when no
10/// orientation is given.
11#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
12#[allow(dead_code)]
13pub enum SeparatorOrientation {
14    /// A rule across the full width of its container.
15    #[default]
16    Horizontal,
17    /// A rule down the full height of its container.
18    Vertical,
19}
20
21impl SeparatorOrientation {
22    /// Classes that set the rule's thickness and stretch it along its orientation.
23    fn classes(self) -> StaticClass {
24        match self {
25            Self::Horizontal => class!("h-px w-full"),
26            Self::Vertical => class!("h-full w-px"),
27        }
28    }
29
30    /// The value of the `aria-orientation` attribute, or `None` for the
31    /// horizontal default assistive technology already assumes.
32    fn aria(self) -> Option<PromotedStr> {
33        match self {
34            Self::Horizontal => None,
35            Self::Vertical => Some(PromotedStr(&"vertical")),
36        }
37    }
38}
39
40/// Classes for a separator that keeps its thickness in a flex layout.
41const SEPARATOR: StaticClass = class!("shrink-0 border-0 bg-border");
42
43/// A thin rule between groups of content.
44///
45/// Uses an `<hr>` element. Its length comes from its container, so a vertical separator
46/// needs a container with a height. Pass `aria-hidden="true"` for a purely decorative
47/// rule. `attrs` are forwarded to the `<hr>`, with extra classes added to its classes.
48///
49/// ```ignore
50/// view! {
51///     <div class="flex flex-col gap-4">
52///         <p>"Everyone with access to this workspace."</p>
53///         separator()
54///         <div class="flex h-5 items-center gap-3">
55///             <a href="/docs">"Docs"</a>
56///             separator(orientation: SeparatorOrientation::Vertical)
57///             <a href="/blog">"Blog"</a>
58///         </div>
59///     </div>
60/// }
61/// ```
62#[component]
63pub async fn separator(
64    /// The direction the rule runs in.
65    #[default]
66    orientation: SeparatorOrientation,
67    /// Extra attributes for the `<hr>` element.
68    #[default]
69    mut attrs: Attributes,
70) -> Result<impl View> {
71    Ok(view! {
72        <hr
73            class=(class!(SEPARATOR, orientation.classes(), attrs.remove("class")))
74            aria-orientation=(orientation.aria())
75            (attrs)
76        >
77    })
78}