Skip to main content

guise/
badge.rs

1//! `Badge` — a small pill for labels, counts, and statuses.
2
3use gpui::prelude::*;
4use gpui::{div, px, App, FontWeight, IntoElement, SharedString, Window};
5
6use crate::style::{surface, ColorValue, Variant};
7use crate::theme::{theme, Size};
8
9/// A compact status pill. The Mantine `Badge`.
10#[derive(IntoElement)]
11pub struct Badge {
12    label: SharedString,
13    variant: Variant,
14    color: ColorValue,
15    size: Size,
16}
17
18impl Badge {
19    pub fn new(label: impl Into<SharedString>) -> Self {
20        Badge {
21            label: label.into(),
22            variant: Variant::Light,
23            color: ColorValue::default(),
24            size: Size::Md,
25        }
26    }
27
28    pub fn variant(mut self, variant: Variant) -> Self {
29        self.variant = variant;
30        self
31    }
32
33    pub fn color(mut self, color: impl Into<ColorValue>) -> Self {
34        self.color = color.into();
35        self
36    }
37
38    pub fn size(mut self, size: Size) -> Self {
39        self.size = size;
40        self
41    }
42
43    /// (height, horizontal padding, font size).
44    fn metrics(&self) -> (f32, f32, f32) {
45        match self.size {
46            Size::Xs => (16.0, 6.0, 9.0),
47            Size::Sm => (18.0, 8.0, 10.0),
48            Size::Md => (20.0, 10.0, 11.0),
49            Size::Lg => (26.0, 12.0, 13.0),
50            Size::Xl => (32.0, 16.0, 16.0),
51        }
52    }
53}
54
55impl RenderOnce for Badge {
56    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
57        let t = theme(cx);
58        let s = surface(t, self.color, self.variant);
59        let (height, pad_x, font) = self.metrics();
60        let mut el = div()
61            .flex()
62            .items_center()
63            .justify_center()
64            .h(px(height))
65            .px(px(pad_x))
66            .rounded(px(height))
67            .bg(s.bg)
68            .text_color(s.fg)
69            .text_size(px(font))
70            .font_weight(FontWeight::BOLD)
71            .child(self.label);
72        if let Some(border) = s.border {
73            el = el.border_1().border_color(border);
74        }
75        el
76    }
77}