1use crate::prelude::*;
2use gpui::{AnyElement, AnyView, Hsla, IntoElement, ParentElement, Styled};
3
4/// Chips provide a container for an informative label.
5///
6/// # Usage Example
7///
8/// ```
9/// use ui::Chip;
10///
11/// let chip = Chip::new("This Chip");
12/// ```
13#[derive(IntoElement, RegisterComponent)]
14pub struct Chip {
15 label: SharedString,
16 label_color: Color,
17 label_size: LabelSize,
18 bg_color: Option<Hsla>,
19 border_color: Option<Hsla>,
20 height: Option<Pixels>,
21 tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView + 'static>>,
22}
23
24impl Chip {
25 /// Creates a new `Chip` component with the specified label.
26 pub fn new(label: impl Into<SharedString>) -> Self {
27 Self {
28 label: label.into(),
29 label_color: Color::Default,
30 label_size: LabelSize::XSmall,
31 bg_color: None,
32 border_color: None,
33 height: None,
34 tooltip: None,
35 }
36 }
37
38 /// Sets the color of the label.
39 pub fn label_color(mut self, color: Color) -> Self {
40 self.label_color = color;
41 self
42 }
43
44 /// Sets the size of the label.
45 pub fn label_size(mut self, size: LabelSize) -> Self {
46 self.label_size = size;
47 self
48 }
49
50 /// Sets a custom background color for the callout content.
51 pub fn bg_color(mut self, color: Hsla) -> Self {
52 self.bg_color = Some(color);
53 self
54 }
55
56 /// Sets a custom border color for the chip.
57 pub fn border_color(mut self, color: Hsla) -> Self {
58 self.border_color = Some(color);
59 self
60 }
61
62 /// Sets a custom height for the chip.
63 pub fn height(mut self, height: Pixels) -> Self {
64 self.height = Some(height);
65 self
66 }
67
68 pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
69 self.tooltip = Some(Box::new(tooltip));
70 self
71 }
72}
73
74impl RenderOnce for Chip {
75 fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
76 let bg_color = self
77 .bg_color
78 .unwrap_or(cx.theme().colors().element_background);
79
80 let border_color = self.border_color.unwrap_or(cx.theme().colors().border);
81
82 h_flex()
83 .when_some(self.height, |this, h| this.h(h))
84 .min_w_0()
85 .flex_initial()
86 .px_1()
87 .border_1()
88 .rounded_sm()
89 .border_color(border_color)
90 .bg(bg_color)
91 .overflow_hidden()
92 .child(
93 Label::new(self.label.clone())
94 .size(self.label_size)
95 .color(self.label_color)
96 .buffer_font(cx)
97 .truncate(),
98 )
99 .id(self.label.clone())
100 .when_some(self.tooltip, |this, tooltip| this.tooltip(tooltip))
101 }
102}
103
104impl Component for Chip {
105 fn scope() -> ComponentScope {
106 ComponentScope::DataDisplay
107 }
108
109 fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
110 let chip_examples = vec![
111 single_example("Default", Chip::new("Chip Example").into_any_element()),
112 single_example(
113 "Customized Label Color",
114 Chip::new("Chip Example")
115 .label_color(Color::Accent)
116 .into_any_element(),
117 ),
118 single_example(
119 "Customized Label Size",
120 Chip::new("Chip Example")
121 .label_size(LabelSize::Large)
122 .label_color(Color::Accent)
123 .into_any_element(),
124 ),
125 single_example(
126 "Customized Background Color",
127 Chip::new("Chip Example")
128 .bg_color(cx.theme().colors().text_accent.opacity(0.1))
129 .into_any_element(),
130 ),
131 ];
132
133 Some(example_group(chip_examples).vertical().into_any_element())
134 }
135}