Skip to main content

guise/
indicator.rs

1//! `Indicator` — a dot or count badge overlaid on a child element.
2
3use gpui::prelude::*;
4use gpui::{div, px, AnyElement, App, FontWeight, IntoElement, SharedString, Window};
5
6use crate::devtools::Probed;
7use crate::theme::{theme, ColorName};
8
9/// A corner indicator over any child.
10#[derive(IntoElement)]
11pub struct Indicator {
12  child: AnyElement,
13  label: Option<SharedString>,
14  color: ColorName,
15  disabled: bool,
16}
17
18impl Indicator {
19  pub fn new(child: impl IntoElement) -> Self {
20    Indicator {
21      child: child.into_any_element(),
22      label: None,
23      color: ColorName::Red,
24      disabled: false,
25    }
26  }
27
28  /// Show a count/text instead of a plain dot.
29  pub fn label(mut self, label: impl Into<SharedString>) -> Self {
30    self.label = Some(label.into());
31    self
32  }
33
34  pub fn color(mut self, color: ColorName) -> Self {
35    self.color = color;
36    self
37  }
38
39  /// Hide the indicator (but keep the child).
40  pub fn disabled(mut self, disabled: bool) -> Self {
41    self.disabled = disabled;
42    self
43  }
44}
45
46impl RenderOnce for Indicator {
47  fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
48    let t = theme(cx);
49    let accent = t.color(self.color, t.primary_shade());
50    let fg = accent.contrasting().hsla();
51    let bg = accent.hsla();
52
53    let mut root = div().relative().child(self.child);
54    if !self.disabled {
55      let dot = match self.label {
56        Some(label) => div()
57          .absolute()
58          .top(px(-4.0))
59          .right(px(-4.0))
60          .h(px(16.0))
61          .min_w(px(16.0))
62          .px(px(4.0))
63          .flex()
64          .items_center()
65          .justify_center()
66          .rounded(px(16.0))
67          .bg(bg)
68          .text_color(fg)
69          .text_size(px(10.0))
70          .font_weight(FontWeight::BOLD)
71          .child(label),
72        None => div()
73          .absolute()
74          .top(px(-2.0))
75          .right(px(-2.0))
76          .w(px(10.0))
77          .h(px(10.0))
78          .rounded(px(10.0))
79          .bg(bg),
80      };
81      root = root.child(dot);
82    }
83    root.probe("Indicator")
84  }
85}