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(true);
 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 ui::prelude::*;
 93    ///
 94    /// let my_label = Label::new("Hello, World!").weight(FontWeight::Bold);
 95    /// ```
 96    fn weight(mut self, weight: gpui::FontWeight) -> Self {
 97        self.base = self.base.weight(weight);
 98        self
 99    }
100
101    /// Sets the line height style of the label using a [`LineHeightStyle`].
102    ///
103    /// # Examples
104    ///
105    /// ```
106    /// use ui::prelude::*;
107    ///
108    /// let my_label = Label::new("Hello, World!").line_height_style(LineHeightStyle::UiLabel);
109    /// ```
110    fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
111        self.base = self.base.line_height_style(line_height_style);
112        self
113    }
114
115    /// Sets the color of the label using a [`Color`].
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use ui::prelude::*;
121    ///
122    /// let my_label = Label::new("Hello, World!").color(Color::Accent);
123    /// ```
124    fn color(mut self, color: Color) -> Self {
125        self.base = self.base.color(color);
126        self
127    }
128
129    /// Sets the strikethrough property of the label.
130    ///
131    /// # Examples
132    ///
133    /// ```
134    /// use ui::prelude::*;
135    ///
136    /// let my_label = Label::new("Hello, World!").strikethrough(true);
137    /// ```
138    fn strikethrough(mut self) -> Self {
139        self.base = self.base.strikethrough();
140        self
141    }
142
143    /// Sets the italic property of the label.
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// use ui::prelude::*;
149    ///
150    /// let my_label = Label::new("Hello, World!").italic(true);
151    /// ```
152    fn italic(mut self) -> Self {
153        self.base = self.base.italic();
154        self
155    }
156
157    /// Sets the alpha property of the color of label.
158    ///
159    /// # Examples
160    ///
161    /// ```
162    /// use ui::prelude::*;
163    ///
164    /// let my_label = Label::new("Hello, World!").alpha(0.5);
165    /// ```
166    fn alpha(mut self, alpha: f32) -> Self {
167        self.base = self.base.alpha(alpha);
168        self
169    }
170
171    fn underline(mut self) -> Self {
172        self.base = self.base.underline();
173        self
174    }
175
176    /// Truncates overflowing text with an ellipsis (`…`) if needed.
177    fn truncate(mut self) -> Self {
178        self.base = self.base.truncate();
179        self
180    }
181
182    fn single_line(mut self) -> Self {
183        self.label = SharedString::from(self.label.replace('\n', ""));
184        self.base = self.base.single_line();
185        self
186    }
187
188    fn buffer_font(mut self, cx: &App) -> Self {
189        self.base = self.base.buffer_font(cx);
190        self
191    }
192
193    /// Styles the label to look like inline code.
194    fn inline_code(mut self, cx: &App) -> Self {
195        self.base = self.base.inline_code(cx);
196        self
197    }
198}
199
200impl RenderOnce for Label {
201    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
202        self.base.child(self.label)
203    }
204}
205
206impl Component for Label {
207    fn scope() -> ComponentScope {
208        ComponentScope::Typography
209    }
210
211    fn description() -> Option<&'static str> {
212        Some("A text label component that supports various styles, sizes, and formatting options.")
213    }
214
215    fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
216        Some(
217            v_flex()
218                .gap_6()
219                .children(vec![
220                    example_group_with_title(
221                        "Sizes",
222                        vec![
223                            single_example("Default", Label::new("Project Explorer").into_any_element()),
224                            single_example("Small", Label::new("File: main.rs").size(LabelSize::Small).into_any_element()),
225                            single_example("Large", Label::new("Welcome to Zed").size(LabelSize::Large).into_any_element()),
226                        ],
227                    ),
228                    example_group_with_title(
229                        "Colors",
230                        vec![
231                            single_example("Default", Label::new("Status: Ready").into_any_element()),
232                            single_example("Accent", Label::new("New Update Available").color(Color::Accent).into_any_element()),
233                            single_example("Error", Label::new("Build Failed").color(Color::Error).into_any_element()),
234                        ],
235                    ),
236                    example_group_with_title(
237                        "Styles",
238                        vec![
239                            single_example("Default", Label::new("Normal Text").into_any_element()),
240                            single_example("Bold", Label::new("Important Notice").weight(gpui::FontWeight::BOLD).into_any_element()),
241                            single_example("Italic", Label::new("Code Comment").italic().into_any_element()),
242                            single_example("Strikethrough", Label::new("Deprecated Feature").strikethrough().into_any_element()),
243                            single_example("Underline", Label::new("Clickable Link").underline().into_any_element()),
244                            single_example("Inline Code", Label::new("fn main() {}").inline_code(cx).into_any_element()),
245                        ],
246                    ),
247                    example_group_with_title(
248                        "Line Height Styles",
249                        vec![
250                            single_example("Default", Label::new("Multi-line\nText\nExample").into_any_element()),
251                            single_example("UI Label", Label::new("Compact\nUI\nLabel").line_height_style(LineHeightStyle::UiLabel).into_any_element()),
252                        ],
253                    ),
254                    example_group_with_title(
255                        "Special Cases",
256                        vec![
257                            single_example("Single Line", Label::new("Line 1\nLine 2\nLine 3").single_line().into_any_element()),
258                            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()),
259                        ],
260                    ),
261                ])
262                .into_any_element()
263        )
264    }
265}