Skip to main content

guise/
divider.rs

1//! `Divider` — a thin separating line, optionally with a centered label.
2
3use gpui::prelude::*;
4use gpui::{div, px, App, IntoElement, SharedString, Window};
5
6use crate::devtools::Probed;
7use crate::theme::theme;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Orientation {
11  Horizontal,
12  Vertical,
13}
14
15/// A separator line.
16#[derive(IntoElement)]
17pub struct Divider {
18  orientation: Orientation,
19  label: Option<SharedString>,
20}
21
22impl Divider {
23  pub fn new() -> Self {
24    Divider {
25      orientation: Orientation::Horizontal,
26      label: None,
27    }
28  }
29
30  pub fn vertical() -> Self {
31    Divider {
32      orientation: Orientation::Vertical,
33      label: None,
34    }
35  }
36
37  /// A label rendered centered on a horizontal divider.
38  pub fn label(mut self, label: impl Into<SharedString>) -> Self {
39    self.label = Some(label.into());
40    self
41  }
42}
43
44impl Default for Divider {
45  fn default() -> Self {
46    Divider::new()
47  }
48}
49
50impl RenderOnce for Divider {
51  fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
52    let t = theme(cx);
53    let line_color = t.border().hsla();
54
55    if self.orientation == Orientation::Vertical {
56      return div().w(px(1.0)).h_full().bg(line_color).into_any_element();
57    }
58
59    let element = match self.label {
60      None => div().w_full().h(px(1.0)).bg(line_color),
61      Some(label) => div()
62        .flex()
63        .items_center()
64        .gap(px(t.spacing(crate::theme::Size::Sm)))
65        .w_full()
66        .child(div().flex_1().h(px(1.0)).bg(line_color))
67        .child(
68          div()
69            .text_size(px(t.font_size(crate::theme::Size::Sm)))
70            .text_color(t.dimmed().hsla())
71            .child(label),
72        )
73        .child(div().flex_1().h(px(1.0)).bg(line_color)),
74    };
75
76    element.probe("Divider").into_any_element()
77  }
78}