1use crate::{
2 self as gpui, hsla, point, px, relative, rems, AbsoluteLength, AlignItems, CursorStyle,
3 DefiniteLength, Display, Fill, FlexDirection, FontWeight, Hsla, JustifyContent, Length,
4 Position, SharedString, StyleRefinement, Visibility, WhiteSpace,
5};
6use crate::{BoxShadow, TextStyleRefinement};
7use smallvec::{smallvec, SmallVec};
8use taffy::style::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: u8) -> 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 element to allow a flex item to grow to fill any available space.
311 /// [Docs](https://tailwindcss.com/docs/flex-grow)
312 fn flex_grow(mut self) -> Self {
313 self.style().flex_grow = Some(1.);
314 self
315 }
316
317 /// Sets the element to align flex items to the start of the container's cross axis.
318 /// [Docs](https://tailwindcss.com/docs/align-items#start)
319 fn items_start(mut self) -> Self {
320 self.style().align_items = Some(AlignItems::FlexStart);
321 self
322 }
323
324 /// Sets the element to align flex items to the end of the container's cross axis.
325 /// [Docs](https://tailwindcss.com/docs/align-items#end)
326 fn items_end(mut self) -> Self {
327 self.style().align_items = Some(AlignItems::FlexEnd);
328 self
329 }
330
331 /// Sets the element to align flex items along the center of the container's cross axis.
332 /// [Docs](https://tailwindcss.com/docs/align-items#center)
333 fn items_center(mut self) -> Self {
334 self.style().align_items = Some(AlignItems::Center);
335 self
336 }
337
338 /// Sets the element to justify flex items along the container's main axis
339 /// such that there is an equal amount of space between each item.
340 /// [Docs](https://tailwindcss.com/docs/justify-content#space-between)
341 fn justify_between(mut self) -> Self {
342 self.style().justify_content = Some(JustifyContent::SpaceBetween);
343 self
344 }
345
346 /// Sets the element to justify flex items along the center of the container's main axis.
347 /// [Docs](https://tailwindcss.com/docs/justify-content#center)
348 fn justify_center(mut self) -> Self {
349 self.style().justify_content = Some(JustifyContent::Center);
350 self
351 }
352
353 /// Sets the element to justify flex items against the start of the container's main axis.
354 /// [Docs](https://tailwindcss.com/docs/justify-content#start)
355 fn justify_start(mut self) -> Self {
356 self.style().justify_content = Some(JustifyContent::Start);
357 self
358 }
359
360 /// Sets the element to justify flex items against the end of the container's main axis.
361 /// [Docs](https://tailwindcss.com/docs/justify-content#end)
362 fn justify_end(mut self) -> Self {
363 self.style().justify_content = Some(JustifyContent::End);
364 self
365 }
366
367 /// Sets the element to justify items along the container's main axis such
368 /// that there is an equal amount of space on each side of each item.
369 /// [Docs](https://tailwindcss.com/docs/justify-content#space-around)
370 fn justify_around(mut self) -> Self {
371 self.style().justify_content = Some(JustifyContent::SpaceAround);
372 self
373 }
374
375 /// Sets the background color of the element.
376 fn bg<F>(mut self, fill: F) -> Self
377 where
378 F: Into<Fill>,
379 Self: Sized,
380 {
381 self.style().background = Some(fill.into());
382 self
383 }
384
385 /// Sets the border color of the element.
386 fn border_color<C>(mut self, border_color: C) -> Self
387 where
388 C: Into<Hsla>,
389 Self: Sized,
390 {
391 self.style().border_color = Some(border_color.into());
392 self
393 }
394
395 /// Sets the box shadow of the element.
396 /// [Docs](https://tailwindcss.com/docs/box-shadow)
397 fn shadow(mut self, shadows: SmallVec<[BoxShadow; 2]>) -> Self {
398 self.style().box_shadow = Some(shadows);
399 self
400 }
401
402 /// Clears the box shadow of the element.
403 /// [Docs](https://tailwindcss.com/docs/box-shadow)
404 fn shadow_none(mut self) -> Self {
405 self.style().box_shadow = Some(Default::default());
406 self
407 }
408
409 /// Sets the box shadow of the element.
410 /// [Docs](https://tailwindcss.com/docs/box-shadow)
411 fn shadow_sm(mut self) -> Self {
412 self.style().box_shadow = Some(smallvec::smallvec![BoxShadow {
413 color: hsla(0., 0., 0., 0.05),
414 offset: point(px(0.), px(1.)),
415 blur_radius: px(2.),
416 spread_radius: px(0.),
417 }]);
418 self
419 }
420
421 /// Sets the box shadow of the element.
422 /// [Docs](https://tailwindcss.com/docs/box-shadow)
423 fn shadow_md(mut self) -> Self {
424 self.style().box_shadow = Some(smallvec![
425 BoxShadow {
426 color: hsla(0.5, 0., 0., 0.1),
427 offset: point(px(0.), px(4.)),
428 blur_radius: px(6.),
429 spread_radius: px(-1.),
430 },
431 BoxShadow {
432 color: hsla(0., 0., 0., 0.1),
433 offset: point(px(0.), px(2.)),
434 blur_radius: px(4.),
435 spread_radius: px(-2.),
436 }
437 ]);
438 self
439 }
440
441 /// Sets the box shadow of the element.
442 /// [Docs](https://tailwindcss.com/docs/box-shadow)
443 fn shadow_lg(mut self) -> Self {
444 self.style().box_shadow = Some(smallvec![
445 BoxShadow {
446 color: hsla(0., 0., 0., 0.1),
447 offset: point(px(0.), px(10.)),
448 blur_radius: px(15.),
449 spread_radius: px(-3.),
450 },
451 BoxShadow {
452 color: hsla(0., 0., 0., 0.1),
453 offset: point(px(0.), px(4.)),
454 blur_radius: px(6.),
455 spread_radius: px(-4.),
456 }
457 ]);
458 self
459 }
460
461 /// Sets the box shadow of the element.
462 /// [Docs](https://tailwindcss.com/docs/box-shadow)
463 fn shadow_xl(mut self) -> Self {
464 self.style().box_shadow = Some(smallvec![
465 BoxShadow {
466 color: hsla(0., 0., 0., 0.1),
467 offset: point(px(0.), px(20.)),
468 blur_radius: px(25.),
469 spread_radius: px(-5.),
470 },
471 BoxShadow {
472 color: hsla(0., 0., 0., 0.1),
473 offset: point(px(0.), px(8.)),
474 blur_radius: px(10.),
475 spread_radius: px(-6.),
476 }
477 ]);
478 self
479 }
480
481 /// Sets the box shadow of the element.
482 /// [Docs](https://tailwindcss.com/docs/box-shadow)
483 fn shadow_2xl(mut self) -> Self {
484 self.style().box_shadow = Some(smallvec![BoxShadow {
485 color: hsla(0., 0., 0., 0.25),
486 offset: point(px(0.), px(25.)),
487 blur_radius: px(50.),
488 spread_radius: px(-12.),
489 }]);
490 self
491 }
492
493 fn text_style(&mut self) -> &mut Option<TextStyleRefinement> {
494 let style: &mut StyleRefinement = self.style();
495 &mut style.text
496 }
497
498 fn text_color(mut self, color: impl Into<Hsla>) -> Self {
499 self.text_style().get_or_insert_with(Default::default).color = Some(color.into());
500 self
501 }
502
503 fn font_weight(mut self, weight: FontWeight) -> Self {
504 self.text_style()
505 .get_or_insert_with(Default::default)
506 .font_weight = Some(weight);
507 self
508 }
509
510 fn text_bg(mut self, bg: impl Into<Hsla>) -> Self {
511 self.text_style()
512 .get_or_insert_with(Default::default)
513 .background_color = Some(bg.into());
514 self
515 }
516
517 fn text_size(mut self, size: impl Into<AbsoluteLength>) -> Self {
518 self.text_style()
519 .get_or_insert_with(Default::default)
520 .font_size = Some(size.into());
521 self
522 }
523
524 fn text_xs(mut self) -> Self {
525 self.text_style()
526 .get_or_insert_with(Default::default)
527 .font_size = Some(rems(0.75).into());
528 self
529 }
530
531 fn text_sm(mut self) -> Self {
532 self.text_style()
533 .get_or_insert_with(Default::default)
534 .font_size = Some(rems(0.875).into());
535 self
536 }
537
538 fn text_base(mut self) -> Self {
539 self.text_style()
540 .get_or_insert_with(Default::default)
541 .font_size = Some(rems(1.0).into());
542 self
543 }
544
545 fn text_lg(mut self) -> Self {
546 self.text_style()
547 .get_or_insert_with(Default::default)
548 .font_size = Some(rems(1.125).into());
549 self
550 }
551
552 fn text_xl(mut self) -> Self {
553 self.text_style()
554 .get_or_insert_with(Default::default)
555 .font_size = Some(rems(1.25).into());
556 self
557 }
558
559 fn text_2xl(mut self) -> Self {
560 self.text_style()
561 .get_or_insert_with(Default::default)
562 .font_size = Some(rems(1.5).into());
563 self
564 }
565
566 fn text_3xl(mut self) -> Self {
567 self.text_style()
568 .get_or_insert_with(Default::default)
569 .font_size = Some(rems(1.875).into());
570 self
571 }
572
573 fn text_decoration_none(mut self) -> Self {
574 self.text_style()
575 .get_or_insert_with(Default::default)
576 .underline = None;
577 self
578 }
579
580 fn text_decoration_color(mut self, color: impl Into<Hsla>) -> Self {
581 let style = self.text_style().get_or_insert_with(Default::default);
582 let underline = style.underline.get_or_insert_with(Default::default);
583 underline.color = Some(color.into());
584 self
585 }
586
587 fn text_decoration_solid(mut self) -> Self {
588 let style = self.text_style().get_or_insert_with(Default::default);
589 let underline = style.underline.get_or_insert_with(Default::default);
590 underline.wavy = false;
591 self
592 }
593
594 fn text_decoration_wavy(mut self) -> Self {
595 let style = self.text_style().get_or_insert_with(Default::default);
596 let underline = style.underline.get_or_insert_with(Default::default);
597 underline.wavy = true;
598 self
599 }
600
601 fn text_decoration_0(mut self) -> 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.thickness = px(0.);
605 self
606 }
607
608 fn text_decoration_1(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.thickness = px(1.);
612 self
613 }
614
615 fn text_decoration_2(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.thickness = px(2.);
619 self
620 }
621
622 fn text_decoration_4(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(4.);
626 self
627 }
628
629 fn text_decoration_8(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(8.);
633 self
634 }
635
636 fn font(mut self, family_name: impl Into<SharedString>) -> Self {
637 self.text_style()
638 .get_or_insert_with(Default::default)
639 .font_family = Some(family_name.into());
640 self
641 }
642
643 fn line_height(mut self, line_height: impl Into<DefiniteLength>) -> Self {
644 self.text_style()
645 .get_or_insert_with(Default::default)
646 .line_height = Some(line_height.into());
647 self
648 }
649
650 #[cfg(debug_assertions)]
651 fn debug(mut self) -> Self {
652 self.style().debug = Some(true);
653 self
654 }
655
656 #[cfg(debug_assertions)]
657 fn debug_below(mut self) -> Self {
658 self.style().debug_below = Some(true);
659 self
660 }
661}