label.rs

  1use crate::{LabelLike, prelude::*};
  2use gpui::StyleRefinement;
  3
  4/// A struct representing a label element in the UI.
  5///
  6/// The `Label` struct stores the label text and common properties for a label element.
  7/// It provides methods for modifying these properties.
  8///
  9/// # Examples
 10///
 11/// ```
 12/// use ui::prelude::*;
 13///
 14/// Label::new("Hello, World!");
 15/// ```
 16///
 17/// **A colored label**, for example labeling a dangerous action:
 18///
 19/// ```
 20/// use ui::prelude::*;
 21///
 22/// let my_label = Label::new("Delete").color(Color::Error);
 23/// ```
 24///
 25/// **A label with a strikethrough**, for example labeling something that has been deleted:
 26///
 27/// ```
 28/// use ui::prelude::*;
 29///
 30/// let my_label = Label::new("Deleted").strikethrough();
 31/// ```
 32#[derive(IntoElement, RegisterComponent)]
 33pub struct Label {
 34    base: LabelLike,
 35    label: SharedString,
 36}
 37
 38impl Label {
 39    /// Creates a new [`Label`] with the given text.
 40    ///
 41    /// # Examples
 42    ///
 43    /// ```
 44    /// use ui::prelude::*;
 45    ///
 46    /// let my_label = Label::new("Hello, World!");
 47    /// ```
 48    pub fn new(label: impl Into<SharedString>) -> Self {
 49        Self {
 50            base: LabelLike::new(),
 51            label: label.into(),
 52        }
 53    }
 54
 55    /// Sets the text of the [`Label`].
 56    pub fn set_text(&mut self, text: impl Into<SharedString>) {
 57        self.label = text.into();
 58    }
 59}
 60
 61// Style methods.
 62impl Label {
 63    fn style(&mut self) -> &mut StyleRefinement {
 64        self.base.base.style()
 65    }
 66
 67    gpui::margin_style_methods!({
 68        visibility: pub
 69    });
 70}
 71
 72impl LabelCommon for Label {
 73    /// Sets the size of the label using a [`LabelSize`].
 74    ///
 75    /// # Examples
 76    ///
 77    /// ```
 78    /// use ui::prelude::*;
 79    ///
 80    /// let my_label = Label::new("Hello, World!").size(LabelSize::Small);
 81    /// ```
 82    fn size(mut self, size: LabelSize) -> Self {
 83        self.base = self.base.size(size);
 84        self
 85    }
 86
 87    /// Sets the weight of the label using a [`FontWeight`].
 88    ///
 89    /// # Examples
 90    ///
 91    /// ```
 92    /// use gpui::FontWeight;
 93    /// use ui::prelude::*;
 94    ///
 95    /// let my_label = Label::new("Hello, World!").weight(FontWeight::BOLD);
 96    /// ```
 97    fn weight(mut self, weight: gpui::FontWeight) -> Self {
 98        self.base = self.base.weight(weight);
 99        self
100    }
101
102    /// Sets the line height style of the label using a [`LineHeightStyle`].
103    ///
104    /// # Examples
105    ///
106    /// ```
107    /// use ui::prelude::*;
108    ///
109    /// let my_label = Label::new("Hello, World!").line_height_style(LineHeightStyle::UiLabel);
110    /// ```
111    fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
112        self.base = self.base.line_height_style(line_height_style);
113        self
114    }
115
116    /// Sets the color of the label using a [`Color`].
117    ///
118    /// # Examples
119    ///
120    /// ```
121    /// use ui::prelude::*;
122    ///
123    /// let my_label = Label::new("Hello, World!").color(Color::Accent);
124    /// ```
125    fn color(mut self, color: Color) -> Self {
126        self.base = self.base.color(color);
127        self
128    }
129
130    /// Sets the strikethrough property of the label.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// use ui::prelude::*;
136    ///
137    /// let my_label = Label::new("Hello, World!").strikethrough();
138    /// ```
139    fn strikethrough(mut self) -> Self {
140        self.base = self.base.strikethrough();
141        self
142    }
143
144    /// Sets the italic property of the label.
145    ///
146    /// # Examples
147    ///
148    /// ```
149    /// use ui::prelude::*;
150    ///
151    /// let my_label = Label::new("Hello, World!").italic();
152    /// ```
153    fn italic(mut self) -> Self {
154        self.base = self.base.italic();
155        self
156    }
157
158    /// Sets the alpha property of the color of label.
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// use ui::prelude::*;
164    ///
165    /// let my_label = Label::new("Hello, World!").alpha(0.5);
166    /// ```
167    fn alpha(mut self, alpha: f32) -> Self {
168        self.base = self.base.alpha(alpha);
169        self
170    }
171
172    fn underline(mut self) -> Self {
173        self.base = self.base.underline();
174        self
175    }
176
177    /// Truncates overflowing text with an ellipsis (`…`) if needed.
178    fn truncate(mut self) -> Self {
179        self.base = self.base.truncate();
180        self
181    }
182
183    fn single_line(mut self) -> Self {
184        self.label = SharedString::from(self.label.replace('\n', ""));
185        self.base = self.base.single_line();
186        self
187    }
188
189    fn buffer_font(mut self, cx: &App) -> Self {
190        self.base = self.base.buffer_font(cx);
191        self
192    }
193
194    /// Styles the label to look like inline code.
195    fn inline_code(mut self, cx: &App) -> Self {
196        self.base = self.base.inline_code(cx);
197        self
198    }
199}
200
201impl RenderOnce for Label {
202    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
203        self.base.child(self.label)
204    }
205}
206
207impl Component for Label {
208    fn scope() -> ComponentScope {
209        ComponentScope::Typography
210    }
211
212    fn description() -> Option<&'static str> {
213        Some("A text label component that supports various styles, sizes, and formatting options.")
214    }
215
216    fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
217        Some(
218            v_flex()
219                .gap_6()
220                .children(vec![
221                    example_group_with_title(
222                        "Sizes",
223                        vec![
224                            single_example("Default", Label::new("Project Explorer").into_any_element()),
225                            single_example("Small", Label::new("File: main.rs").size(LabelSize::Small).into_any_element()),
226                            single_example("Large", Label::new("Welcome to Zed").size(LabelSize::Large).into_any_element()),
227                        ],
228                    ),
229                    example_group_with_title(
230                        "Colors",
231                        vec![
232                            single_example("Default", Label::new("Status: Ready").into_any_element()),
233                            single_example("Accent", Label::new("New Update Available").color(Color::Accent).into_any_element()),
234                            single_example("Error", Label::new("Build Failed").color(Color::Error).into_any_element()),
235                        ],
236                    ),
237                    example_group_with_title(
238                        "Styles",
239                        vec![
240                            single_example("Default", Label::new("Normal Text").into_any_element()),
241                            single_example("Bold", Label::new("Important Notice").weight(gpui::FontWeight::BOLD).into_any_element()),
242                            single_example("Italic", Label::new("Code Comment").italic().into_any_element()),
243                            single_example("Strikethrough", Label::new("Deprecated Feature").strikethrough().into_any_element()),
244                            single_example("Underline", Label::new("Clickable Link").underline().into_any_element()),
245                            single_example("Inline Code", Label::new("fn main() {}").inline_code(cx).into_any_element()),
246                        ],
247                    ),
248                    example_group_with_title(
249                        "Line Height Styles",
250                        vec![
251                            single_example("Default", Label::new("Multi-line\nText\nExample").into_any_element()),
252                            single_example("UI Label", Label::new("Compact\nUI\nLabel").line_height_style(LineHeightStyle::UiLabel).into_any_element()),
253                        ],
254                    ),
255                    example_group_with_title(
256                        "Special Cases",
257                        vec![
258                            single_example("Single Line", Label::new("Line 1\nLine 2\nLine 3").single_line().into_any_element()),
259                            single_example("Text Ellipsis", div().max_w_24().child(Label::new("This is a very long file name that should be truncated: very_long_file_name_with_many_words.rs").truncate()).into_any_element()),
260                        ],
261                    ),
262                ])
263                .into_any_element()
264        )
265    }
266}