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