1use std::rc::Rc;
2
3use crate::Divider;
4use crate::DividerColor;
5use crate::Tooltip;
6use crate::component_prelude::*;
7use crate::prelude::*;
8use gpui::AnyView;
9use gpui::{AnyElement, IntoElement, SharedString, Window};
10
11#[derive(IntoElement, RegisterComponent)]
12pub struct Badge {
13 label: SharedString,
14 icon: IconName,
15 tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
16}
17
18impl Badge {
19 pub fn new(label: impl Into<SharedString>) -> Self {
20 Self {
21 label: label.into(),
22 icon: IconName::Check,
23 tooltip: None,
24 }
25 }
26
27 pub const fn icon(mut self, icon: IconName) -> Self {
28 self.icon = icon;
29 self
30 }
31
32 pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
33 self.tooltip = Some(Rc::new(tooltip));
34 self
35 }
36}
37
38impl RenderOnce for Badge {
39 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
40 let tooltip = self.tooltip;
41
42 h_flex()
43 .id(self.label.clone())
44 .h_full()
45 .gap_1()
46 .pl_1()
47 .pr_2()
48 .border_1()
49 .border_color(cx.theme().colors().border.opacity(0.6))
50 .bg(cx.theme().colors().element_background)
51 .rounded_sm()
52 .overflow_hidden()
53 .child(
54 Icon::new(self.icon)
55 .size(IconSize::XSmall)
56 .color(Color::Muted),
57 )
58 .child(Divider::vertical().color(DividerColor::Border))
59 .child(Label::new(self.label.clone()).size(LabelSize::Small).ml_1())
60 .when_some(tooltip, |this, tooltip| {
61 this.hoverable_tooltip(move |window, cx| tooltip(window, cx))
62 })
63 }
64}
65
66impl Component for Badge {
67 fn scope() -> ComponentScope {
68 ComponentScope::DataDisplay
69 }
70
71 fn description() -> Option<&'static str> {
72 Some(
73 "A compact, labeled component with optional icon for displaying status, categories, or metadata.",
74 )
75 }
76
77 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
78 Some(
79 v_flex()
80 .gap_6()
81 .child(single_example(
82 "Basic Badge",
83 Badge::new("Default").into_any_element(),
84 ))
85 .child(single_example(
86 "With Tooltip",
87 Badge::new("Tooltip")
88 .tooltip(Tooltip::text("This is a tooltip."))
89 .into_any_element(),
90 ))
91 .into_any_element(),
92 )
93 }
94}