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, 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, shadows: SmallVec<[BoxShadow; 2]>) -> Self
299 where
300 Self: Sized,
301 {
302 self.style().box_shadow = Some(shadows);
303 self
304 }
305
306 /// Clears the box shadow of the element.
307 /// [Docs](https://tailwindcss.com/docs/box-shadow)
308 fn shadow_none(mut self) -> Self
309 where
310 Self: Sized,
311 {
312 self.style().box_shadow = Some(Default::default());
313 self
314 }
315
316 /// Sets the box shadow of the element.
317 /// [Docs](https://tailwindcss.com/docs/box-shadow)
318 fn shadow_sm(mut self) -> Self
319 where
320 Self: Sized,
321 {
322 self.style().box_shadow = Some(smallvec::smallvec![BoxShadow {
323 color: hsla(0., 0., 0., 0.05),
324 offset: point(px(0.), px(1.)),
325 blur_radius: px(2.),
326 spread_radius: px(0.),
327 }]);
328 self
329 }
330
331 /// Sets the box shadow of the element.
332 /// [Docs](https://tailwindcss.com/docs/box-shadow)
333 fn shadow_md(mut self) -> Self
334 where
335 Self: Sized,
336 {
337 self.style().box_shadow = Some(smallvec![
338 BoxShadow {
339 color: hsla(0.5, 0., 0., 0.1),
340 offset: point(px(0.), px(4.)),
341 blur_radius: px(6.),
342 spread_radius: px(-1.),
343 },
344 BoxShadow {
345 color: hsla(0., 0., 0., 0.1),
346 offset: point(px(0.), px(2.)),
347 blur_radius: px(4.),
348 spread_radius: px(-2.),
349 }
350 ]);
351 self
352 }
353
354 /// Sets the box shadow of the element.
355 /// [Docs](https://tailwindcss.com/docs/box-shadow)
356 fn shadow_lg(mut self) -> Self
357 where
358 Self: Sized,
359 {
360 self.style().box_shadow = Some(smallvec![
361 BoxShadow {
362 color: hsla(0., 0., 0., 0.1),
363 offset: point(px(0.), px(10.)),
364 blur_radius: px(15.),
365 spread_radius: px(-3.),
366 },
367 BoxShadow {
368 color: hsla(0., 0., 0., 0.1),
369 offset: point(px(0.), px(4.)),
370 blur_radius: px(6.),
371 spread_radius: px(-4.),
372 }
373 ]);
374 self
375 }
376
377 /// Sets the box shadow of the element.
378 /// [Docs](https://tailwindcss.com/docs/box-shadow)
379 fn shadow_xl(mut self) -> Self
380 where
381 Self: Sized,
382 {
383 self.style().box_shadow = Some(smallvec![
384 BoxShadow {
385 color: hsla(0., 0., 0., 0.1),
386 offset: point(px(0.), px(20.)),
387 blur_radius: px(25.),
388 spread_radius: px(-5.),
389 },
390 BoxShadow {
391 color: hsla(0., 0., 0., 0.1),
392 offset: point(px(0.), px(8.)),
393 blur_radius: px(10.),
394 spread_radius: px(-6.),
395 }
396 ]);
397 self
398 }
399
400 /// Sets the box shadow of the element.
401 /// [Docs](https://tailwindcss.com/docs/box-shadow)
402 fn shadow_2xl(mut self) -> Self
403 where
404 Self: Sized,
405 {
406 self.style().box_shadow = Some(smallvec![BoxShadow {
407 color: hsla(0., 0., 0., 0.25),
408 offset: point(px(0.), px(25.)),
409 blur_radius: px(50.),
410 spread_radius: px(-12.),
411 }]);
412 self
413 }
414
415 fn text_style(&mut self) -> &mut Option<TextStyleRefinement> {
416 let style: &mut StyleRefinement = self.style();
417 &mut style.text
418 }
419
420 fn text_color(mut self, color: impl Into<Hsla>) -> Self
421 where
422 Self: Sized,
423 {
424 self.text_style().get_or_insert_with(Default::default).color = Some(color.into());
425 self
426 }
427
428 fn text_size(mut self, size: impl Into<AbsoluteLength>) -> Self
429 where
430 Self: Sized,
431 {
432 self.text_style()
433 .get_or_insert_with(Default::default)
434 .font_size = Some(size.into());
435 self
436 }
437
438 fn text_xs(mut self) -> Self
439 where
440 Self: Sized,
441 {
442 self.text_style()
443 .get_or_insert_with(Default::default)
444 .font_size = Some(rems(0.75).into());
445 self
446 }
447
448 fn text_sm(mut self) -> Self
449 where
450 Self: Sized,
451 {
452 self.text_style()
453 .get_or_insert_with(Default::default)
454 .font_size = Some(rems(0.875).into());
455 self
456 }
457
458 fn text_base(mut self) -> Self
459 where
460 Self: Sized,
461 {
462 self.text_style()
463 .get_or_insert_with(Default::default)
464 .font_size = Some(rems(1.0).into());
465 self
466 }
467
468 fn text_lg(mut self) -> Self
469 where
470 Self: Sized,
471 {
472 self.text_style()
473 .get_or_insert_with(Default::default)
474 .font_size = Some(rems(1.125).into());
475 self
476 }
477
478 fn text_xl(mut self) -> Self
479 where
480 Self: Sized,
481 {
482 self.text_style()
483 .get_or_insert_with(Default::default)
484 .font_size = Some(rems(1.25).into());
485 self
486 }
487
488 fn text_2xl(mut self) -> Self
489 where
490 Self: Sized,
491 {
492 self.text_style()
493 .get_or_insert_with(Default::default)
494 .font_size = Some(rems(1.5).into());
495 self
496 }
497
498 fn text_3xl(mut self) -> Self
499 where
500 Self: Sized,
501 {
502 self.text_style()
503 .get_or_insert_with(Default::default)
504 .font_size = Some(rems(1.875).into());
505 self
506 }
507
508 fn text_decoration_none(mut self) -> Self
509 where
510 Self: Sized,
511 {
512 self.text_style()
513 .get_or_insert_with(Default::default)
514 .underline = None;
515 self
516 }
517
518 fn text_decoration_color(mut self, color: impl Into<Hsla>) -> Self
519 where
520 Self: Sized,
521 {
522 let style = self.text_style().get_or_insert_with(Default::default);
523 let underline = style.underline.get_or_insert_with(Default::default);
524 underline.color = Some(color.into());
525 self
526 }
527
528 fn text_decoration_solid(mut self) -> Self
529 where
530 Self: Sized,
531 {
532 let style = self.text_style().get_or_insert_with(Default::default);
533 let underline = style.underline.get_or_insert_with(Default::default);
534 underline.wavy = false;
535 self
536 }
537
538 fn text_decoration_wavy(mut self) -> Self
539 where
540 Self: Sized,
541 {
542 let style = self.text_style().get_or_insert_with(Default::default);
543 let underline = style.underline.get_or_insert_with(Default::default);
544 underline.wavy = true;
545 self
546 }
547
548 fn text_decoration_0(mut self) -> Self
549 where
550 Self: Sized,
551 {
552 let style = self.text_style().get_or_insert_with(Default::default);
553 let underline = style.underline.get_or_insert_with(Default::default);
554 underline.thickness = px(0.);
555 self
556 }
557
558 fn text_decoration_1(mut self) -> Self
559 where
560 Self: Sized,
561 {
562 let style = self.text_style().get_or_insert_with(Default::default);
563 let underline = style.underline.get_or_insert_with(Default::default);
564 underline.thickness = px(1.);
565 self
566 }
567
568 fn text_decoration_2(mut self) -> Self
569 where
570 Self: Sized,
571 {
572 let style = self.text_style().get_or_insert_with(Default::default);
573 let underline = style.underline.get_or_insert_with(Default::default);
574 underline.thickness = px(2.);
575 self
576 }
577
578 fn text_decoration_4(mut self) -> Self
579 where
580 Self: Sized,
581 {
582 let style = self.text_style().get_or_insert_with(Default::default);
583 let underline = style.underline.get_or_insert_with(Default::default);
584 underline.thickness = px(4.);
585 self
586 }
587
588 fn text_decoration_8(mut self) -> Self
589 where
590 Self: Sized,
591 {
592 let style = self.text_style().get_or_insert_with(Default::default);
593 let underline = style.underline.get_or_insert_with(Default::default);
594 underline.thickness = px(8.);
595 self
596 }
597
598 fn font(mut self, family_name: impl Into<SharedString>) -> Self
599 where
600 Self: Sized,
601 {
602 self.text_style()
603 .get_or_insert_with(Default::default)
604 .font_family = Some(family_name.into());
605 self
606 }
607
608 fn line_height(mut self, line_height: impl Into<DefiniteLength>) -> Self
609 where
610 Self: Sized,
611 {
612 self.text_style()
613 .get_or_insert_with(Default::default)
614 .line_height = Some(line_height.into());
615 self
616 }
617}