1use crate::{
2 self as gpui, AbsoluteLength, AlignContent, AlignItems, BlendMode, BorderStyle, CursorStyle,
3 DefiniteLength, Display, Fill, FlexDirection, FlexWrap, Font, FontStyle, FontWeight,
4 GridPlacement, Hsla, JustifyContent, Length, Pixels, SharedString, StrikethroughStyle,
5 StyleRefinement, TextAlign, TextOverflow, TextShadow, TextStyleRefinement, UnderlineStyle,
6 WhiteSpace, point, px, relative, rems,
7};
8pub use gpui_macros::{
9 border_style_methods, box_shadow_style_methods, cursor_style_methods, margin_style_methods,
10 overflow_style_methods, padding_style_methods, position_style_methods,
11 visibility_style_methods,
12};
13
14const ELLIPSIS: SharedString = SharedString::new_static("…");
15
16#[cfg_attr(
19 any(feature = "inspector", debug_assertions),
20 gpui_macros::derive_inspector_reflection
21)]
22pub trait Styled: Sized {
23 fn style(&mut self) -> &mut StyleRefinement;
25
26 gpui_macros::style_helpers!();
27 gpui_macros::visibility_style_methods!();
28 gpui_macros::margin_style_methods!();
29 gpui_macros::padding_style_methods!();
30 gpui_macros::position_style_methods!();
31 gpui_macros::overflow_style_methods!();
32 gpui_macros::cursor_style_methods!();
33 gpui_macros::border_style_methods!();
34 gpui_macros::box_shadow_style_methods!();
35
36 fn block(mut self) -> Self {
39 self.style().display = Some(Display::Block);
40 self
41 }
42
43 fn flex(mut self) -> Self {
46 self.style().display = Some(Display::Flex);
47 self
48 }
49
50 fn grid(mut self) -> Self {
53 self.style().display = Some(Display::Grid);
54 self
55 }
56
57 fn whitespace_normal(mut self) -> Self {
60 self.text_style()
61 .get_or_insert_with(Default::default)
62 .white_space = Some(WhiteSpace::Normal);
63 self
64 }
65
66 fn whitespace_nowrap(mut self) -> Self {
69 self.text_style()
70 .get_or_insert_with(Default::default)
71 .white_space = Some(WhiteSpace::Nowrap);
72 self
73 }
74
75 fn text_ellipsis(mut self) -> Self {
78 self.text_style()
79 .get_or_insert_with(Default::default)
80 .text_overflow = Some(TextOverflow::Truncate(ELLIPSIS));
81 self
82 }
83
84 fn text_overflow(mut self, overflow: TextOverflow) -> Self {
86 self.text_style()
87 .get_or_insert_with(Default::default)
88 .text_overflow = Some(overflow);
89 self
90 }
91
92 fn text_align(mut self, align: TextAlign) -> Self {
94 self.text_style()
95 .get_or_insert_with(Default::default)
96 .text_align = Some(align);
97 self
98 }
99
100 fn text_left(mut self) -> Self {
102 self.text_align(TextAlign::Left)
103 }
104
105 fn text_center(mut self) -> Self {
107 self.text_align(TextAlign::Center)
108 }
109
110 fn text_right(mut self) -> Self {
112 self.text_align(TextAlign::Right)
113 }
114
115 fn truncate(mut self) -> Self {
118 self.overflow_hidden().whitespace_nowrap().text_ellipsis()
119 }
120
121 fn line_clamp(mut self, lines: usize) -> Self {
124 let mut text_style = self.text_style().get_or_insert_with(Default::default);
125 text_style.line_clamp = Some(lines);
126 self.overflow_hidden()
127 }
128
129 fn letter_spacing(mut self, spacing: impl Into<Pixels>) -> Self {
132 self.text_style()
133 .get_or_insert_with(Default::default)
134 .letter_spacing = Some(spacing.into());
135 self
136 }
137
138 fn tracking_tighter(self) -> Self {
140 self.letter_spacing(px(-0.5))
141 }
142
143 fn tracking_tight(self) -> Self {
145 self.letter_spacing(px(-0.25))
146 }
147
148 fn tracking_normal(self) -> Self {
150 self.letter_spacing(px(0.0))
151 }
152
153 fn tracking_wide(self) -> Self {
155 self.letter_spacing(px(0.5))
156 }
157
158 fn tracking_wider(self) -> Self {
160 self.letter_spacing(px(1.0))
161 }
162
163 fn tracking_widest(self) -> Self {
165 self.letter_spacing(px(2.0))
166 }
167
168 fn continuous_corners(mut self) -> Self {
171 self.style().continuous_corners = Some(true);
172 self
173 }
174
175 fn blend_mode(mut self, mode: BlendMode) -> Self {
177 self.style().blend_mode = Some(mode);
178 self
179 }
180
181 fn text_shadow(mut self, shadow: TextShadow) -> Self {
183 self.text_style()
184 .get_or_insert_with(Default::default)
185 .text_shadow = Some(shadow);
186 self
187 }
188
189 fn text_shadow_sm(mut self) -> Self {
191 self.text_style()
192 .get_or_insert_with(Default::default)
193 .text_shadow = Some(TextShadow {
194 color: Hsla {
195 h: 0.0,
196 s: 0.0,
197 l: 0.0,
198 a: 0.2,
199 },
200 offset: point(px(0.0), px(1.0)),
201 blur_radius: px(2.0),
202 });
203 self
204 }
205
206 fn text_shadow_md(mut self) -> Self {
208 self.text_style()
209 .get_or_insert_with(Default::default)
210 .text_shadow = Some(TextShadow {
211 color: Hsla {
212 h: 0.0,
213 s: 0.0,
214 l: 0.0,
215 a: 0.25,
216 },
217 offset: point(px(0.0), px(2.0)),
218 blur_radius: px(4.0),
219 });
220 self
221 }
222
223 fn text_shadow_lg(mut self) -> Self {
225 self.text_style()
226 .get_or_insert_with(Default::default)
227 .text_shadow = Some(TextShadow {
228 color: Hsla {
229 h: 0.0,
230 s: 0.0,
231 l: 0.0,
232 a: 0.3,
233 },
234 offset: point(px(0.0), px(3.0)),
235 blur_radius: px(6.0),
236 });
237 self
238 }
239
240 fn flex_col(mut self) -> Self {
243 self.style().flex_direction = Some(FlexDirection::Column);
244 self
245 }
246
247 fn flex_col_reverse(mut self) -> Self {
250 self.style().flex_direction = Some(FlexDirection::ColumnReverse);
251 self
252 }
253
254 fn flex_row(mut self) -> Self {
257 self.style().flex_direction = Some(FlexDirection::Row);
258 self
259 }
260
261 fn flex_row_reverse(mut self) -> Self {
264 self.style().flex_direction = Some(FlexDirection::RowReverse);
265 self
266 }
267
268 fn flex_1(mut self) -> Self {
271 self.style().flex_grow = Some(1.);
272 self.style().flex_shrink = Some(1.);
273 self.style().flex_basis = Some(relative(0.).into());
274 self
275 }
276
277 fn flex_auto(mut self) -> Self {
280 self.style().flex_grow = Some(1.);
281 self.style().flex_shrink = Some(1.);
282 self.style().flex_basis = Some(Length::Auto);
283 self
284 }
285
286 fn flex_initial(mut self) -> Self {
289 self.style().flex_grow = Some(0.);
290 self.style().flex_shrink = Some(1.);
291 self.style().flex_basis = Some(Length::Auto);
292 self
293 }
294
295 fn flex_none(mut self) -> Self {
298 self.style().flex_grow = Some(0.);
299 self.style().flex_shrink = Some(0.);
300 self
301 }
302
303 fn flex_basis(mut self, basis: impl Into<Length>) -> Self {
306 self.style().flex_basis = Some(basis.into());
307 self
308 }
309
310 fn flex_grow(mut self) -> Self {
313 self.style().flex_grow = Some(1.);
314 self
315 }
316
317 fn flex_shrink(mut self) -> Self {
320 self.style().flex_shrink = Some(1.);
321 self
322 }
323
324 fn flex_shrink_0(mut self) -> Self {
327 self.style().flex_shrink = Some(0.);
328 self
329 }
330
331 fn flex_wrap(mut self) -> Self {
334 self.style().flex_wrap = Some(FlexWrap::Wrap);
335 self
336 }
337
338 fn flex_wrap_reverse(mut self) -> Self {
341 self.style().flex_wrap = Some(FlexWrap::WrapReverse);
342 self
343 }
344
345 fn flex_nowrap(mut self) -> Self {
348 self.style().flex_wrap = Some(FlexWrap::NoWrap);
349 self
350 }
351
352 fn items_start(mut self) -> Self {
355 self.style().align_items = Some(AlignItems::FlexStart);
356 self
357 }
358
359 fn items_end(mut self) -> Self {
362 self.style().align_items = Some(AlignItems::FlexEnd);
363 self
364 }
365
366 fn items_center(mut self) -> Self {
369 self.style().align_items = Some(AlignItems::Center);
370 self
371 }
372
373 fn items_baseline(mut self) -> Self {
376 self.style().align_items = Some(AlignItems::Baseline);
377 self
378 }
379
380 fn justify_start(mut self) -> Self {
383 self.style().justify_content = Some(JustifyContent::Start);
384 self
385 }
386
387 fn justify_end(mut self) -> Self {
390 self.style().justify_content = Some(JustifyContent::End);
391 self
392 }
393
394 fn justify_center(mut self) -> Self {
397 self.style().justify_content = Some(JustifyContent::Center);
398 self
399 }
400
401 fn justify_between(mut self) -> Self {
405 self.style().justify_content = Some(JustifyContent::SpaceBetween);
406 self
407 }
408
409 fn justify_around(mut self) -> Self {
413 self.style().justify_content = Some(JustifyContent::SpaceAround);
414 self
415 }
416
417 fn content_normal(mut self) -> Self {
420 self.style().align_content = None;
421 self
422 }
423
424 fn content_center(mut self) -> Self {
427 self.style().align_content = Some(AlignContent::Center);
428 self
429 }
430
431 fn content_start(mut self) -> Self {
434 self.style().align_content = Some(AlignContent::FlexStart);
435 self
436 }
437
438 fn content_end(mut self) -> Self {
441 self.style().align_content = Some(AlignContent::FlexEnd);
442 self
443 }
444
445 fn content_between(mut self) -> Self {
449 self.style().align_content = Some(AlignContent::SpaceBetween);
450 self
451 }
452
453 fn content_around(mut self) -> Self {
457 self.style().align_content = Some(AlignContent::SpaceAround);
458 self
459 }
460
461 fn content_evenly(mut self) -> Self {
465 self.style().align_content = Some(AlignContent::SpaceEvenly);
466 self
467 }
468
469 fn content_stretch(mut self) -> Self {
472 self.style().align_content = Some(AlignContent::Stretch);
473 self
474 }
475
476 fn bg<F>(mut self, fill: F) -> Self
478 where
479 F: Into<Fill>,
480 Self: Sized,
481 {
482 self.style().background = Some(fill.into());
483 self
484 }
485
486 fn border_dashed(mut self) -> Self {
488 self.style().border_style = Some(BorderStyle::Dashed);
489 self
490 }
491
492 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 {
502 self.text_style().get_or_insert_with(Default::default).color = Some(color.into());
503 self
504 }
505
506 fn font_weight(mut self, weight: FontWeight) -> Self {
510 self.text_style()
511 .get_or_insert_with(Default::default)
512 .font_weight = Some(weight);
513 self
514 }
515
516 fn text_bg(mut self, bg: impl Into<Hsla>) -> Self {
520 self.text_style()
521 .get_or_insert_with(Default::default)
522 .background_color = Some(bg.into());
523 self
524 }
525
526 fn text_size(mut self, size: impl Into<AbsoluteLength>) -> Self {
530 self.text_style()
531 .get_or_insert_with(Default::default)
532 .font_size = Some(size.into());
533 self
534 }
535
536 fn text_xs(mut self) -> Self {
539 self.text_style()
540 .get_or_insert_with(Default::default)
541 .font_size = Some(rems(0.75).into());
542 self
543 }
544
545 fn text_sm(mut self) -> Self {
548 self.text_style()
549 .get_or_insert_with(Default::default)
550 .font_size = Some(rems(0.875).into());
551 self
552 }
553
554 fn text_base(mut self) -> Self {
557 self.text_style()
558 .get_or_insert_with(Default::default)
559 .font_size = Some(rems(1.0).into());
560 self
561 }
562
563 fn text_lg(mut self) -> Self {
566 self.text_style()
567 .get_or_insert_with(Default::default)
568 .font_size = Some(rems(1.125).into());
569 self
570 }
571
572 fn text_xl(mut self) -> Self {
575 self.text_style()
576 .get_or_insert_with(Default::default)
577 .font_size = Some(rems(1.25).into());
578 self
579 }
580
581 fn text_2xl(mut self) -> Self {
584 self.text_style()
585 .get_or_insert_with(Default::default)
586 .font_size = Some(rems(1.5).into());
587 self
588 }
589
590 fn text_3xl(mut self) -> Self {
593 self.text_style()
594 .get_or_insert_with(Default::default)
595 .font_size = Some(rems(1.875).into());
596 self
597 }
598
599 fn italic(mut self) -> Self {
602 self.text_style()
603 .get_or_insert_with(Default::default)
604 .font_style = Some(FontStyle::Italic);
605 self
606 }
607
608 fn not_italic(mut self) -> Self {
611 self.text_style()
612 .get_or_insert_with(Default::default)
613 .font_style = Some(FontStyle::Normal);
614 self
615 }
616
617 fn underline(mut self) -> Self {
620 let style = self.text_style().get_or_insert_with(Default::default);
621 style.underline = Some(UnderlineStyle {
622 thickness: px(1.),
623 ..Default::default()
624 });
625 self
626 }
627
628 fn line_through(mut self) -> Self {
631 let style = self.text_style().get_or_insert_with(Default::default);
632 style.strikethrough = Some(StrikethroughStyle {
633 thickness: px(1.),
634 ..Default::default()
635 });
636 self
637 }
638
639 fn text_decoration_none(mut self) -> Self {
643 self.text_style()
644 .get_or_insert_with(Default::default)
645 .underline = None;
646 self
647 }
648
649 fn text_decoration_color(mut self, color: impl Into<Hsla>) -> 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.color = Some(color.into());
654 self
655 }
656
657 fn text_decoration_solid(mut self) -> Self {
660 let style = self.text_style().get_or_insert_with(Default::default);
661 let underline = style.underline.get_or_insert_with(Default::default);
662 underline.wavy = false;
663 self
664 }
665
666 fn text_decoration_wavy(mut self) -> Self {
669 let style = self.text_style().get_or_insert_with(Default::default);
670 let underline = style.underline.get_or_insert_with(Default::default);
671 underline.wavy = true;
672 self
673 }
674
675 fn text_decoration_0(mut self) -> Self {
678 let style = self.text_style().get_or_insert_with(Default::default);
679 let underline = style.underline.get_or_insert_with(Default::default);
680 underline.thickness = px(0.);
681 self
682 }
683
684 fn text_decoration_1(mut self) -> Self {
687 let style = self.text_style().get_or_insert_with(Default::default);
688 let underline = style.underline.get_or_insert_with(Default::default);
689 underline.thickness = px(1.);
690 self
691 }
692
693 fn text_decoration_2(mut self) -> Self {
696 let style = self.text_style().get_or_insert_with(Default::default);
697 let underline = style.underline.get_or_insert_with(Default::default);
698 underline.thickness = px(2.);
699 self
700 }
701
702 fn text_decoration_4(mut self) -> Self {
705 let style = self.text_style().get_or_insert_with(Default::default);
706 let underline = style.underline.get_or_insert_with(Default::default);
707 underline.thickness = px(4.);
708 self
709 }
710
711 fn text_decoration_8(mut self) -> Self {
714 let style = self.text_style().get_or_insert_with(Default::default);
715 let underline = style.underline.get_or_insert_with(Default::default);
716 underline.thickness = px(8.);
717 self
718 }
719
720 fn font_family(mut self, family_name: impl Into<SharedString>) -> Self {
722 self.text_style()
723 .get_or_insert_with(Default::default)
724 .font_family = Some(family_name.into());
725 self
726 }
727
728 fn font(mut self, font: Font) -> Self {
730 let Font {
731 family,
732 features,
733 fallbacks,
734 weight,
735 style,
736 } = font;
737
738 let text_style = self.text_style().get_or_insert_with(Default::default);
739 text_style.font_family = Some(family);
740 text_style.font_features = Some(features);
741 text_style.font_weight = Some(weight);
742 text_style.font_style = Some(style);
743 text_style.font_fallbacks = fallbacks;
744
745 self
746 }
747
748 fn line_height(mut self, line_height: impl Into<DefiniteLength>) -> Self {
750 self.text_style()
751 .get_or_insert_with(Default::default)
752 .line_height = Some(line_height.into());
753 self
754 }
755
756 fn opacity(mut self, opacity: f32) -> Self {
758 self.style().opacity = Some(opacity);
759 self
760 }
761
762 fn rotate(mut self, angle_degrees: f32) -> Self {
764 self.style().rotate = Some(angle_degrees.to_radians());
765 self
766 }
767
768 fn scale(mut self, factor: f32) -> Self {
770 self.style().scale = Some(point(factor, factor));
771 self
772 }
773
774 fn scale_xy(mut self, x: f32, y: f32) -> Self {
776 self.style().scale = Some(point(x, y));
777 self
778 }
779
780 fn transform_origin(mut self, x: f32, y: f32) -> Self {
783 self.style().transform_origin = Some(point(x, y));
784 self
785 }
786
787 fn grid_cols(mut self, cols: u16) -> Self {
789 self.style().grid_cols = Some(cols);
790 self
791 }
792
793 fn grid_rows(mut self, rows: u16) -> Self {
795 self.style().grid_rows = Some(rows);
796 self
797 }
798
799 fn col_start(mut self, start: i16) -> Self {
801 let grid_location = self.style().grid_location_mut();
802 grid_location.column.start = GridPlacement::Line(start);
803 self
804 }
805
806 fn col_start_auto(mut self) -> Self {
808 let grid_location = self.style().grid_location_mut();
809 grid_location.column.start = GridPlacement::Auto;
810 self
811 }
812
813 fn col_end(mut self, end: i16) -> Self {
815 let grid_location = self.style().grid_location_mut();
816 grid_location.column.end = GridPlacement::Line(end);
817 self
818 }
819
820 fn col_end_auto(mut self) -> Self {
822 let grid_location = self.style().grid_location_mut();
823 grid_location.column.end = GridPlacement::Auto;
824 self
825 }
826
827 fn col_span(mut self, span: u16) -> Self {
829 let grid_location = self.style().grid_location_mut();
830 grid_location.column = GridPlacement::Span(span)..GridPlacement::Span(span);
831 self
832 }
833
834 fn col_span_full(mut self) -> Self {
836 let grid_location = self.style().grid_location_mut();
837 grid_location.column = GridPlacement::Line(1)..GridPlacement::Line(-1);
838 self
839 }
840
841 fn row_start(mut self, start: i16) -> Self {
843 let grid_location = self.style().grid_location_mut();
844 grid_location.row.start = GridPlacement::Line(start);
845 self
846 }
847
848 fn row_start_auto(mut self) -> Self {
850 let grid_location = self.style().grid_location_mut();
851 grid_location.row.start = GridPlacement::Auto;
852 self
853 }
854
855 fn row_end(mut self, end: i16) -> Self {
857 let grid_location = self.style().grid_location_mut();
858 grid_location.row.end = GridPlacement::Line(end);
859 self
860 }
861
862 fn row_end_auto(mut self) -> Self {
864 let grid_location = self.style().grid_location_mut();
865 grid_location.row.end = GridPlacement::Auto;
866 self
867 }
868
869 fn row_span(mut self, span: u16) -> Self {
871 let grid_location = self.style().grid_location_mut();
872 grid_location.row = GridPlacement::Span(span)..GridPlacement::Span(span);
873 self
874 }
875
876 fn row_span_full(mut self) -> Self {
878 let grid_location = self.style().grid_location_mut();
879 grid_location.row = GridPlacement::Line(1)..GridPlacement::Line(-1);
880 self
881 }
882
883 #[cfg(debug_assertions)]
885 fn debug(mut self) -> Self {
886 self.style().debug = Some(true);
887 self
888 }
889
890 #[cfg(debug_assertions)]
892 fn debug_below(mut self) -> Self {
893 self.style().debug_below = Some(true);
894 self
895 }
896}