gpui/styled.rs
1use crate::{
2 self as gpui, AbsoluteLength, AlignContent, AlignItems, AlignSelf, BorderStyle, CursorStyle,
3 DefiniteLength, Display, Edges, Fill, Filter, FlexDirection, FlexWrap, Font, FontFeatures,
4 FontStyle, FontWeight, FontWidth, GridPlacement, GridTemplate, GridTemplateMinSize,
5 JustifyContent, LayoutDirection, Length, Pixels, SharedString, StrikethroughStyle,
6 StyleRefinement, TextAlign, TextOverflow, TextStyleRefinement, TextTransform, UnderlineStyle,
7 UnicodeBidi, VerticalAlign, WhiteSpace, px, relative, rems,
8};
9pub use gpui_macros::{
10 border_style_methods, box_shadow_style_methods, cursor_style_methods, margin_style_methods,
11 overflow_style_methods, padding_style_methods, position_style_methods,
12 visibility_style_methods,
13};
14use palette::{Hsla, IntoColor};
15use refineable::Refineable;
16const ELLIPSIS: SharedString = SharedString::new_static("…");
17
18/// Sets an element's layout, paint and text properties.
19///
20/// Import the prelude to style an element with method calls. Setters return `Self`, allowing
21/// several choices in one expression. This card uses a column flex layout, padding, rounded
22/// corners and a shadow:
23///
24/// ```
25/// use gpui::{Display, div, prelude::*, rgb};
26///
27/// let mut card = div()
28/// .flex()
29/// .flex_col()
30/// .gap_2()
31/// .p_4()
32/// .rounded_lg()
33/// .bg(rgb(0xffffff))
34/// .shadow_md();
35///
36/// assert_eq!(card.style().display, Some(Display::Flex));
37/// ```
38///
39/// Each call writes to the element's [`StyleRefinement`]. Unset properties fall back to
40/// [`Style`](crate::Style)'s defaults. Setting the same property again normally replaces its
41/// earlier value; an additive setter such as [`Styled::blur`] documents its exception.
42/// Interaction styles use refinements too: [`hover`](crate::InteractiveElement::hover) passes
43/// an empty refinement to a closure, where these methods describe the changes for that state.
44///
45/// Setters record a request rather than measuring the element. Layout resolves `size`,
46/// `min_size`, `max_size` and percentages within the containing layout; painting then uses
47/// the resulting bounds. The [layout and style concept](crate::_documentation::concepts::layout_and_style)
48/// explains why a requested size can differ from the final size.
49///
50/// # Naming scale
51///
52/// Names generally follow Tailwind CSS. Spacing, sizing and radius suffixes use a quarter-rem
53/// scale: `p_4` is 1rem of padding, and `gap_2` is a 0.5rem gap. At the default 16px root size,
54/// those lengths are 16px and 8px. The common steps are:
55///
56/// | Suffix | Length | Pixels at the default rem size |
57/// | --- | --- | --- |
58/// | `0` | `0` | 0px |
59/// | `0p5` | `0.125rem` | 2px |
60/// | `1` | `0.25rem` | 4px |
61/// | `2` | `0.5rem` | 8px |
62/// | `4` | `1rem` | 16px |
63/// | `8` | `2rem` | 32px |
64/// | `16` | `4rem` | 64px |
65/// | `px` | `1px` | 1px |
66///
67/// A `p` inside a number denotes a decimal point: `p_1p5` is `0.375rem`. Fraction suffixes
68/// such as `_1_2` and `_1_3` use a percentage of the containing layout size on that axis.
69/// `full` means 100% for a size or the largest radius for a corner. Where allowed, `auto`
70/// leaves the choice to layout. Each method lists its available values.
71///
72/// Font sizes have their own scale, from [`Styled::text_xs`] (`0.75rem`) to
73/// [`Styled::text_3xl`] (`1.875rem`). For instance, `text_sm` is `0.875rem`, or 14px at the
74/// default root size. [`Window::set_rem_size`](crate::Window::set_rem_size) changes that
75/// root, scaling both these fonts and rem-based spacing.
76// Avoid expanding the large reflection macro while rust-analyzer indexes this trait.
77#[cfg_attr(
78 all(any(feature = "inspector", debug_assertions), not(rust_analyzer)),
79 gpui_macros::derive_inspector_reflection
80)]
81pub trait Styled: Sized {
82 /// Returns the [`StyleRefinement`] that the methods on this trait write into.
83 ///
84 /// Use this when you need to set a property that has no dedicated method. Each element stores its
85 /// own refinement, so changes here affect only this element. The refinement is merged over
86 /// [`Style`](crate::Style)'s defaults when the element is laid out and painted; an unset field does
87 /// not clear the corresponding default.
88 fn style(&mut self) -> &mut StyleRefinement;
89
90 /// Applies every property set in `refinement` to this element's style.
91 ///
92 /// Unset properties keep their current values. Nested refinements merge field by field too:
93 /// setting a text color does not clear the font weight. Apply shared styles first and specific
94 /// overrides afterward so the latter values win.
95 fn refine_style(mut self, refinement: &StyleRefinement) -> Self {
96 self.style().refine(refinement);
97
98 self
99 }
100
101 gpui_macros::style_helpers!();
102 gpui_macros::visibility_style_methods!();
103 gpui_macros::margin_style_methods!();
104 gpui_macros::padding_style_methods!();
105 gpui_macros::position_style_methods!();
106 gpui_macros::overflow_style_methods!();
107 gpui_macros::cursor_style_methods!();
108 gpui_macros::border_style_methods!();
109 gpui_macros::box_shadow_style_methods!();
110
111 /// Sets the inline direction of this element and its logical descendants.
112 ///
113 /// The direction is inherited by descendants and is used by logical inline-start/end layout. It
114 /// does not rewrite physical `left` and `right` properties. Prefer [`Styled::rtl`] or
115 /// [`Styled::ltr`] unless you need to pass a runtime [`LayoutDirection`].
116 fn direction(mut self, direction: LayoutDirection) -> Self {
117 self.style().direction = Some(direction);
118
119 self
120 }
121
122 /// Lays out this element and its logical descendants right to left.
123 ///
124 /// Use it for right-to-left languages such as Arabic and Hebrew. Descendants inherit this
125 /// direction until they set another one; physical left/right properties keep their physical
126 /// meaning. See the [layout and style](crate::_documentation::concepts::layout_and_style) page.
127 fn rtl(self) -> Self {
128 self.direction(LayoutDirection::RightToLeft)
129 }
130
131 /// Lays out this element and its logical descendants left to right.
132 ///
133 /// Use it to restore left-to-right layout inside an element that is set to [`Styled::rtl`].
134 /// Elements otherwise inherit their direction, whose resolved default is left to right.
135 fn ltr(self) -> Self {
136 self.direction(LayoutDirection::LeftToRight)
137 }
138
139 /// Sets how this element's text takes part in the Unicode bidirectional algorithm.
140 ///
141 /// Setting a value marks the property as explicit, so it overrides the default
142 /// behavior that GPUI applies otherwise.
143 fn unicode_bidi(mut self, unicode_bidi: UnicodeBidi) -> Self {
144 let style = self.style();
145 style.unicode_bidi = Some(unicode_bidi);
146 style.unicode_bidi_explicit = Some(true);
147
148 self
149 }
150
151 /// Blurs this element's own content and children, like CSS `filter: blur(<radius>)`.
152 ///
153 /// The radius is in logical pixels. This isolates the element's subtree, blurs it as
154 /// a group, and composites the result back. To blur the content behind the element
155 /// instead, use [`Styled::backdrop_blur`].
156 ///
157 /// This adds to the element's filter chain, so `.blur(8.)` composes with the other filter setters.
158 /// A later [`Styled::filter`] call replaces the chain accumulated so far; call `filter` first if
159 /// you want to append a blur afterward.
160 fn blur(mut self, radius: impl Into<Pixels>) -> Self {
161 self.style()
162 .filter
163 .get_or_insert_with(Vec::new)
164 .push(Filter::Blur(radius.into()));
165 self
166 }
167
168 /// Replaces the list of filters applied to this element's own content, like CSS `filter`.
169 ///
170 /// Any filters set before this call are discarded. To add one filter to the chain,
171 /// use a convenience setter such as [`Styled::blur`].
172 fn filter(mut self, filters: impl Into<Vec<Filter>>) -> Self {
173 self.style().filter = Some(filters.into());
174 self
175 }
176
177 /// Blurs the content behind this element, like CSS `backdrop-filter: blur(<radius>)`.
178 ///
179 /// The radius is in logical pixels. Pair it with a translucent [`Styled::bg`] so the
180 /// background tints the blurred content and the result looks like frosted glass.
181 ///
182 /// This adds to the element's backdrop filter chain. A later [`Styled::backdrop_filter`] call
183 /// replaces the chain accumulated so far; call `backdrop_filter` first if you want to append a
184 /// blur afterward.
185 fn backdrop_blur(mut self, radius: impl Into<Pixels>) -> Self {
186 self.style()
187 .backdrop_filter
188 .get_or_insert_with(Vec::new)
189 .push(Filter::Blur(radius.into()));
190 self
191 }
192
193 /// Replaces the list of filters applied to the content behind this element, like CSS `backdrop-filter`.
194 ///
195 /// Any backdrop filters set before this call are discarded. To add one filter to the
196 /// chain, use a convenience setter such as [`Styled::backdrop_blur`].
197 fn backdrop_filter(mut self, filters: impl Into<Vec<Filter>>) -> Self {
198 self.style().backdrop_filter = Some(filters.into());
199 self
200 }
201
202 /// Sets the display type of this element.
203 ///
204 /// The display type chooses the layout algorithm for the element's children. See
205 /// [`Display`] for the values.
206 fn display(mut self, display: Display) -> Self {
207 self.style().display = Some(display);
208 self
209 }
210
211 /// Sets the display type of this element to `block`.
212 ///
213 /// [Docs](https://tailwindcss.com/docs/display)
214 fn block(self) -> Self {
215 self.display(Display::Block)
216 }
217
218 /// Sets the display type of this element to `flex`.
219 ///
220 /// Its children lay out in a row by default. Use [`Styled::flex_col`] for a column.
221 ///
222 /// [Docs](https://tailwindcss.com/docs/display)
223 fn flex(self) -> Self {
224 self.display(Display::Flex)
225 }
226
227 /// Sets the display type of this element to `grid`.
228 ///
229 /// Children are placed in rows and columns. Choose the column count with
230 /// [`Styled::grid_cols`].
231 ///
232 /// [Docs](https://tailwindcss.com/docs/display)
233 fn grid(self) -> Self {
234 self.display(Display::Grid)
235 }
236
237 /// Places this element in its parent's inline formatting context as an inline box.
238 ///
239 /// Its content participates in the surrounding line layout instead of creating a block box;
240 /// whitespace and line breaks still come from the content and its surrounding layout.
241 fn inline(self) -> Self {
242 self.display(Display::Inline)
243 }
244
245 /// Places this element in its parent's paragraph as one atomic box with flex layout inside.
246 fn inline_flex(self) -> Self {
247 self.display(Display::InlineFlex)
248 }
249
250 /// Sets how this element aligns when it is placed in an inline layout.
251 ///
252 /// Use it for elements that take part in text flow, such as inline boxes inside a
253 /// paragraph. For flex and grid alignment, use [`Styled::items_center`] or
254 /// [`Styled::self_center`].
255 fn vertical_align(mut self, align: VerticalAlign) -> Self {
256 self.style().vertical_align = Some(align);
257 self
258 }
259
260 /// Aligns this inline box with the surrounding text baseline.
261 fn align_baseline(self) -> Self {
262 self.vertical_align(VerticalAlign::Baseline)
263 }
264
265 /// Aligns this inline box's midpoint with the parent baseline plus half its font's x-height.
266 ///
267 /// This is CSS `vertical-align: middle`. For flex or grid centering, use
268 /// [`Styled::self_center`] on the item or [`Styled::items_center`] on its container.
269 fn align_middle(self) -> Self {
270 self.vertical_align(VerticalAlign::Middle)
271 }
272
273 /// Aligns this inline box with the top of its line.
274 fn align_top(self) -> Self {
275 self.vertical_align(VerticalAlign::Top)
276 }
277
278 /// Aligns this inline box with the bottom of its line.
279 fn align_bottom(self) -> Self {
280 self.vertical_align(VerticalAlign::Bottom)
281 }
282
283 /// Sets the display type of this element to `none`, which removes it from layout and painting.
284 ///
285 /// Its children are removed too. Use [`Styled::invisible`] to keep the space the
286 /// element would take.
287 ///
288 /// [Docs](https://tailwindcss.com/docs/display)
289 fn hidden(self) -> Self {
290 self.display(Display::None)
291 }
292
293 /// Sets the space reserved for the scrollbar, in logical pixels or rems.
294 ///
295 /// The space affects layout only when the element's overflow is [`Overflow::Scroll`](crate::Overflow::Scroll).
296 fn scrollbar_width(mut self, width: impl Into<AbsoluteLength>) -> Self {
297 self.style().scrollbar_width = Some(width.into());
298 self
299 }
300
301 /// Fades the content clipped by this element's overflow to transparent at each edge.
302 ///
303 /// Each value is the distance over which the content fades as it approaches the
304 /// corresponding clipped edge, similar to CSS `mask-image: linear-gradient(...)`.
305 /// Use [`Edges`] to set the four edges separately.
306 fn overflow_fade(mut self, fade: impl Into<Edges<AbsoluteLength>>) -> Self {
307 let fade = fade.into();
308 let overflow_fade = &mut self.style().overflow_fade;
309 overflow_fade.top = Some(fade.top);
310 overflow_fade.right = Some(fade.right);
311 overflow_fade.bottom = Some(fade.bottom);
312 overflow_fade.left = Some(fade.left);
313 self
314 }
315
316 /// Fades content at the left and right overflow edges by the same distance.
317 ///
318 /// This clears any fade set on the top and bottom edges.
319 fn overflow_fade_x(self, fade: impl Into<AbsoluteLength>) -> Self {
320 self.overflow_fade(Edges::horizontal(fade.into()))
321 }
322
323 /// Fades content at the top and bottom overflow edges by the same distance.
324 ///
325 /// This clears any fade set on the left and right edges.
326 fn overflow_fade_y(self, fade: impl Into<AbsoluteLength>) -> Self {
327 self.overflow_fade(Edges::vertical(fade.into()))
328 }
329
330 /// Sets how this element's text handles whitespace and wrapping.
331 fn whitespace(mut self, white_space: WhiteSpace) -> Self {
332 self.text_style().white_space = Some(white_space);
333 self
334 }
335
336 /// Sets the whitespace of this element's text to `normal`, so text wraps at the available width.
337 ///
338 /// [Docs](https://tailwindcss.com/docs/whitespace#normal)
339 fn whitespace_normal(mut self) -> Self {
340 self.text_style().white_space = Some(WhiteSpace::Normal);
341 self
342 }
343
344 /// Sets the whitespace of this element's text to `nowrap`, so text stays on one line.
345 ///
346 /// [Docs](https://tailwindcss.com/docs/whitespace#nowrap)
347 fn whitespace_nowrap(mut self) -> Self {
348 self.text_style().white_space = Some(WhiteSpace::Nowrap);
349 self
350 }
351
352 /// Truncates overflowing text with an ellipsis (…) at the end.
353 ///
354 /// This sets the overflow mode; pair it with [`Styled::overflow_hidden`] and
355 /// [`Styled::whitespace_nowrap`] when you want a single clipped line. [`Styled::truncate`]
356 /// applies all three settings.
357 ///
358 /// [Docs](https://tailwindcss.com/docs/text-overflow#ellipsis)
359 fn text_ellipsis(mut self) -> Self {
360 self.text_style().text_overflow = Some(TextOverflow::Truncate(ELLIPSIS));
361 self
362 }
363
364 /// Truncates overflowing text with an ellipsis (…) at the start.
365 ///
366 /// This sets the overflow mode; pair it with [`Styled::overflow_hidden`] and
367 /// [`Styled::whitespace_nowrap`] when you want a single clipped line. Use it for file paths,
368 /// where the end matters more than the beginning.
369 /// This doesn't exist in Tailwind CSS.
370 fn text_ellipsis_start(mut self) -> Self {
371 self.text_style().text_overflow = Some(TextOverflow::TruncateStart(ELLIPSIS));
372 self
373 }
374
375 /// Truncates overflowing text with an ellipsis (…) in the middle.
376 ///
377 /// The beginning and end of the text stay visible. Pair it with
378 /// [`Styled::overflow_hidden`] and [`Styled::whitespace_nowrap`] for a single clipped line.
379 /// It is useful for file names.
380 /// This doesn't exist in Tailwind CSS.
381 fn text_ellipsis_middle(mut self) -> Self {
382 self.text_style().text_overflow = Some(TextOverflow::TruncateMiddle(ELLIPSIS));
383 self
384 }
385
386 /// Sets how this element's text is truncated when it overflows.
387 ///
388 /// See [`TextOverflow`] for the values.
389 fn text_overflow(mut self, overflow: TextOverflow) -> Self {
390 self.text_style().text_overflow = Some(overflow);
391 self
392 }
393
394 /// Sets the horizontal alignment of this element's text.
395 fn text_align(mut self, align: TextAlign) -> Self {
396 self.text_style().text_align = Some(align);
397 self
398 }
399
400 /// Aligns text to the start edge of each line, which is the left edge in left-to-right text.
401 fn text_start(self) -> Self {
402 self.text_align(TextAlign::Start)
403 }
404
405 /// Aligns text to the end edge of each line, which is the right edge in left-to-right text.
406 fn text_end(self) -> Self {
407 self.text_align(TextAlign::End)
408 }
409
410 /// Aligns text to the left edge.
411 fn text_left(mut self) -> Self {
412 self.text_align(TextAlign::Left)
413 }
414
415 /// Centers text horizontally.
416 fn text_center(mut self) -> Self {
417 self.text_align(TextAlign::Center)
418 }
419
420 /// Aligns text to the right edge.
421 fn text_right(mut self) -> Self {
422 self.text_align(TextAlign::Right)
423 }
424
425 /// Sets the space between letters in this element and its children, in logical pixels.
426 fn letter_spacing(mut self, spacing: impl Into<Pixels>) -> Self {
427 self.text_style().letter_spacing = Some(spacing.into());
428 self
429 }
430
431 /// Sets the case transformation for text in this element and its children.
432 fn text_transform(mut self, transform: TextTransform) -> Self {
433 self.text_style().text_transform = Some(transform);
434 self
435 }
436
437 /// Prevents text from wrapping and truncates overflowing text with an ellipsis (…) at the end.
438 ///
439 /// This sets [`Styled::overflow_hidden`], [`Styled::whitespace_nowrap`] and
440 /// [`Styled::text_ellipsis`].
441 ///
442 /// [Docs](https://tailwindcss.com/docs/text-overflow#truncate)
443 fn truncate(mut self) -> Self {
444 self.overflow_hidden().whitespace_nowrap().text_ellipsis()
445 }
446
447 /// Shows at most `lines` lines of text, then truncates the rest.
448 ///
449 /// This also sets [`Styled::overflow_hidden`].
450 ///
451 /// [Docs](https://tailwindcss.com/docs/line-clamp)
452 fn line_clamp(mut self, lines: usize) -> Self {
453 let mut text_style = self.text_style();
454 text_style.line_clamp = Some(lines);
455 self.overflow_hidden()
456 }
457
458 /// Sets the direction in which flex children are placed.
459 ///
460 /// See [`FlexDirection`] for the values. [Docs](https://tailwindcss.com/docs/flex-direction)
461 fn flex_direction(mut self, direction: FlexDirection) -> Self {
462 self.style().flex_direction = Some(direction);
463 self
464 }
465
466 /// Sets the flex direction to `column`, so children stack from top to bottom.
467 ///
468 /// [Docs](https://tailwindcss.com/docs/flex-direction#column)
469 fn flex_col(mut self) -> Self {
470 self.style().flex_direction = Some(FlexDirection::Column);
471 self
472 }
473
474 /// Sets the flex direction to `column-reverse`, so children stack from bottom to top.
475 ///
476 /// [Docs](https://tailwindcss.com/docs/flex-direction#column-reverse)
477 fn flex_col_reverse(mut self) -> Self {
478 self.style().flex_direction = Some(FlexDirection::ColumnReverse);
479 self
480 }
481
482 /// Sets the flex direction to `row`, so children sit left to right.
483 ///
484 /// [Docs](https://tailwindcss.com/docs/flex-direction#row)
485 fn flex_row(mut self) -> Self {
486 self.style().flex_direction = Some(FlexDirection::Row);
487 self
488 }
489
490 /// Sets the flex direction to `row-reverse`, so children sit right to left.
491 ///
492 /// [Docs](https://tailwindcss.com/docs/flex-direction#row-reverse)
493 fn flex_row_reverse(mut self) -> Self {
494 self.style().flex_direction = Some(FlexDirection::RowReverse);
495 self
496 }
497
498 /// Lets a flex child grow and shrink to fill the space, ignoring its initial size.
499 ///
500 /// This sets `flex: 1 1 0%`: grow 1, shrink 1, basis 0. Use it on the child that
501 /// should take up the remaining space.
502 ///
503 /// [Docs](https://tailwindcss.com/docs/flex#flex-1)
504 fn flex_1(mut self) -> Self {
505 self.style().flex_grow = Some(1.);
506 self.style().flex_shrink = Some(1.);
507 self.style().flex_basis = Some(relative(0.).into());
508 self
509 }
510
511 /// Lets a flex child grow and shrink, starting from its natural size.
512 ///
513 /// This sets `flex: 1 1 auto`.
514 ///
515 /// [Docs](https://tailwindcss.com/docs/flex#auto)
516 fn flex_auto(mut self) -> Self {
517 self.style().flex_grow = Some(1.);
518 self.style().flex_shrink = Some(1.);
519 self.style().flex_basis = Some(Length::Auto);
520 self
521 }
522
523 /// Lets a flex child shrink but not grow, starting from its natural size.
524 ///
525 /// This sets `flex: 0 1 auto`.
526 ///
527 /// [Docs](https://tailwindcss.com/docs/flex#initial)
528 fn flex_initial(mut self) -> Self {
529 self.style().flex_grow = Some(0.);
530 self.style().flex_shrink = Some(1.);
531 self.style().flex_basis = Some(Length::Auto);
532 self
533 }
534
535 /// Stops a flex child from growing or shrinking.
536 ///
537 /// This sets `flex: none`, which keeps the child at its natural size.
538 ///
539 /// [Docs](https://tailwindcss.com/docs/flex#none)
540 fn flex_none(mut self) -> Self {
541 self.style().flex_grow = Some(0.);
542 self.style().flex_shrink = Some(0.);
543 self.style().flex_basis = Some(Length::Auto);
544 self
545 }
546
547 /// Sets the starting size of a flex child before it grows or shrinks.
548 ///
549 /// [Docs](https://tailwindcss.com/docs/flex-basis)
550 fn flex_basis(mut self, basis: impl Into<Length>) -> Self {
551 self.style().flex_basis = Some(basis.into());
552 self
553 }
554
555 /// Sets the factor by which a flex child grows to fill spare space.
556 ///
557 /// A child with a factor of 2 takes twice the spare space of a child with 1.
558 ///
559 /// [Docs](https://tailwindcss.com/docs/flex-grow)
560 fn flex_grow(mut self, grow: f32) -> Self {
561 self.style().flex_grow = Some(grow);
562 self
563 }
564
565 /// Stops a flex child from growing.
566 ///
567 /// [Docs](https://tailwindcss.com/docs/flex-grow#dont-grow)
568 fn flex_grow_0(mut self) -> Self {
569 self.style().flex_grow = Some(0.);
570 self
571 }
572
573 /// Lets a flex child grow with a factor of 1.
574 ///
575 /// [Docs](https://tailwindcss.com/docs/flex-grow#grow-1)
576 fn flex_grow_1(mut self) -> Self {
577 self.style().flex_grow = Some(1.);
578 self
579 }
580
581 /// Sets the factor by which a flex child shrinks when space is short.
582 ///
583 /// [Docs](https://tailwindcss.com/docs/flex-shrink)
584 fn flex_shrink(mut self, shrink: f32) -> Self {
585 self.style().flex_shrink = Some(shrink);
586 self
587 }
588
589 /// Prevents this flex child from participating in shrinkage when space is short.
590 ///
591 /// Other constraints, including the child's minimum size, still affect its final size. This
592 /// is the usual fix for a sidebar that gets squeezed by its content area.
593 ///
594 /// [Docs](https://tailwindcss.com/docs/flex-shrink#dont-shrink)
595 fn flex_shrink_0(mut self) -> Self {
596 self.style().flex_shrink = Some(0.);
597 self
598 }
599
600 /// Lets a flex child shrink with a factor of 1.
601 ///
602 /// [Docs](https://tailwindcss.com/docs/flex-shrink#shrink-1)
603 fn flex_shrink_1(mut self) -> Self {
604 self.style().flex_shrink = Some(1.);
605 self
606 }
607
608 /// Lets flex children wrap onto new lines in the normal direction.
609 ///
610 /// [Docs](https://tailwindcss.com/docs/flex-wrap#wrap-normally)
611 fn flex_wrap(mut self) -> Self {
612 self.style().flex_wrap = Some(FlexWrap::Wrap);
613 self
614 }
615
616 /// Lets flex children wrap onto new lines in the reverse direction.
617 ///
618 /// [Docs](https://tailwindcss.com/docs/flex-wrap#wrap-reversed)
619 fn flex_wrap_reverse(mut self) -> Self {
620 self.style().flex_wrap = Some(FlexWrap::WrapReverse);
621 self
622 }
623
624 /// Stops flex children from wrapping. Inflexible children overflow the container instead.
625 ///
626 /// [Docs](https://tailwindcss.com/docs/flex-wrap#dont-wrap)
627 fn flex_nowrap(mut self) -> Self {
628 self.style().flex_wrap = Some(FlexWrap::NoWrap);
629 self
630 }
631
632 /// Aligns flex or grid children to the start of the cross axis.
633 ///
634 /// [Docs](https://tailwindcss.com/docs/align-items#start)
635 fn items_start(mut self) -> Self {
636 self.style().align_items = Some(AlignItems::FlexStart);
637 self
638 }
639
640 /// Aligns flex or grid children to the end of the cross axis.
641 ///
642 /// [Docs](https://tailwindcss.com/docs/align-items#end)
643 fn items_end(mut self) -> Self {
644 self.style().align_items = Some(AlignItems::FlexEnd);
645 self
646 }
647
648 /// Centers flex or grid children along the cross axis.
649 ///
650 /// [Docs](https://tailwindcss.com/docs/align-items#center)
651 fn items_center(mut self) -> Self {
652 self.style().align_items = Some(AlignItems::Center);
653 self
654 }
655
656 /// Aligns flex or grid children on their text baselines along the cross axis.
657 ///
658 /// [Docs](https://tailwindcss.com/docs/align-items#baseline)
659 fn items_baseline(mut self) -> Self {
660 self.style().align_items = Some(AlignItems::Baseline);
661 self
662 }
663
664 /// Stretches flex or grid children to fill the cross axis.
665 ///
666 /// [Docs](https://tailwindcss.com/docs/align-items#stretch)
667 fn items_stretch(mut self) -> Self {
668 self.style().align_items = Some(AlignItems::Stretch);
669 self
670 }
671
672 /// Aligns this flex or grid child to the start of the container's cross axis.
673 ///
674 /// [Docs](https://tailwindcss.com/docs/align-self#start)
675 fn self_start(mut self) -> Self {
676 self.style().align_self = Some(AlignSelf::Start);
677 self
678 }
679
680 /// Aligns this flex or grid child to the end of the container's cross axis.
681 ///
682 /// [Docs](https://tailwindcss.com/docs/align-self#end)
683 fn self_end(mut self) -> Self {
684 self.style().align_self = Some(AlignSelf::End);
685 self
686 }
687
688 /// Aligns this flex child to the flex-relative start of the cross axis.
689 ///
690 /// [Docs](https://tailwindcss.com/docs/align-self#start)
691 fn self_flex_start(mut self) -> Self {
692 self.style().align_self = Some(AlignSelf::FlexStart);
693 self
694 }
695
696 /// Aligns this flex child to the flex-relative end of the cross axis.
697 ///
698 /// [Docs](https://tailwindcss.com/docs/align-self#end)
699 fn self_flex_end(mut self) -> Self {
700 self.style().align_self = Some(AlignSelf::FlexEnd);
701 self
702 }
703
704 /// Centers this flex or grid child along the container's cross axis.
705 ///
706 /// [Docs](https://tailwindcss.com/docs/align-self#center)
707 fn self_center(mut self) -> Self {
708 self.style().align_self = Some(AlignSelf::Center);
709 self
710 }
711
712 /// Aligns this flex or grid child on the container's baseline along the cross axis.
713 ///
714 /// [Docs](https://tailwindcss.com/docs/align-self#baseline)
715 fn self_baseline(mut self) -> Self {
716 self.style().align_self = Some(AlignSelf::Baseline);
717 self
718 }
719
720 /// Stretches this flex or grid child to fill the container's cross axis.
721 ///
722 /// [Docs](https://tailwindcss.com/docs/align-self#stretch)
723 fn self_stretch(mut self) -> Self {
724 self.style().align_self = Some(AlignSelf::Stretch);
725 self
726 }
727
728 /// Packs flex or grid children against the start of the main axis.
729 ///
730 /// [Docs](https://tailwindcss.com/docs/justify-content#start)
731 fn justify_start(mut self) -> Self {
732 self.style().justify_content = Some(JustifyContent::Start);
733 self
734 }
735
736 /// Packs flex or grid children against the end of the main axis.
737 ///
738 /// [Docs](https://tailwindcss.com/docs/justify-content#end)
739 fn justify_end(mut self) -> Self {
740 self.style().justify_content = Some(JustifyContent::End);
741 self
742 }
743
744 /// Packs flex children against the flex-relative start of the main axis.
745 fn justify_flex_start(mut self) -> Self {
746 self.style().justify_content = Some(JustifyContent::FlexStart);
747 self
748 }
749
750 /// Packs flex children against the flex-relative end of the main axis.
751 fn justify_flex_end(mut self) -> Self {
752 self.style().justify_content = Some(JustifyContent::FlexEnd);
753 self
754 }
755
756 /// Centers flex or grid children along the main axis.
757 ///
758 /// [Docs](https://tailwindcss.com/docs/justify-content#center)
759 fn justify_center(mut self) -> Self {
760 self.style().justify_content = Some(JustifyContent::Center);
761 self
762 }
763
764 /// Spreads children along the main axis with equal space between them.
765 ///
766 /// The first and last children touch the edges.
767 ///
768 /// [Docs](https://tailwindcss.com/docs/justify-content#space-between)
769 fn justify_between(mut self) -> Self {
770 self.style().justify_content = Some(JustifyContent::SpaceBetween);
771 self
772 }
773
774 /// Spreads children along the main axis with equal space on each side of each child.
775 ///
776 /// The space at the edges is half the space between children.
777 ///
778 /// [Docs](https://tailwindcss.com/docs/justify-content#space-around)
779 fn justify_around(mut self) -> Self {
780 self.style().justify_content = Some(JustifyContent::SpaceAround);
781 self
782 }
783
784 /// Spreads children along the main axis with equal space between every child and at both edges.
785 ///
786 /// [Docs](https://tailwindcss.com/docs/justify-content#space-evenly)
787 fn justify_evenly(mut self) -> Self {
788 self.style().justify_content = Some(JustifyContent::SpaceEvenly);
789 self
790 }
791
792 /// Clears `align-content`, so lines of children use their default packing.
793 ///
794 /// [Docs](https://tailwindcss.com/docs/align-content#normal)
795 fn content_normal(mut self) -> Self {
796 self.style().align_content = None;
797 self
798 }
799
800 /// Packs lines of children in the center of the cross axis.
801 ///
802 /// [Docs](https://tailwindcss.com/docs/align-content#center)
803 fn content_center(mut self) -> Self {
804 self.style().align_content = Some(AlignContent::Center);
805 self
806 }
807
808 /// Packs lines of children against the start of the cross axis.
809 ///
810 /// [Docs](https://tailwindcss.com/docs/align-content#start)
811 fn content_start(mut self) -> Self {
812 self.style().align_content = Some(AlignContent::FlexStart);
813 self
814 }
815
816 /// Packs lines of children against the end of the cross axis.
817 ///
818 /// [Docs](https://tailwindcss.com/docs/align-content#end)
819 fn content_end(mut self) -> Self {
820 self.style().align_content = Some(AlignContent::FlexEnd);
821 self
822 }
823
824 /// Spreads lines of children along the cross axis with equal space between them.
825 ///
826 /// [Docs](https://tailwindcss.com/docs/align-content#space-between)
827 fn content_between(mut self) -> Self {
828 self.style().align_content = Some(AlignContent::SpaceBetween);
829 self
830 }
831
832 /// Spreads lines of children along the cross axis with equal space on each side of each line.
833 ///
834 /// [Docs](https://tailwindcss.com/docs/align-content#space-around)
835 fn content_around(mut self) -> Self {
836 self.style().align_content = Some(AlignContent::SpaceAround);
837 self
838 }
839
840 /// Spreads lines of children along the cross axis with equal space between every line and at both edges.
841 ///
842 /// [Docs](https://tailwindcss.com/docs/align-content#space-evenly)
843 fn content_evenly(mut self) -> Self {
844 self.style().align_content = Some(AlignContent::SpaceEvenly);
845 self
846 }
847
848 /// Stretches lines of children to fill the cross axis.
849 ///
850 /// [Docs](https://tailwindcss.com/docs/align-content#stretch)
851 fn content_stretch(mut self) -> Self {
852 self.style().align_content = Some(AlignContent::Stretch);
853 self
854 }
855
856 /// Sets the width-to-height ratio of this element.
857 ///
858 /// A ratio of `2.0` makes the element twice as wide as it is tall. The ratio is used
859 /// only when one dimension is not set explicitly.
860 ///
861 /// [Docs](https://tailwindcss.com/docs/aspect-ratio)
862 fn aspect_ratio(mut self, ratio: f32) -> Self {
863 self.style().aspect_ratio = Some(ratio);
864 self
865 }
866
867 /// Sets the aspect ratio to `1.0`, so the element's width and height are equal.
868 ///
869 /// [Docs](https://tailwindcss.com/docs/aspect-ratio)
870 fn aspect_square(mut self) -> Self {
871 self.style().aspect_ratio = Some(1.0);
872 self
873 }
874
875 /// Sets the background of this element.
876 ///
877 /// Accepts any color, such as [`Hsla`](crate::Hsla) or [`Rgba`](crate::Rgba), or a gradient or pattern as a
878 /// [`Background`](crate::Background). See [`Fill`] for the full set of accepted values.
879 fn bg<F>(mut self, fill: F) -> Self
880 where
881 F: Into<Fill>,
882 Self: Sized,
883 {
884 self.style().background = Some(fill.into());
885 self
886 }
887
888 /// Sets the border style to dashed.
889 ///
890 /// Use [`Styled::border_dashed_length`] and [`Styled::border_dashed_gap`] to tune the
891 /// dashes.
892 fn border_dashed(mut self) -> Self {
893 self.style().border_style = Some(BorderStyle::Dashed);
894 self
895 }
896
897 /// Sets the length of each border dash as a multiple of the border width.
898 ///
899 /// Negative values are clamped to `0.0`. For a 2px border, `3.0` gives 6px dashes.
900 fn border_dashed_length(mut self, length_per_border_width: f32) -> Self {
901 self.style().border_dashed_length = Some(length_per_border_width.max(0.0));
902
903 self
904 }
905
906 /// Sets the gap between border dashes as a multiple of the border width.
907 ///
908 /// Negative values are clamped to `0.0`. For a 2px border, `2.0` gives 4px gaps.
909 fn border_dashed_gap(mut self, gap_per_border_width: f32) -> Self {
910 self.style().border_dashed_gap = Some(gap_per_border_width.max(0.0));
911
912 self
913 }
914
915 /// Returns the text style refinement configured on this element.
916 ///
917 /// Use it to set a text property that has no dedicated method. The refinement is inherited
918 /// by text descendants when GPUI resolves their styles; a descendant's own value takes
919 /// precedence.
920 fn text_style(&mut self) -> &mut TextStyleRefinement {
921 let style: &mut StyleRefinement = self.style();
922 &mut style.text
923 }
924
925 /// Sets the text color of this element.
926 ///
927 /// This value cascades to its children, unless a child sets its own color.
928 fn text_color(mut self, color: impl IntoColor<Hsla>) -> Self {
929 self.text_style().color = Some(color.into_color());
930 self
931 }
932
933 /// Sets the font weight of this element and its children.
934 ///
935 /// This value cascades to its children.
936 fn font_weight(mut self, weight: FontWeight) -> Self {
937 self.text_style().font_weight = Some(weight);
938 self
939 }
940
941 /// Sets the font width of this element and its children.
942 ///
943 /// Accepts a percentage or a [`FontWidth`] preset.
944 fn font_width(mut self, width: impl Into<FontWidth>) -> Self {
945 self.text_style().font_width = Some(width.into());
946
947 self
948 }
949
950 /// Sets the background color behind the text of this element.
951 ///
952 /// This value cascades to its children.
953 fn text_bg(mut self, bg: impl IntoColor<Hsla>) -> Self {
954 self.text_style().background_color = Some(bg.into_color());
955 self
956 }
957
958 /// Sets the font size of this element and its children.
959 ///
960 /// The size is an absolute length: pass [`px`](crate::px) for logical pixels or
961 /// [`rems`](crate::rems) to scale with the window's root font size. This value
962 /// cascades to its children.
963 fn text_size(mut self, size: impl Into<AbsoluteLength>) -> Self {
964 self.text_style().font_size = Some(size.into());
965 self
966 }
967
968 /// Sets the font size to `0.75rem` (12px with the default 16px root size).
969 ///
970 /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
971 fn text_xs(mut self) -> Self {
972 self.text_style().font_size = Some(rems(0.75).into());
973 self
974 }
975
976 /// Sets the font size to `0.875rem` (14px with the default 16px root size).
977 ///
978 /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
979 fn text_sm(mut self) -> Self {
980 self.text_style().font_size = Some(rems(0.875).into());
981 self
982 }
983
984 /// Sets the font size to `1rem` (16px with the default 16px root size).
985 ///
986 /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
987 fn text_base(mut self) -> Self {
988 self.text_style().font_size = Some(rems(1.0).into());
989 self
990 }
991
992 /// Sets the font size to `1.125rem` (18px with the default 16px root size).
993 ///
994 /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
995 fn text_lg(mut self) -> Self {
996 self.text_style().font_size = Some(rems(1.125).into());
997 self
998 }
999
1000 /// Sets the font size to `1.25rem` (20px with the default 16px root size).
1001 ///
1002 /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
1003 fn text_xl(mut self) -> Self {
1004 self.text_style().font_size = Some(rems(1.25).into());
1005 self
1006 }
1007
1008 /// Sets the font size to `1.5rem` (24px with the default 16px root size).
1009 ///
1010 /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
1011 fn text_2xl(mut self) -> Self {
1012 self.text_style().font_size = Some(rems(1.5).into());
1013 self
1014 }
1015
1016 /// Sets the font size to `1.875rem` (30px with the default 16px root size).
1017 ///
1018 /// [Docs](https://tailwindcss.com/docs/font-size#setting-the-font-size)
1019 fn text_3xl(mut self) -> Self {
1020 self.text_style().font_size = Some(rems(1.875).into());
1021 self
1022 }
1023
1024 /// Sets the font style to italic.
1025 ///
1026 /// [Docs](https://tailwindcss.com/docs/font-style#italicizing-text)
1027 fn italic(mut self) -> Self {
1028 self.text_style().font_style = Some(FontStyle::Italic);
1029 self
1030 }
1031
1032 /// Sets the font style to normal, which is not italic.
1033 ///
1034 /// [Docs](https://tailwindcss.com/docs/font-style#displaying-text-normally)
1035 fn not_italic(mut self) -> Self {
1036 self.text_style().font_style = Some(FontStyle::Normal);
1037 self
1038 }
1039
1040 /// Underlines the text of this element with a 1px line.
1041 ///
1042 /// This replaces any underline style set earlier on this element, including its
1043 /// color, so call [`Styled::text_decoration_color`] after this method.
1044 /// An underline set here can cascade to text descendants; [`Styled::text_decoration_none`]
1045 /// only clears one set on the current element.
1046 ///
1047 /// [Docs](https://tailwindcss.com/docs/text-decoration-line#underling-text)
1048 fn underline(mut self) -> Self {
1049 let style = self.text_style();
1050 style.underline = Some(UnderlineStyle {
1051 thickness: px(1.),
1052 ..Default::default()
1053 });
1054 self
1055 }
1056
1057 /// Draws a line through the text of this element with a 1px line.
1058 ///
1059 /// This replaces any strikethrough set earlier on this element. It doesn't change the
1060 /// underline.
1061 ///
1062 /// [Docs](https://tailwindcss.com/docs/text-decoration-line#adding-a-line-through-text)
1063 fn line_through(mut self) -> Self {
1064 let style = self.text_style();
1065 style.strikethrough = Some(StrikethroughStyle {
1066 thickness: px(1.),
1067 ..Default::default()
1068 });
1069 self
1070 }
1071
1072 /// Removes an underline set earlier on this element. It can't remove an underline
1073 /// inherited from a parent, and it leaves any strikethrough alone.
1074 fn text_decoration_none(mut self) -> Self {
1075 self.text_style().underline = None;
1076 self
1077 }
1078
1079 /// Sets the color of the text decoration line.
1080 ///
1081 /// This sets the underline color, not the strikethrough color. If no underline is set,
1082 /// it creates one with 0px thickness, which draws nothing until you set a thickness.
1083 /// Call this after [`Styled::underline`], because `underline` replaces the whole underline
1084 /// record, including its color.
1085 fn text_decoration_color(mut self, color: impl IntoColor<Hsla>) -> Self {
1086 let style = self.text_style();
1087 let underline = style.underline.get_or_insert_with(Default::default);
1088 underline.color = Some(color.into_color());
1089 self
1090 }
1091
1092 /// Sets the text decoration style to a solid line.
1093 ///
1094 /// If no underline exists yet, this creates one with zero thickness; pair it with
1095 /// [`Styled::underline`] or a thickness method to make the line visible.
1096 ///
1097 /// [Docs](https://tailwindcss.com/docs/text-decoration-style)
1098 fn text_decoration_solid(mut self) -> Self {
1099 let style = self.text_style();
1100 let underline = style.underline.get_or_insert_with(Default::default);
1101 underline.wavy = false;
1102 self
1103 }
1104
1105 /// Sets the text decoration style to a wavy line.
1106 ///
1107 /// If no underline exists yet, this creates one with zero thickness; pair it with
1108 /// [`Styled::underline`] or a thickness method to make the line visible.
1109 ///
1110 /// [Docs](https://tailwindcss.com/docs/text-decoration-style)
1111 fn text_decoration_wavy(mut self) -> Self {
1112 let style = self.text_style();
1113 let underline = style.underline.get_or_insert_with(Default::default);
1114 underline.wavy = true;
1115 self
1116 }
1117
1118 /// Sets the text decoration thickness to `0px`, which hides the line.
1119 ///
1120 /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness)
1121 fn text_decoration_0(mut self) -> Self {
1122 let style = self.text_style();
1123 let underline = style.underline.get_or_insert_with(Default::default);
1124 underline.thickness = px(0.);
1125 self
1126 }
1127
1128 /// Sets the text decoration thickness to `1px`.
1129 ///
1130 /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness)
1131 fn text_decoration_1(mut self) -> Self {
1132 let style = self.text_style();
1133 let underline = style.underline.get_or_insert_with(Default::default);
1134 underline.thickness = px(1.);
1135 self
1136 }
1137
1138 /// Sets the text decoration thickness to `2px`.
1139 ///
1140 /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness)
1141 fn text_decoration_2(mut self) -> Self {
1142 let style = self.text_style();
1143 let underline = style.underline.get_or_insert_with(Default::default);
1144 underline.thickness = px(2.);
1145 self
1146 }
1147
1148 /// Sets the text decoration thickness to `4px`.
1149 ///
1150 /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness)
1151 fn text_decoration_4(mut self) -> Self {
1152 let style = self.text_style();
1153 let underline = style.underline.get_or_insert_with(Default::default);
1154 underline.thickness = px(4.);
1155 self
1156 }
1157
1158 /// Sets the text decoration thickness to `8px`.
1159 ///
1160 /// [Docs](https://tailwindcss.com/docs/text-decoration-thickness)
1161 fn text_decoration_8(mut self) -> Self {
1162 let style = self.text_style();
1163 let underline = style.underline.get_or_insert_with(Default::default);
1164 underline.thickness = px(8.);
1165 self
1166 }
1167
1168 /// Sets the font family of this element and its children.
1169 ///
1170 /// Pass a font family name, such as `"Menlo"`. This value cascades to its children.
1171 fn font_family(mut self, family_name: impl Into<SharedString>) -> Self {
1172 self.text_style().font_family = Some(family_name.into());
1173 self
1174 }
1175
1176 /// Sets the OpenType font features of this element and its children.
1177 fn font_features(mut self, features: FontFeatures) -> Self {
1178 self.text_style().font_features = Some(features);
1179 self
1180 }
1181
1182 /// Sets the font family, features, fallbacks, weight, width, and style of this element and its children.
1183 ///
1184 /// Use [`Styled::font_family`] to change only the family.
1185 fn font(mut self, font: Font) -> Self {
1186 let Font {
1187 family,
1188 features,
1189 fallbacks,
1190 weight,
1191 width,
1192 style,
1193 } = font;
1194
1195 let text_style = self.text_style();
1196 text_style.font_family = Some(family);
1197 text_style.font_features = Some(features);
1198 text_style.font_weight = Some(weight);
1199 text_style.font_width = Some(width);
1200 text_style.font_style = Some(style);
1201 text_style.font_fallbacks = fallbacks;
1202
1203 self
1204 }
1205
1206 /// Sets the line height of this element and its children.
1207 ///
1208 /// Pass an absolute length such as [`px`](crate::px) or [`rems`](crate::rems), or a relative
1209 /// length such as `relative(1.5)` to make each line 1.5 times the element's font size.
1210 /// Relative values are resolved against the font size, not the parent's layout size.
1211 fn line_height(mut self, line_height: impl Into<DefiniteLength>) -> Self {
1212 self.text_style().line_height = Some(line_height.into());
1213 self
1214 }
1215
1216 /// Sets the opacity of this element and its children, composited together as one group.
1217 ///
1218 /// `0.0` is fully transparent and `1.0` is fully opaque.
1219 fn opacity(mut self, opacity: f32) -> Self {
1220 self.style().opacity = Some(opacity);
1221 self
1222 }
1223
1224 /// Sets the number of equal-width columns in this grid element.
1225 ///
1226 /// Columns share the remaining width equally, with a zero minimum track size. A long child
1227 /// can therefore overflow or be compressed below its min-content width. Use
1228 /// [`Styled::grid_cols_min_content`] when each column must accommodate its min-content size.
1229 fn grid_cols(mut self, cols: u16) -> Self {
1230 self.style().grid_cols = Some(GridTemplate {
1231 repeat: cols,
1232 min_size: GridTemplateMinSize::Zero,
1233 });
1234 self
1235 }
1236
1237 /// Sets the number of columns, each at least as wide as its content.
1238 ///
1239 /// Each track has a min-content minimum and then shares remaining space equally. This keeps
1240 /// unbreakable or otherwise intrinsic content from being compressed below that minimum.
1241 fn grid_cols_min_content(mut self, cols: u16) -> Self {
1242 self.style().grid_cols = Some(GridTemplate {
1243 repeat: cols,
1244 min_size: GridTemplateMinSize::MinContent,
1245 });
1246 self
1247 }
1248
1249 /// Sets the number of columns with max-content sizing as the upper track size.
1250 ///
1251 /// Each track can grow to its max-content width instead of sharing all remaining space as a
1252 /// flexible `1fr` track. The minimum remains zero, so a narrow grid can compress or overflow
1253 /// content, and unused space need not be distributed across the tracks.
1254 fn grid_cols_max_content(mut self, cols: u16) -> Self {
1255 self.style().grid_cols = Some(GridTemplate {
1256 repeat: cols,
1257 min_size: GridTemplateMinSize::MaxContent,
1258 });
1259 self
1260 }
1261
1262 /// Sets the number of equal-height rows in this grid element.
1263 ///
1264 /// Rows share the remaining height equally, with a zero minimum track size. A tall child can
1265 /// therefore overflow or be compressed below its min-content height. Use
1266 /// [`Styled::grid_rows_min_content`] when each row must accommodate that minimum.
1267 fn grid_rows(mut self, rows: u16) -> Self {
1268 self.style().grid_rows = Some(GridTemplate {
1269 repeat: rows,
1270 min_size: GridTemplateMinSize::Zero,
1271 });
1272 self
1273 }
1274
1275 /// Sets the number of rows, each at least as tall as its content.
1276 ///
1277 /// Each track has a min-content minimum and then shares remaining space equally. This keeps
1278 /// content from being compressed below its intrinsic minimum height.
1279 fn grid_rows_min_content(mut self, rows: u16) -> Self {
1280 self.style().grid_rows = Some(GridTemplate {
1281 repeat: rows,
1282 min_size: GridTemplateMinSize::MinContent,
1283 });
1284 self
1285 }
1286
1287 /// Sets the number of rows with max-content sizing as the upper track size.
1288 ///
1289 /// Each track can grow to its max-content height instead of sharing all remaining space as a
1290 /// flexible `1fr` track. The minimum remains zero, so a short grid can compress or overflow
1291 /// content, and unused space need not be distributed across the tracks.
1292 fn grid_rows_max_content(mut self, rows: u16) -> Self {
1293 self.style().grid_rows = Some(GridTemplate {
1294 repeat: rows,
1295 min_size: GridTemplateMinSize::MaxContent,
1296 });
1297 self
1298 }
1299
1300 /// Sets the grid column line where this element starts. Lines are numbered from 1;
1301 /// negative values count backward from the end of the explicit grid.
1302 fn col_start(mut self, start: i16) -> Self {
1303 let grid_location = self.style().grid_location_mut();
1304 grid_location.column.start = GridPlacement::Line(start);
1305 self
1306 }
1307
1308 /// Lets the grid place this element's start column automatically.
1309 fn col_start_auto(mut self) -> Self {
1310 let grid_location = self.style().grid_location_mut();
1311 grid_location.column.start = GridPlacement::Auto;
1312 self
1313 }
1314
1315 /// Sets the grid column line where this element ends. Lines are numbered from 1; negative values count from the end.
1316 fn col_end(mut self, end: i16) -> Self {
1317 let grid_location = self.style().grid_location_mut();
1318 grid_location.column.end = GridPlacement::Line(end);
1319 self
1320 }
1321
1322 /// Lets the grid place this element's end column automatically.
1323 fn col_end_auto(mut self) -> Self {
1324 let grid_location = self.style().grid_location_mut();
1325 grid_location.column.end = GridPlacement::Auto;
1326 self
1327 }
1328
1329 /// Makes this element span `span` grid columns.
1330 fn col_span(mut self, span: u16) -> Self {
1331 let grid_location = self.style().grid_location_mut();
1332 grid_location.column = GridPlacement::Span(span)..GridPlacement::Span(span);
1333 self
1334 }
1335
1336 /// Makes this element span all grid columns.
1337 fn col_span_full(mut self) -> Self {
1338 let grid_location = self.style().grid_location_mut();
1339 grid_location.column = GridPlacement::Line(1)..GridPlacement::Line(-1);
1340 self
1341 }
1342
1343 /// Sets the grid row line where this element starts. Lines are numbered from 1;
1344 /// negative values count backward from the end of the explicit grid.
1345 fn row_start(mut self, start: i16) -> Self {
1346 let grid_location = self.style().grid_location_mut();
1347 grid_location.row.start = GridPlacement::Line(start);
1348 self
1349 }
1350
1351 /// Lets the grid place this element's start row automatically.
1352 fn row_start_auto(mut self) -> Self {
1353 let grid_location = self.style().grid_location_mut();
1354 grid_location.row.start = GridPlacement::Auto;
1355 self
1356 }
1357
1358 /// Sets the grid row line where this element ends. Lines are numbered from 1; negative values count from the end.
1359 fn row_end(mut self, end: i16) -> Self {
1360 let grid_location = self.style().grid_location_mut();
1361 grid_location.row.end = GridPlacement::Line(end);
1362 self
1363 }
1364
1365 /// Lets the grid place this element's end row automatically.
1366 fn row_end_auto(mut self) -> Self {
1367 let grid_location = self.style().grid_location_mut();
1368 grid_location.row.end = GridPlacement::Auto;
1369 self
1370 }
1371
1372 /// Makes this element span `span` grid rows.
1373 fn row_span(mut self, span: u16) -> Self {
1374 let grid_location = self.style().grid_location_mut();
1375 grid_location.row = GridPlacement::Span(span)..GridPlacement::Span(span);
1376 self
1377 }
1378
1379 /// Makes this element span all grid rows.
1380 fn row_span_full(mut self) -> Self {
1381 let grid_location = self.style().grid_location_mut();
1382 grid_location.row = GridPlacement::Line(1)..GridPlacement::Line(-1);
1383 self
1384 }
1385
1386 /// Draws a debug border around this element.
1387 ///
1388 /// This method exists only in debug builds (`debug_assertions`).
1389 #[cfg(debug_assertions)]
1390 fn debug(mut self) -> Self {
1391 self.style().debug = Some(true);
1392 self
1393 }
1394
1395 /// Draws a debug border around this element and every element below it in the tree.
1396 ///
1397 /// This method exists only in debug builds (`debug_assertions`).
1398 #[cfg(debug_assertions)]
1399 fn debug_below(mut self) -> Self {
1400 self.style().debug_below = Some(true);
1401 self
1402 }
1403
1404 /// Sets how smooth the rounded corners are, from `0.0` for circular corners to `1.0` for maximum smoothing.
1405 /// In debug builds, values outside this range trigger an assertion.
1406 fn rounded_smoothing(mut self, amount: f32) -> Self {
1407 debug_assert!(
1408 (0.0..=1.0).contains(&amount),
1409 "corner smoothing must be between 0 and 1"
1410 );
1411 self.style().corner_smoothing = Some(amount);
1412 self
1413 }
1414
1415 /// Sets corner smoothing to `0.6`, which matches iOS-style corners.
1416 fn rounded_smoothing_ios(mut self) -> Self {
1417 self.style().corner_smoothing = Some(0.6);
1418 self
1419 }
1420}