styled.rs

  1use crate::TextStyleRefinement;
  2use crate::{
  3    self as gpui, px, relative, rems, AbsoluteLength, AlignItems, CursorStyle, DefiniteLength,
  4    Fill, FlexDirection, FlexWrap, Font, FontStyle, FontWeight, Hsla, JustifyContent, Length,
  5    SharedString, StyleRefinement, WhiteSpace,
  6};
  7pub use gpui_macros::{
  8    border_style_methods, box_shadow_style_methods, cursor_style_methods, margin_style_methods,
  9    overflow_style_methods, padding_style_methods, position_style_methods,
 10    visibility_style_methods,
 11};
 12use taffy::style::{AlignContent, Display};
 13
 14/// A trait for elements that can be styled.
 15/// Use this to opt-in to a CSS-like styling API.
 16pub trait Styled: Sized {
 17    /// Returns a reference to the style memory of this element.
 18    fn style(&mut self) -> &mut StyleRefinement;
 19
 20    gpui_macros::style_helpers!();
 21    gpui_macros::visibility_style_methods!();
 22    gpui_macros::margin_style_methods!();
 23    gpui_macros::padding_style_methods!();
 24    gpui_macros::position_style_methods!();
 25    gpui_macros::overflow_style_methods!();
 26    gpui_macros::cursor_style_methods!();
 27    gpui_macros::border_style_methods!();
 28    gpui_macros::box_shadow_style_methods!();
 29
 30    /// Sets the display type of the element to `block`.
 31    /// [Docs](https://tailwindcss.com/docs/display)
 32    fn block(mut self) -> Self {
 33        self.style().display = Some(Display::Block);
 34        self
 35    }
 36
 37    /// Sets the display type of the element to `flex`.
 38    /// [Docs](https://tailwindcss.com/docs/display)
 39    fn flex(mut self) -> Self {
 40        self.style().display = Some(Display::Flex);
 41        self
 42    }
 43
 44    /// Sets the whitespace of the element to `normal`.
 45    /// [Docs](https://tailwindcss.com/docs/whitespace#normal)
 46    fn whitespace_normal(mut self) -> Self {
 47        self.text_style()
 48            .get_or_insert_with(Default::default)
 49            .white_space = Some(WhiteSpace::Normal);
 50        self
 51    }
 52
 53    /// Sets the whitespace of the element to `nowrap`.
 54    /// [Docs](https://tailwindcss.com/docs/whitespace#nowrap)
 55    fn whitespace_nowrap(mut self) -> Self {
 56        self.text_style()
 57            .get_or_insert_with(Default::default)
 58            .white_space = Some(WhiteSpace::Nowrap);
 59        self
 60    }
 61
 62    /// Sets the flex direction of the element to `column`.
 63    /// [Docs](https://tailwindcss.com/docs/flex-direction#column)
 64    fn flex_col(mut self) -> Self {
 65        self.style().flex_direction = Some(FlexDirection::Column);
 66        self
 67    }
 68
 69    /// Sets the flex direction of the element to `column-reverse`.
 70    /// [Docs](https://tailwindcss.com/docs/flex-direction#column-reverse)
 71    fn flex_col_reverse(mut self) -> Self {
 72        self.style().flex_direction = Some(FlexDirection::ColumnReverse);
 73        self
 74    }
 75
 76    /// Sets the flex direction of the element to `row`.
 77    /// [Docs](https://tailwindcss.com/docs/flex-direction#row)
 78    fn flex_row(mut self) -> Self {
 79        self.style().flex_direction = Some(FlexDirection::Row);
 80        self
 81    }
 82
 83    /// Sets the flex direction of the element to `row-reverse`.
 84    /// [Docs](https://tailwindcss.com/docs/flex-direction#row-reverse)
 85    fn flex_row_reverse(mut self) -> Self {
 86        self.style().flex_direction = Some(FlexDirection::RowReverse);
 87        self
 88    }
 89
 90    /// Sets the element to allow a flex item to grow and shrink as needed, ignoring its initial size.
 91    /// [Docs](https://tailwindcss.com/docs/flex#flex-1)
 92    fn flex_1(mut self) -> Self {
 93        self.style().flex_grow = Some(1.);
 94        self.style().flex_shrink = Some(1.);
 95        self.style().flex_basis = Some(relative(0.).into());
 96        self
 97    }
 98
 99    /// Sets the element to allow a flex item to grow and shrink, taking into account its initial size.
100    /// [Docs](https://tailwindcss.com/docs/flex#auto)
101    fn flex_auto(mut self) -> Self {
102        self.style().flex_grow = Some(1.);
103        self.style().flex_shrink = Some(1.);
104        self.style().flex_basis = Some(Length::Auto);
105        self
106    }
107
108    /// Sets the element to allow a flex item to shrink but not grow, taking into account its initial size.
109    /// [Docs](https://tailwindcss.com/docs/flex#initial)
110    fn flex_initial(mut self) -> Self {
111        self.style().flex_grow = Some(0.);
112        self.style().flex_shrink = Some(1.);
113        self.style().flex_basis = Some(Length::Auto);
114        self
115    }
116
117    /// Sets the element to prevent a flex item from growing or shrinking.
118    /// [Docs](https://tailwindcss.com/docs/flex#none)
119    fn flex_none(mut self) -> Self {
120        self.style().flex_grow = Some(0.);
121        self.style().flex_shrink = Some(0.);
122        self
123    }
124
125    /// Sets the initial size of flex items for this element.
126    /// [Docs](https://tailwindcss.com/docs/flex-basis)
127    fn flex_basis(mut self, basis: impl Into<Length>) -> Self {
128        self.style().flex_basis = Some(basis.into());
129        self
130    }
131
132    /// Sets the element to allow a flex item to grow to fill any available space.
133    /// [Docs](https://tailwindcss.com/docs/flex-grow)
134    fn flex_grow(mut self) -> Self {
135        self.style().flex_grow = Some(1.);
136        self
137    }
138
139    /// Sets the element to allow a flex item to shrink if needed.
140    /// [Docs](https://tailwindcss.com/docs/flex-shrink)
141    fn flex_shrink(mut self) -> Self {
142        self.style().flex_shrink = Some(1.);
143        self
144    }
145
146    /// Sets the element to prevent a flex item from shrinking.
147    /// [Docs](https://tailwindcss.com/docs/flex-shrink#dont-shrink)
148    fn flex_shrink_0(mut self) -> Self {
149        self.style().flex_shrink = Some(0.);
150        self
151    }
152
153    /// Sets the element to allow flex items to wrap.
154    /// [Docs](https://tailwindcss.com/docs/flex-wrap#wrap-normally)
155    fn flex_wrap(mut self) -> Self {
156        self.style().flex_wrap = Some(FlexWrap::Wrap);
157        self
158    }
159
160    /// Sets the element wrap flex items in the reverse direction.
161    /// [Docs](https://tailwindcss.com/docs/flex-wrap#wrap-reversed)
162    fn flex_wrap_reverse(mut self) -> Self {
163        self.style().flex_wrap = Some(FlexWrap::WrapReverse);
164        self
165    }
166
167    /// Sets the element to prevent flex items from wrapping, causing inflexible items to overflow the container if necessary.
168    /// [Docs](https://tailwindcss.com/docs/flex-wrap#dont-wrap)
169    fn flex_nowrap(mut self) -> Self {
170        self.style().flex_wrap = Some(FlexWrap::NoWrap);
171        self
172    }
173
174    /// Sets the element to align flex items to the start of the container's cross axis.
175    /// [Docs](https://tailwindcss.com/docs/align-items#start)
176    fn items_start(mut self) -> Self {
177        self.style().align_items = Some(AlignItems::FlexStart);
178        self
179    }
180
181    /// Sets the element to align flex items to the end of the container's cross axis.
182    /// [Docs](https://tailwindcss.com/docs/align-items#end)
183    fn items_end(mut self) -> Self {
184        self.style().align_items = Some(AlignItems::FlexEnd);
185        self
186    }
187
188    /// Sets the element to align flex items along the center of the container's cross axis.
189    /// [Docs](https://tailwindcss.com/docs/align-items#center)
190    fn items_center(mut self) -> Self {
191        self.style().align_items = Some(AlignItems::Center);
192        self
193    }
194
195    /// Sets the element to align flex items along the baseline of the container's cross axis.
196    /// [Docs](https://tailwindcss.com/docs/align-items#baseline)
197    fn items_baseline(mut self) -> Self {
198        self.style().align_items = Some(AlignItems::Baseline);
199        self
200    }
201
202    /// Sets the element to justify flex items against the start of the container's main axis.
203    /// [Docs](https://tailwindcss.com/docs/justify-content#start)
204    fn justify_start(mut self) -> Self {
205        self.style().justify_content = Some(JustifyContent::Start);
206        self
207    }
208
209    /// Sets the element to justify flex items against the end of the container's main axis.
210    /// [Docs](https://tailwindcss.com/docs/justify-content#end)
211    fn justify_end(mut self) -> Self {
212        self.style().justify_content = Some(JustifyContent::End);
213        self
214    }
215
216    /// Sets the element to justify flex items along the center of the container's main axis.
217    /// [Docs](https://tailwindcss.com/docs/justify-content#center)
218    fn justify_center(mut self) -> Self {
219        self.style().justify_content = Some(JustifyContent::Center);
220        self
221    }
222
223    /// Sets the element to justify flex items along the container's main axis
224    /// such that there is an equal amount of space between each item.
225    /// [Docs](https://tailwindcss.com/docs/justify-content#space-between)
226    fn justify_between(mut self) -> Self {
227        self.style().justify_content = Some(JustifyContent::SpaceBetween);
228        self
229    }
230
231    /// Sets the element to justify items along the container's main axis such
232    /// that there is an equal amount of space on each side of each item.
233    /// [Docs](https://tailwindcss.com/docs/justify-content#space-around)
234    fn justify_around(mut self) -> Self {
235        self.style().justify_content = Some(JustifyContent::SpaceAround);
236        self
237    }
238
239    /// Sets the element to pack content items in their default position as if no align-content value was set.
240    /// [Docs](https://tailwindcss.com/docs/align-content#normal)
241    fn content_normal(mut self) -> Self {
242        self.style().align_content = None;
243        self
244    }
245
246    /// Sets the element to pack content items in the center of the container's cross axis.
247    /// [Docs](https://tailwindcss.com/docs/align-content#center)
248    fn content_center(mut self) -> Self {
249        self.style().align_content = Some(AlignContent::Center);
250        self
251    }
252
253    /// Sets the element to pack content items against the start of the container's cross axis.
254    /// [Docs](https://tailwindcss.com/docs/align-content#start)
255    fn content_start(mut self) -> Self {
256        self.style().align_content = Some(AlignContent::FlexStart);
257        self
258    }
259
260    /// Sets the element to pack content items against the end of the container's cross axis.
261    /// [Docs](https://tailwindcss.com/docs/align-content#end)
262    fn content_end(mut self) -> Self {
263        self.style().align_content = Some(AlignContent::FlexEnd);
264        self
265    }
266
267    /// Sets the element to pack content items along the container's cross axis
268    /// such that there is an equal amount of space between each item.
269    /// [Docs](https://tailwindcss.com/docs/align-content#space-between)
270    fn content_between(mut self) -> Self {
271        self.style().align_content = Some(AlignContent::SpaceBetween);
272        self
273    }
274
275    /// Sets the element to pack content items along the container's cross axis
276    /// such that there is an equal amount of space on each side of each item.
277    /// [Docs](https://tailwindcss.com/docs/align-content#space-around)
278    fn content_around(mut self) -> Self {
279        self.style().align_content = Some(AlignContent::SpaceAround);
280        self
281    }
282
283    /// Sets the element to pack content items along the container's cross axis
284    /// such that there is an equal amount of space between each item.
285    /// [Docs](https://tailwindcss.com/docs/align-content#space-evenly)
286    fn content_evenly(mut self) -> Self {
287        self.style().align_content = Some(AlignContent::SpaceEvenly);
288        self
289    }
290
291    /// Sets the element to allow content items to fill the available space along the container's cross axis.
292    /// [Docs](https://tailwindcss.com/docs/align-content#stretch)
293    fn content_stretch(mut self) -> Self {
294        self.style().align_content = Some(AlignContent::Stretch);
295        self
296    }
297
298    /// Sets the background color of the element.
299    fn bg<F>(mut self, fill: F) -> Self
300    where
301        F: Into<Fill>,
302        Self: Sized,
303    {
304        self.style().background = Some(fill.into());
305        self
306    }
307
308    /// Get the text style that has been configured on this element.
309    fn text_style(&mut self) -> &mut Option<TextStyleRefinement> {
310        let style: &mut StyleRefinement = self.style();
311        &mut style.text
312    }
313
314    /// Set the text color of this element, this value cascades to its child elements.
315    fn text_color(mut self, color: impl Into<Hsla>) -> Self {
316        self.text_style().get_or_insert_with(Default::default).color = Some(color.into());
317        self
318    }
319
320    /// Set the font weight of this element, this value cascades to its child elements.
321    fn font_weight(mut self, weight: FontWeight) -> Self {
322        self.text_style()
323            .get_or_insert_with(Default::default)
324            .font_weight = Some(weight);
325        self
326    }
327
328    /// Set the background color of this element, this value cascades to its child elements.
329    fn text_bg(mut self, bg: impl Into<Hsla>) -> Self {
330        self.text_style()
331            .get_or_insert_with(Default::default)
332            .background_color = Some(bg.into());
333        self
334    }
335
336    /// Set the text size of this element, this value cascades to its child elements.
337    fn text_size(mut self, size: impl Into<AbsoluteLength>) -> Self {
338        self.text_style()
339            .get_or_insert_with(Default::default)
340            .font_size = Some(size.into());
341        self
342    }
343
344    /// Set the text size to 'extra small',
345    /// see the [Tailwind Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
346    fn text_xs(mut self) -> Self {
347        self.text_style()
348            .get_or_insert_with(Default::default)
349            .font_size = Some(rems(0.75).into());
350        self
351    }
352
353    /// Set the text size to 'small',
354    /// see the [Tailwind Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
355    fn text_sm(mut self) -> Self {
356        self.text_style()
357            .get_or_insert_with(Default::default)
358            .font_size = Some(rems(0.875).into());
359        self
360    }
361
362    /// Reset the text styling for this element and its children.
363    fn text_base(mut self) -> Self {
364        self.text_style()
365            .get_or_insert_with(Default::default)
366            .font_size = Some(rems(1.0).into());
367        self
368    }
369
370    /// Set the text size to 'large',
371    /// see the [Tailwind Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
372    fn text_lg(mut self) -> Self {
373        self.text_style()
374            .get_or_insert_with(Default::default)
375            .font_size = Some(rems(1.125).into());
376        self
377    }
378
379    /// Set the text size to 'extra large',
380    /// see the [Tailwind Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
381    fn text_xl(mut self) -> Self {
382        self.text_style()
383            .get_or_insert_with(Default::default)
384            .font_size = Some(rems(1.25).into());
385        self
386    }
387
388    /// Set the text size to 'extra-extra large',
389    /// see the [Tailwind Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
390    fn text_2xl(mut self) -> Self {
391        self.text_style()
392            .get_or_insert_with(Default::default)
393            .font_size = Some(rems(1.5).into());
394        self
395    }
396
397    /// Set the text size to 'extra-extra-extra large',
398    /// see the [Tailwind Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
399    fn text_3xl(mut self) -> Self {
400        self.text_style()
401            .get_or_insert_with(Default::default)
402            .font_size = Some(rems(1.875).into());
403        self
404    }
405
406    /// Set the font style to 'non-italic',
407    /// see the [Tailwind Docs](https://tailwindcss.com/docs/font-style#italicizing-text)
408    fn non_italic(mut self) -> Self {
409        self.text_style()
410            .get_or_insert_with(Default::default)
411            .font_style = Some(FontStyle::Normal);
412        self
413    }
414
415    /// Set the font style to 'italic',
416    /// see the [Tailwind Docs](https://tailwindcss.com/docs/font-style#italicizing-text)
417    fn italic(mut self) -> Self {
418        self.text_style()
419            .get_or_insert_with(Default::default)
420            .font_style = Some(FontStyle::Italic);
421        self
422    }
423
424    /// Remove the text decoration on this element, this value cascades to its child elements.
425    fn text_decoration_none(mut self) -> Self {
426        self.text_style()
427            .get_or_insert_with(Default::default)
428            .underline = None;
429        self
430    }
431
432    /// Set the color for the underline on this element
433    fn text_decoration_color(mut self, color: impl Into<Hsla>) -> Self {
434        let style = self.text_style().get_or_insert_with(Default::default);
435        let underline = style.underline.get_or_insert_with(Default::default);
436        underline.color = Some(color.into());
437        self
438    }
439
440    /// Set the underline to a solid line
441    fn text_decoration_solid(mut self) -> Self {
442        let style = self.text_style().get_or_insert_with(Default::default);
443        let underline = style.underline.get_or_insert_with(Default::default);
444        underline.wavy = false;
445        self
446    }
447
448    /// Set the underline to a wavy line
449    fn text_decoration_wavy(mut self) -> Self {
450        let style = self.text_style().get_or_insert_with(Default::default);
451        let underline = style.underline.get_or_insert_with(Default::default);
452        underline.wavy = true;
453        self
454    }
455
456    /// Set the underline to be 0 thickness, see the [Tailwind Docs](https://tailwindcss.com/docs/text-decoration-thickness)
457    fn text_decoration_0(mut self) -> Self {
458        let style = self.text_style().get_or_insert_with(Default::default);
459        let underline = style.underline.get_or_insert_with(Default::default);
460        underline.thickness = px(0.);
461        self
462    }
463
464    /// Set the underline to be 1px thick, see the [Tailwind Docs](https://tailwindcss.com/docs/text-decoration-thickness)
465    fn text_decoration_1(mut self) -> Self {
466        let style = self.text_style().get_or_insert_with(Default::default);
467        let underline = style.underline.get_or_insert_with(Default::default);
468        underline.thickness = px(1.);
469        self
470    }
471
472    /// Set the underline to be 2px thick, see the [Tailwind Docs](https://tailwindcss.com/docs/text-decoration-thickness)
473    fn text_decoration_2(mut self) -> Self {
474        let style = self.text_style().get_or_insert_with(Default::default);
475        let underline = style.underline.get_or_insert_with(Default::default);
476        underline.thickness = px(2.);
477        self
478    }
479
480    /// Set the underline to be 4px thick, see the [Tailwind Docs](https://tailwindcss.com/docs/text-decoration-thickness)
481    fn text_decoration_4(mut self) -> Self {
482        let style = self.text_style().get_or_insert_with(Default::default);
483        let underline = style.underline.get_or_insert_with(Default::default);
484        underline.thickness = px(4.);
485        self
486    }
487
488    /// Set the underline to be 8px thick, see the [Tailwind Docs](https://tailwindcss.com/docs/text-decoration-thickness)
489    fn text_decoration_8(mut self) -> Self {
490        let style = self.text_style().get_or_insert_with(Default::default);
491        let underline = style.underline.get_or_insert_with(Default::default);
492        underline.thickness = px(8.);
493        self
494    }
495
496    /// Change the font family on this element and its children.
497    fn font_family(mut self, family_name: impl Into<SharedString>) -> Self {
498        self.text_style()
499            .get_or_insert_with(Default::default)
500            .font_family = Some(family_name.into());
501        self
502    }
503
504    /// Change the font of this element and its children.
505    fn font(mut self, font: Font) -> Self {
506        let Font {
507            family,
508            features,
509            weight,
510            style,
511        } = font;
512
513        let text_style = self.text_style().get_or_insert_with(Default::default);
514        text_style.font_family = Some(family);
515        text_style.font_features = Some(features);
516        text_style.font_weight = Some(weight);
517        text_style.font_style = Some(style);
518
519        self
520    }
521
522    /// Set the line height on this element and its children.
523    fn line_height(mut self, line_height: impl Into<DefiniteLength>) -> Self {
524        self.text_style()
525            .get_or_insert_with(Default::default)
526            .line_height = Some(line_height.into());
527        self
528    }
529
530    /// Draw a debug border around this element.
531    #[cfg(debug_assertions)]
532    fn debug(mut self) -> Self {
533        self.style().debug = Some(true);
534        self
535    }
536
537    /// Draw a debug border on all conforming elements below this element.
538    #[cfg(debug_assertions)]
539    fn debug_below(mut self) -> Self {
540        self.style().debug_below = Some(true);
541        self
542    }
543}