1use gpui::prelude::*;
6use gpui::*;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
10pub enum BadgeVariant {
11 #[default]
13 Default,
14 Primary,
16 Success,
18 Warning,
20 Error,
22 Info,
24}
25
26impl BadgeVariant {
27 fn colors(&self) -> (Rgba, Rgba) {
28 match self {
30 BadgeVariant::Default => (rgb(0x3a3a3a), rgb(0xcccccc)),
31 BadgeVariant::Primary => (rgb(0x1a4a7a), rgb(0x7cc4ff)),
32 BadgeVariant::Success => (rgb(0x1a3a1a), rgb(0x7ccc7c)),
33 BadgeVariant::Warning => (rgb(0x3a3a1a), rgb(0xcccc7c)),
34 BadgeVariant::Error => (rgb(0x3a1a1a), rgb(0xcc7c7c)),
35 BadgeVariant::Info => (rgb(0x1a3a3a), rgb(0x7ccccc)),
36 }
37 }
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
42pub enum BadgeSize {
43 Sm,
45 #[default]
47 Md,
48 Lg,
50}
51
52pub struct Badge {
54 label: SharedString,
55 variant: BadgeVariant,
56 size: BadgeSize,
57 rounded: bool,
58 icon: Option<SharedString>,
59}
60
61impl Badge {
62 pub fn new(label: impl Into<SharedString>) -> Self {
64 Self {
65 label: label.into(),
66 variant: BadgeVariant::default(),
67 size: BadgeSize::default(),
68 rounded: false,
69 icon: None,
70 }
71 }
72
73 pub fn variant(mut self, variant: BadgeVariant) -> Self {
75 self.variant = variant;
76 self
77 }
78
79 pub fn size(mut self, size: BadgeSize) -> Self {
81 self.size = size;
82 self
83 }
84
85 pub fn rounded(mut self, rounded: bool) -> Self {
87 self.rounded = rounded;
88 self
89 }
90
91 pub fn icon(mut self, icon: impl Into<SharedString>) -> Self {
93 self.icon = Some(icon.into());
94 self
95 }
96
97 pub fn build(self) -> Div {
99 let (bg, text_color) = self.variant.colors();
100
101 let (px_val, py_val) = match self.size {
102 BadgeSize::Sm => (px(6.0), px(2.0)),
103 BadgeSize::Md => (px(8.0), px(3.0)),
104 BadgeSize::Lg => (px(12.0), px(4.0)),
105 };
106
107 let mut badge = div()
108 .flex()
109 .items_center()
110 .gap_1()
111 .px(px_val)
112 .py(py_val)
113 .bg(bg)
114 .text_color(text_color);
115
116 badge = match self.size {
118 BadgeSize::Sm => badge.text_xs(),
119 BadgeSize::Md => badge.text_xs(),
120 BadgeSize::Lg => badge.text_sm(),
121 };
122
123 if self.rounded {
125 badge = badge.rounded_full();
126 } else {
127 badge = badge.rounded(px(3.0));
128 }
129
130 if let Some(icon) = self.icon {
132 badge = badge.child(div().child(icon));
133 }
134
135 badge = badge.child(self.label);
137
138 badge
139 }
140}
141
142impl IntoElement for Badge {
143 type Element = Div;
144
145 fn into_element(self) -> Self::Element {
146 self.build()
147 }
148}
149
150pub struct BadgeDot {
152 variant: BadgeVariant,
153 size: Pixels,
154}
155
156impl BadgeDot {
157 pub fn new() -> Self {
159 Self {
160 variant: BadgeVariant::default(),
161 size: px(8.0),
162 }
163 }
164
165 pub fn variant(mut self, variant: BadgeVariant) -> Self {
167 self.variant = variant;
168 self
169 }
170
171 pub fn size(mut self, size: Pixels) -> Self {
173 self.size = size;
174 self
175 }
176
177 pub fn build(self) -> Div {
179 let (bg, _) = self.variant.colors();
180
181 div().w(self.size).h(self.size).rounded_full().bg(bg)
182 }
183}
184
185impl Default for BadgeDot {
186 fn default() -> Self {
187 Self::new()
188 }
189}
190
191impl IntoElement for BadgeDot {
192 type Element = Div;
193
194 fn into_element(self) -> Self::Element {
195 self.build()
196 }
197}