1use crate::{
2 self as gpui, hsla, point, px, relative, rems, AbsoluteLength, AlignItems, CursorStyle,
3 DefiniteLength, Fill, FlexDirection, FontWeight, Hsla, JustifyContent, Length, Position,
4 SharedString, StyleRefinement, Visibility, WhiteSpace,
5};
6use crate::{BoxShadow, TextStyleRefinement};
7use smallvec::{smallvec, SmallVec};
8use taffy::style::{Display, Overflow};
9
10pub trait Styled: Sized {
11 fn style(&mut self) -> &mut StyleRefinement;
12
13 gpui_macros::style_helpers!();
14
15 fn z_index(mut self, z_index: u16) -> Self {
16 self.style().z_index = Some(z_index);
17 self
18 }
19
20 /// Sets the size of the element to the full width and height.
21 fn full(mut self) -> Self {
22 self.style().size.width = Some(relative(1.).into());
23 self.style().size.height = Some(relative(1.).into());
24 self
25 }
26
27 /// Sets the position of the element to `relative`.
28 /// [Docs](https://tailwindcss.com/docs/position)
29 fn relative(mut self) -> Self {
30 self.style().position = Some(Position::Relative);
31 self
32 }
33
34 /// Sets the position of the element to `absolute`.
35 /// [Docs](https://tailwindcss.com/docs/position)
36 fn absolute(mut self) -> Self {
37 self.style().position = Some(Position::Absolute);
38 self
39 }
40
41 /// Sets the display type of the element to `block`.
42 /// [Docs](https://tailwindcss.com/docs/display)
43 fn block(mut self) -> Self {
44 self.style().display = Some(Display::Block);
45 self
46 }
47
48 /// Sets the display type of the element to `flex`.
49 /// [Docs](https://tailwindcss.com/docs/display)
50 fn flex(mut self) -> Self {
51 self.style().display = Some(Display::Flex);
52 self
53 }
54
55 /// Sets the visibility of the element to `visible`.
56 /// [Docs](https://tailwindcss.com/docs/visibility)
57 fn visible(mut self) -> Self {
58 self.style().visibility = Some(Visibility::Visible);
59 self
60 }
61
62 /// Sets the visibility of the element to `hidden`.
63 /// [Docs](https://tailwindcss.com/docs/visibility)
64 fn invisible(mut self) -> Self {
65 self.style().visibility = Some(Visibility::Hidden);
66 self
67 }
68
69 /// Sets the behavior of content that overflows the container to be hidden.
70 /// [Docs](https://tailwindcss.com/docs/overflow#hiding-content-that-overflows)
71 fn overflow_hidden(mut self) -> Self {
72 self.style().overflow.x = Some(Overflow::Hidden);
73 self.style().overflow.y = Some(Overflow::Hidden);
74 self
75 }
76
77 /// Sets the behavior of content that overflows the container on the X axis to be hidden.
78 /// [Docs](https://tailwindcss.com/docs/overflow#hiding-content-that-overflows)
79 fn overflow_x_hidden(mut self) -> Self {
80 self.style().overflow.x = Some(Overflow::Hidden);
81 self
82 }
83
84 /// Sets the behavior of content that overflows the container on the Y axis to be hidden.
85 /// [Docs](https://tailwindcss.com/docs/overflow#hiding-content-that-overflows)
86 fn overflow_y_hidden(mut self) -> Self {
87 self.style().overflow.y = Some(Overflow::Hidden);
88 self
89 }
90
91 fn cursor(mut self, cursor: CursorStyle) -> Self {
92 self.style().mouse_cursor = Some(cursor);
93 self
94 }
95
96 /// Sets the cursor style when hovering an element to `default`.
97 /// [Docs](https://tailwindcss.com/docs/cursor)
98 fn cursor_default(mut self) -> Self {
99 self.style().mouse_cursor = Some(CursorStyle::Arrow);
100 self
101 }
102
103 /// Sets the cursor style when hovering an element to `pointer`.
104 /// [Docs](https://tailwindcss.com/docs/cursor)
105 fn cursor_pointer(mut self) -> Self {
106 self.style().mouse_cursor = Some(CursorStyle::PointingHand);
107 self
108 }
109
110 /// Sets cursor style when hovering over an element to `text`.
111 /// [Docs](https://tailwindcss.com/docs/cursor)
112 fn cursor_text(mut self) -> Self {
113 self.style().mouse_cursor = Some(CursorStyle::IBeam);
114 self
115 }
116
117 /// Sets cursor style when hovering over an element to `move`.
118 /// [Docs](https://tailwindcss.com/docs/cursor)
119 fn cursor_move(mut self) -> Self {
120 self.style().mouse_cursor = Some(CursorStyle::ClosedHand);
121 self
122 }
123
124 /// Sets cursor style when hovering over an element to `not-allowed`.
125 /// [Docs](https://tailwindcss.com/docs/cursor)
126 fn cursor_not_allowed(mut self) -> Self {
127 self.style().mouse_cursor = Some(CursorStyle::OperationNotAllowed);
128 self
129 }
130
131 /// Sets cursor style when hovering over an element to `context-menu`.
132 /// [Docs](https://tailwindcss.com/docs/cursor)
133 fn cursor_context_menu(mut self) -> Self {
134 self.style().mouse_cursor = Some(CursorStyle::ContextualMenu);
135 self
136 }
137
138 /// Sets cursor style when hovering over an element to `crosshair`.
139 /// [Docs](https://tailwindcss.com/docs/cursor)
140 fn cursor_crosshair(mut self) -> Self {
141 self.style().mouse_cursor = Some(CursorStyle::Crosshair);
142 self
143 }
144
145 /// Sets cursor style when hovering over an element to `vertical-text`.
146 /// [Docs](https://tailwindcss.com/docs/cursor)
147 fn cursor_vertical_text(mut self) -> Self {
148 self.style().mouse_cursor = Some(CursorStyle::IBeamCursorForVerticalLayout);
149 self
150 }
151
152 /// Sets cursor style when hovering over an element to `alias`.
153 /// [Docs](https://tailwindcss.com/docs/cursor)
154 fn cursor_alias(mut self) -> Self {
155 self.style().mouse_cursor = Some(CursorStyle::DragLink);
156 self
157 }
158
159 /// Sets cursor style when hovering over an element to `copy`.
160 /// [Docs](https://tailwindcss.com/docs/cursor)
161 fn cursor_copy(mut self) -> Self {
162 self.style().mouse_cursor = Some(CursorStyle::DragCopy);
163 self
164 }
165
166 /// Sets cursor style when hovering over an element to `no-drop`.
167 /// [Docs](https://tailwindcss.com/docs/cursor)
168 fn cursor_no_drop(mut self) -> Self {
169 self.style().mouse_cursor = Some(CursorStyle::OperationNotAllowed);
170 self
171 }
172
173 /// Sets cursor style when hovering over an element to `grab`.
174 /// [Docs](https://tailwindcss.com/docs/cursor)
175 fn cursor_grab(mut self) -> Self {
176 self.style().mouse_cursor = Some(CursorStyle::OpenHand);
177 self
178 }
179
180 /// Sets cursor style when hovering over an element to `grabbing`.
181 /// [Docs](https://tailwindcss.com/docs/cursor)
182 fn cursor_grabbing(mut self) -> Self {
183 self.style().mouse_cursor = Some(CursorStyle::ClosedHand);
184 self
185 }
186
187 /// Sets cursor style when hovering over an element to `col-resize`.
188 /// [Docs](https://tailwindcss.com/docs/cursor)
189 fn cursor_col_resize(mut self) -> Self {
190 self.style().mouse_cursor = Some(CursorStyle::ResizeLeftRight);
191 self
192 }
193
194 /// Sets cursor style when hovering over an element to `row-resize`.
195 /// [Docs](https://tailwindcss.com/docs/cursor)
196 fn cursor_row_resize(mut self) -> Self {
197 self.style().mouse_cursor = Some(CursorStyle::ResizeUpDown);
198 self
199 }
200
201 /// Sets cursor style when hovering over an element to `n-resize`.
202 /// [Docs](https://tailwindcss.com/docs/cursor)
203 fn cursor_n_resize(mut self) -> Self {
204 self.style().mouse_cursor = Some(CursorStyle::ResizeUp);
205 self
206 }
207
208 /// Sets cursor style when hovering over an element to `e-resize`.
209 /// [Docs](https://tailwindcss.com/docs/cursor)
210 fn cursor_e_resize(mut self) -> Self {
211 self.style().mouse_cursor = Some(CursorStyle::ResizeRight);
212 self
213 }
214
215 /// Sets cursor style when hovering over an element to `s-resize`.
216 /// [Docs](https://tailwindcss.com/docs/cursor)
217 fn cursor_s_resize(mut self) -> Self {
218 self.style().mouse_cursor = Some(CursorStyle::ResizeDown);
219 self
220 }
221
222 /// Sets cursor style when hovering over an element to `w-resize`.
223 /// [Docs](https://tailwindcss.com/docs/cursor)
224 fn cursor_w_resize(mut self) -> Self {
225 self.style().mouse_cursor = Some(CursorStyle::ResizeLeft);
226 self
227 }
228
229 /// Sets the whitespace of the element to `normal`.
230 /// [Docs](https://tailwindcss.com/docs/whitespace#normal)
231 fn whitespace_normal(mut self) -> Self {
232 self.text_style()
233 .get_or_insert_with(Default::default)
234 .white_space = Some(WhiteSpace::Normal);
235 self
236 }
237
238 /// Sets the whitespace of the element to `nowrap`.
239 /// [Docs](https://tailwindcss.com/docs/whitespace#nowrap)
240 fn whitespace_nowrap(mut self) -> Self {
241 self.text_style()
242 .get_or_insert_with(Default::default)
243 .white_space = Some(WhiteSpace::Nowrap);
244 self
245 }
246
247 /// Sets the flex direction of the element to `column`.
248 /// [Docs](https://tailwindcss.com/docs/flex-direction#column)
249 fn flex_col(mut self) -> Self {
250 self.style().flex_direction = Some(FlexDirection::Column);
251 self
252 }
253
254 /// Sets the flex direction of the element to `column-reverse`.
255 /// [Docs](https://tailwindcss.com/docs/flex-direction#column-reverse)
256 fn flex_col_reverse(mut self) -> Self {
257 self.style().flex_direction = Some(FlexDirection::ColumnReverse);
258 self
259 }
260
261 /// Sets the flex direction of the element to `row`.
262 /// [Docs](https://tailwindcss.com/docs/flex-direction#row)
263 fn flex_row(mut self) -> Self {
264 self.style().flex_direction = Some(FlexDirection::Row);
265 self
266 }
267
268 /// Sets the flex direction of the element to `row-reverse`.
269 /// [Docs](https://tailwindcss.com/docs/flex-direction#row-reverse)
270 fn flex_row_reverse(mut self) -> Self {
271 self.style().flex_direction = Some(FlexDirection::RowReverse);
272 self
273 }
274
275 /// Sets the element to allow a flex item to grow and shrink as needed, ignoring its initial size.
276 /// [Docs](https://tailwindcss.com/docs/flex#flex-1)
277 fn flex_1(mut self) -> Self {
278 self.style().flex_grow = Some(1.);
279 self.style().flex_shrink = Some(1.);
280 self.style().flex_basis = Some(relative(0.).into());
281 self
282 }
283
284 /// Sets the element to allow a flex item to grow and shrink, taking into account its initial size.
285 /// [Docs](https://tailwindcss.com/docs/flex#auto)
286 fn flex_auto(mut self) -> Self {
287 self.style().flex_grow = Some(1.);
288 self.style().flex_shrink = Some(1.);
289 self.style().flex_basis = Some(Length::Auto);
290 self
291 }
292
293 /// Sets the element to allow a flex item to shrink but not grow, taking into account its initial size.
294 /// [Docs](https://tailwindcss.com/docs/flex#initial)
295 fn flex_initial(mut self) -> Self {
296 self.style().flex_grow = Some(0.);
297 self.style().flex_shrink = Some(1.);
298 self.style().flex_basis = Some(Length::Auto);
299 self
300 }
301
302 /// Sets the element to prevent a flex item from growing or shrinking.
303 /// [Docs](https://tailwindcss.com/docs/flex#none)
304 fn flex_none(mut self) -> Self {
305 self.style().flex_grow = Some(0.);
306 self.style().flex_shrink = Some(0.);
307 self
308 }
309
310 /// Sets the initial size of flex items for this element.
311 /// [Docs](https://tailwindcss.com/docs/flex-basis)
312 fn flex_basis(mut self, basis: impl Into<Length>) -> Self {
313 self.style().flex_basis = Some(basis.into());
314 self
315 }
316
317 /// Sets the element to allow a flex item to grow to fill any available space.
318 /// [Docs](https://tailwindcss.com/docs/flex-grow)
319 fn flex_grow(mut self) -> Self {
320 self.style().flex_grow = Some(1.);
321 self
322 }
323
324 /// Sets the element to allow a flex item to shrink if needed.
325 /// [Docs](https://tailwindcss.com/docs/flex-shrink)
326 fn flex_shrink(mut self) -> Self {
327 self.style().flex_shrink = Some(1.);
328 self
329 }
330
331 /// Sets the element to prevent a flex item from shrinking.
332 /// [Docs](https://tailwindcss.com/docs/flex-shrink#dont-shrink)
333 fn flex_shrink_0(mut self) -> Self {
334 self.style().flex_shrink = Some(0.);
335 self
336 }
337
338 /// Sets the element to align flex items to the start of the container's cross axis.
339 /// [Docs](https://tailwindcss.com/docs/align-items#start)
340 fn items_start(mut self) -> Self {
341 self.style().align_items = Some(AlignItems::FlexStart);
342 self
343 }
344
345 /// Sets the element to align flex items to the end of the container's cross axis.
346 /// [Docs](https://tailwindcss.com/docs/align-items#end)
347 fn items_end(mut self) -> Self {
348 self.style().align_items = Some(AlignItems::FlexEnd);
349 self
350 }
351
352 /// Sets the element to align flex items along the center of the container's cross axis.
353 /// [Docs](https://tailwindcss.com/docs/align-items#center)
354 fn items_center(mut self) -> Self {
355 self.style().align_items = Some(AlignItems::Center);
356 self
357 }
358
359 /// Sets the element to justify flex items along the container's main axis
360 /// such that there is an equal amount of space between each item.
361 /// [Docs](https://tailwindcss.com/docs/justify-content#space-between)
362 fn justify_between(mut self) -> Self {
363 self.style().justify_content = Some(JustifyContent::SpaceBetween);
364 self
365 }
366
367 /// Sets the element to justify flex items along the center of the container's main axis.
368 /// [Docs](https://tailwindcss.com/docs/justify-content#center)
369 fn justify_center(mut self) -> Self {
370 self.style().justify_content = Some(JustifyContent::Center);
371 self
372 }
373
374 /// Sets the element to justify flex items against the start of the container's main axis.
375 /// [Docs](https://tailwindcss.com/docs/justify-content#start)
376 fn justify_start(mut self) -> Self {
377 self.style().justify_content = Some(JustifyContent::Start);
378 self
379 }
380
381 /// Sets the element to justify flex items against the end of the container's main axis.
382 /// [Docs](https://tailwindcss.com/docs/justify-content#end)
383 fn justify_end(mut self) -> Self {
384 self.style().justify_content = Some(JustifyContent::End);
385 self
386 }
387
388 /// Sets the element to justify items along the container's main axis such
389 /// that there is an equal amount of space on each side of each item.
390 /// [Docs](https://tailwindcss.com/docs/justify-content#space-around)
391 fn justify_around(mut self) -> Self {
392 self.style().justify_content = Some(JustifyContent::SpaceAround);
393 self
394 }
395
396 /// Sets the background color of the element.
397 fn bg<F>(mut self, fill: F) -> Self
398 where
399 F: Into<Fill>,
400 Self: Sized,
401 {
402 self.style().background = Some(fill.into());
403 self
404 }
405
406 /// Sets the border color of the element.
407 fn border_color<C>(mut self, border_color: C) -> Self
408 where
409 C: Into<Hsla>,
410 Self: Sized,
411 {
412 self.style().border_color = Some(border_color.into());
413 self
414 }
415
416 /// Sets the box shadow of the element.
417 /// [Docs](https://tailwindcss.com/docs/box-shadow)
418 fn shadow(mut self, shadows: SmallVec<[BoxShadow; 2]>) -> Self {
419 self.style().box_shadow = Some(shadows);
420 self
421 }
422
423 /// Clears the box shadow of the element.
424 /// [Docs](https://tailwindcss.com/docs/box-shadow)
425 fn shadow_none(mut self) -> Self {
426 self.style().box_shadow = Some(Default::default());
427 self
428 }
429
430 /// Sets the box shadow of the element.
431 /// [Docs](https://tailwindcss.com/docs/box-shadow)
432 fn shadow_sm(mut self) -> Self {
433 self.style().box_shadow = Some(smallvec::smallvec![BoxShadow {
434 color: hsla(0., 0., 0., 0.05),
435 offset: point(px(0.), px(1.)),
436 blur_radius: px(2.),
437 spread_radius: px(0.),
438 }]);
439 self
440 }
441
442 /// Sets the box shadow of the element.
443 /// [Docs](https://tailwindcss.com/docs/box-shadow)
444 fn shadow_md(mut self) -> Self {
445 self.style().box_shadow = Some(smallvec![
446 BoxShadow {
447 color: hsla(0.5, 0., 0., 0.1),
448 offset: point(px(0.), px(4.)),
449 blur_radius: px(6.),
450 spread_radius: px(-1.),
451 },
452 BoxShadow {
453 color: hsla(0., 0., 0., 0.1),
454 offset: point(px(0.), px(2.)),
455 blur_radius: px(4.),
456 spread_radius: px(-2.),
457 }
458 ]);
459 self
460 }
461
462 /// Sets the box shadow of the element.
463 /// [Docs](https://tailwindcss.com/docs/box-shadow)
464 fn shadow_lg(mut self) -> Self {
465 self.style().box_shadow = Some(smallvec![
466 BoxShadow {
467 color: hsla(0., 0., 0., 0.1),
468 offset: point(px(0.), px(10.)),
469 blur_radius: px(15.),
470 spread_radius: px(-3.),
471 },
472 BoxShadow {
473 color: hsla(0., 0., 0., 0.1),
474 offset: point(px(0.), px(4.)),
475 blur_radius: px(6.),
476 spread_radius: px(-4.),
477 }
478 ]);
479 self
480 }
481
482 /// Sets the box shadow of the element.
483 /// [Docs](https://tailwindcss.com/docs/box-shadow)
484 fn shadow_xl(mut self) -> Self {
485 self.style().box_shadow = Some(smallvec![
486 BoxShadow {
487 color: hsla(0., 0., 0., 0.1),
488 offset: point(px(0.), px(20.)),
489 blur_radius: px(25.),
490 spread_radius: px(-5.),
491 },
492 BoxShadow {
493 color: hsla(0., 0., 0., 0.1),
494 offset: point(px(0.), px(8.)),
495 blur_radius: px(10.),
496 spread_radius: px(-6.),
497 }
498 ]);
499 self
500 }
501
502 /// Sets the box shadow of the element.
503 /// [Docs](https://tailwindcss.com/docs/box-shadow)
504 fn shadow_2xl(mut self) -> Self {
505 self.style().box_shadow = Some(smallvec![BoxShadow {
506 color: hsla(0., 0., 0., 0.25),
507 offset: point(px(0.), px(25.)),
508 blur_radius: px(50.),
509 spread_radius: px(-12.),
510 }]);
511 self
512 }
513
514 fn text_style(&mut self) -> &mut Option<TextStyleRefinement> {
515 let style: &mut StyleRefinement = self.style();
516 &mut style.text
517 }
518
519 fn text_color(mut self, color: impl Into<Hsla>) -> Self {
520 self.text_style().get_or_insert_with(Default::default).color = Some(color.into());
521 self
522 }
523
524 fn font_weight(mut self, weight: FontWeight) -> Self {
525 self.text_style()
526 .get_or_insert_with(Default::default)
527 .font_weight = Some(weight);
528 self
529 }
530
531 fn text_bg(mut self, bg: impl Into<Hsla>) -> Self {
532 self.text_style()
533 .get_or_insert_with(Default::default)
534 .background_color = Some(bg.into());
535 self
536 }
537
538 fn text_size(mut self, size: impl Into<AbsoluteLength>) -> Self {
539 self.text_style()
540 .get_or_insert_with(Default::default)
541 .font_size = Some(size.into());
542 self
543 }
544
545 fn text_xs(mut self) -> Self {
546 self.text_style()
547 .get_or_insert_with(Default::default)
548 .font_size = Some(rems(0.75).into());
549 self
550 }
551
552 fn text_sm(mut self) -> Self {
553 self.text_style()
554 .get_or_insert_with(Default::default)
555 .font_size = Some(rems(0.875).into());
556 self
557 }
558
559 fn text_base(mut self) -> Self {
560 self.text_style()
561 .get_or_insert_with(Default::default)
562 .font_size = Some(rems(1.0).into());
563 self
564 }
565
566 fn text_lg(mut self) -> Self {
567 self.text_style()
568 .get_or_insert_with(Default::default)
569 .font_size = Some(rems(1.125).into());
570 self
571 }
572
573 fn text_xl(mut self) -> Self {
574 self.text_style()
575 .get_or_insert_with(Default::default)
576 .font_size = Some(rems(1.25).into());
577 self
578 }
579
580 fn text_2xl(mut self) -> Self {
581 self.text_style()
582 .get_or_insert_with(Default::default)
583 .font_size = Some(rems(1.5).into());
584 self
585 }
586
587 fn text_3xl(mut self) -> Self {
588 self.text_style()
589 .get_or_insert_with(Default::default)
590 .font_size = Some(rems(1.875).into());
591 self
592 }
593
594 fn text_decoration_none(mut self) -> Self {
595 self.text_style()
596 .get_or_insert_with(Default::default)
597 .underline = None;
598 self
599 }
600
601 fn text_decoration_color(mut self, color: impl Into<Hsla>) -> Self {
602 let style = self.text_style().get_or_insert_with(Default::default);
603 let underline = style.underline.get_or_insert_with(Default::default);
604 underline.color = Some(color.into());
605 self
606 }
607
608 fn text_decoration_solid(mut self) -> Self {
609 let style = self.text_style().get_or_insert_with(Default::default);
610 let underline = style.underline.get_or_insert_with(Default::default);
611 underline.wavy = false;
612 self
613 }
614
615 fn text_decoration_wavy(mut self) -> Self {
616 let style = self.text_style().get_or_insert_with(Default::default);
617 let underline = style.underline.get_or_insert_with(Default::default);
618 underline.wavy = true;
619 self
620 }
621
622 fn text_decoration_0(mut self) -> Self {
623 let style = self.text_style().get_or_insert_with(Default::default);
624 let underline = style.underline.get_or_insert_with(Default::default);
625 underline.thickness = px(0.);
626 self
627 }
628
629 fn text_decoration_1(mut self) -> Self {
630 let style = self.text_style().get_or_insert_with(Default::default);
631 let underline = style.underline.get_or_insert_with(Default::default);
632 underline.thickness = px(1.);
633 self
634 }
635
636 fn text_decoration_2(mut self) -> Self {
637 let style = self.text_style().get_or_insert_with(Default::default);
638 let underline = style.underline.get_or_insert_with(Default::default);
639 underline.thickness = px(2.);
640 self
641 }
642
643 fn text_decoration_4(mut self) -> Self {
644 let style = self.text_style().get_or_insert_with(Default::default);
645 let underline = style.underline.get_or_insert_with(Default::default);
646 underline.thickness = px(4.);
647 self
648 }
649
650 fn text_decoration_8(mut self) -> Self {
651 let style = self.text_style().get_or_insert_with(Default::default);
652 let underline = style.underline.get_or_insert_with(Default::default);
653 underline.thickness = px(8.);
654 self
655 }
656
657 fn font(mut self, family_name: impl Into<SharedString>) -> Self {
658 self.text_style()
659 .get_or_insert_with(Default::default)
660 .font_family = Some(family_name.into());
661 self
662 }
663
664 fn line_height(mut self, line_height: impl Into<DefiniteLength>) -> Self {
665 self.text_style()
666 .get_or_insert_with(Default::default)
667 .line_height = Some(line_height.into());
668 self
669 }
670
671 #[cfg(debug_assertions)]
672 fn debug(mut self) -> Self {
673 self.style().debug = Some(true);
674 self
675 }
676
677 #[cfg(debug_assertions)]
678 fn debug_below(mut self) -> Self {
679 self.style().debug_below = Some(true);
680 self
681 }
682}