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