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, IntoComponent)]
 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
 56// nate: If we are going to do this, we might as well just
 57// impl Styled for Label and not constrain styles
 58
 59// Style methods.
 60impl Label {
 61    fn style(&mut self) -> &mut StyleRefinement {
 62        self.base.base.style()
 63    }
 64
 65    gpui::margin_style_methods!({
 66        visibility: pub
 67    });
 68}
 69
 70impl LabelCommon for Label {
 71    /// Sets the size of the label using a [`LabelSize`].
 72    ///
 73    /// # Examples
 74    ///
 75    /// ```
 76    /// use ui::prelude::*;
 77    ///
 78    /// let my_label = Label::new("Hello, World!").size(LabelSize::Small);
 79    /// ```
 80    fn size(mut self, size: LabelSize) -> Self {
 81        self.base = self.base.size(size);
 82        self
 83    }
 84
 85    /// Sets the weight of the label using a [`FontWeight`].
 86    ///
 87    /// # Examples
 88    ///
 89    /// ```
 90    /// use ui::prelude::*;
 91    ///
 92    /// let my_label = Label::new("Hello, World!").weight(FontWeight::Bold);
 93    /// ```
 94    fn weight(mut self, weight: gpui::FontWeight) -> Self {
 95        self.base = self.base.weight(weight);
 96        self
 97    }
 98
 99    /// Sets the line height style of the label using a [`LineHeightStyle`].
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use ui::prelude::*;
105    ///
106    /// let my_label = Label::new("Hello, World!").line_height_style(LineHeightStyle::UiLabel);
107    /// ```
108    fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
109        self.base = self.base.line_height_style(line_height_style);
110        self
111    }
112
113    /// Sets the color of the label using a [`Color`].
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// use ui::prelude::*;
119    ///
120    /// let my_label = Label::new("Hello, World!").color(Color::Accent);
121    /// ```
122    fn color(mut self, color: Color) -> Self {
123        self.base = self.base.color(color);
124        self
125    }
126
127    /// Sets the strikethrough property of the label.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use ui::prelude::*;
133    ///
134    /// let my_label = Label::new("Hello, World!").strikethrough(true);
135    /// ```
136    fn strikethrough(mut self) -> Self {
137        self.base = self.base.strikethrough();
138        self
139    }
140
141    /// Sets the italic property of the label.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// use ui::prelude::*;
147    ///
148    /// let my_label = Label::new("Hello, World!").italic(true);
149    /// ```
150    fn italic(mut self) -> Self {
151        self.base = self.base.italic();
152        self
153    }
154
155    /// Sets the alpha property of the color of label.
156    ///
157    /// # Examples
158    ///
159    /// ```
160    /// use ui::prelude::*;
161    ///
162    /// let my_label = Label::new("Hello, World!").alpha(0.5);
163    /// ```
164    fn alpha(mut self, alpha: f32) -> Self {
165        self.base = self.base.alpha(alpha);
166        self
167    }
168
169    fn underline(mut self) -> Self {
170        self.base = self.base.underline();
171        self
172    }
173
174    /// Truncates overflowing text with an ellipsis (`…`) if needed.
175    fn truncate(mut self) -> Self {
176        self.base = self.base.truncate();
177        self
178    }
179
180    fn single_line(mut self) -> Self {
181        self.label = SharedString::from(self.label.replace('\n', ""));
182        self.base = self.base.single_line();
183        self
184    }
185
186    fn buffer_font(mut self, cx: &App) -> Self {
187        self.base = self.base.buffer_font(cx);
188        self
189    }
190}
191
192impl RenderOnce for Label {
193    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
194        self.base.child(self.label)
195    }
196}
197
198mod label_preview {
199    use crate::prelude::*;
200
201    // View this component preview using `workspace: open component-preview`
202    impl ComponentPreview for Label {
203        fn preview(_window: &mut Window, _cx: &mut App) -> AnyElement {
204            v_flex()
205                .gap_6()
206                .children(vec![
207                    example_group_with_title(
208                        "Sizes",
209                        vec![
210                            single_example("Default", Label::new("Project Explorer").into_any_element()),
211                            single_example("Small", Label::new("File: main.rs").size(LabelSize::Small).into_any_element()),
212                            single_example("Large", Label::new("Welcome to Zed").size(LabelSize::Large).into_any_element()),
213                        ],
214                    ),
215                    example_group_with_title(
216                        "Colors",
217                        vec![
218                            single_example("Default", Label::new("Status: Ready").into_any_element()),
219                            single_example("Accent", Label::new("New Update Available").color(Color::Accent).into_any_element()),
220                            single_example("Error", Label::new("Build Failed").color(Color::Error).into_any_element()),
221                        ],
222                    ),
223                    example_group_with_title(
224                        "Styles",
225                        vec![
226                            single_example("Default", Label::new("Normal Text").into_any_element()),
227                            single_example("Bold", Label::new("Important Notice").weight(gpui::FontWeight::BOLD).into_any_element()),
228                            single_example("Italic", Label::new("Code Comment").italic().into_any_element()),
229                            single_example("Strikethrough", Label::new("Deprecated Feature").strikethrough().into_any_element()),
230                            single_example("Underline", Label::new("Clickable Link").underline().into_any_element()),
231                        ],
232                    ),
233                    example_group_with_title(
234                        "Line Height Styles",
235                        vec![
236                            single_example("Default", Label::new("Multi-line\nText\nExample").into_any_element()),
237                            single_example("UI Label", Label::new("Compact\nUI\nLabel").line_height_style(LineHeightStyle::UiLabel).into_any_element()),
238                        ],
239                    ),
240                    example_group_with_title(
241                        "Special Cases",
242                        vec![
243                            single_example("Single Line", Label::new("Line 1\nLine 2\nLine 3").single_line().into_any_element()),
244                            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()),
245                        ],
246                    ),
247                ])
248                .into_any_element()
249        }
250    }
251}