1use gpui::{hsla, px, Styled, WindowContext};
2use settings::Settings;
3use theme::ThemeSettings;
4
5use crate::prelude::*;
6use crate::{ElevationIndex, UiTextSize};
7
8fn elevated<E: Styled>(this: E, cx: &mut WindowContext, index: ElevationIndex) -> E {
9 this.bg(cx.theme().colors().elevated_surface_background)
10 .rounded(px(8.))
11 .border()
12 .border_color(cx.theme().colors().border_variant)
13 .shadow(index.shadow())
14}
15
16/// Extends [`gpui::Styled`] with Zed-specific styling methods.
17pub trait StyledExt: Styled + Sized {
18 /// Horizontally stacks elements.
19 ///
20 /// Sets `flex()`, `flex_row()`, `items_center()`
21 fn h_flex(self) -> Self {
22 self.flex().flex_row().items_center()
23 }
24
25 /// Vertically stacks elements.
26 ///
27 /// Sets `flex()`, `flex_col()`
28 fn v_flex(self) -> Self {
29 self.flex().flex_col()
30 }
31
32 /// Sets the text size using a [`UiTextSize`].
33 fn text_ui_size(self, size: UiTextSize) -> Self {
34 self.text_size(size.rems())
35 }
36
37 /// The large size for UI text.
38 ///
39 /// `1rem` or `16px` at the default scale of `1rem` = `16px`.
40 ///
41 /// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
42 ///
43 /// Use `text_ui` for regular-sized text.
44 fn text_ui_lg(self) -> Self {
45 self.text_size(UiTextSize::Large.rems())
46 }
47
48 /// The default size for UI text.
49 ///
50 /// `0.825rem` or `14px` at the default scale of `1rem` = `16px`.
51 ///
52 /// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
53 ///
54 /// Use `text_ui_sm` for smaller text.
55 fn text_ui(self) -> Self {
56 self.text_size(UiTextSize::default().rems())
57 }
58
59 /// The small size for UI text.
60 ///
61 /// `0.75rem` or `12px` at the default scale of `1rem` = `16px`.
62 ///
63 /// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
64 ///
65 /// Use `text_ui` for regular-sized text.
66 fn text_ui_sm(self) -> Self {
67 self.text_size(UiTextSize::Small.rems())
68 }
69
70 /// The extra small size for UI text.
71 ///
72 /// `0.625rem` or `10px` at the default scale of `1rem` = `16px`.
73 ///
74 /// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
75 ///
76 /// Use `text_ui` for regular-sized text.
77 fn text_ui_xs(self) -> Self {
78 self.text_size(UiTextSize::XSmall.rems())
79 }
80
81 /// The font size for buffer text.
82 ///
83 /// Retrieves the default font size, or the user's custom font size if set.
84 ///
85 /// This should only be used for text that is displayed in a buffer,
86 /// or other places that text needs to match the user's buffer font size.
87 fn text_buffer(self, cx: &mut WindowContext) -> Self {
88 let settings = ThemeSettings::get_global(cx);
89 self.text_size(settings.buffer_font_size(cx))
90 }
91
92 /// The [`Surface`](ElevationIndex::Surface) elevation level, located above the app background, is the standard level for all elements
93 ///
94 /// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
95 ///
96 /// Example Elements: Title Bar, Panel, Tab Bar, Editor
97 fn elevation_1(self, cx: &mut WindowContext) -> Self {
98 elevated(self, cx, ElevationIndex::Surface)
99 }
100
101 /// Non-Modal Elevated Surfaces appear above the [`Surface`](ElevationIndex::Surface) layer and is used for things that should appear above most UI elements like an editor or panel, but not elements like popovers, context menus, modals, etc.
102 ///
103 /// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
104 ///
105 /// Examples: Notifications, Palettes, Detached/Floating Windows, Detached/Floating Panels
106 fn elevation_2(self, cx: &mut WindowContext) -> Self {
107 elevated(self, cx, ElevationIndex::ElevatedSurface)
108 }
109
110 /// Modal Surfaces are used for elements that should appear above all other UI elements and are located above the wash layer. This is the maximum elevation at which UI elements can be rendered in their default state.
111 ///
112 /// Elements rendered at this layer should have an enforced behavior: Any interaction outside of the modal will either dismiss the modal or prompt an action (Save your progress, etc) then dismiss the modal.
113 ///
114 /// If the element does not have this behavior, it should be rendered at the [`Elevated Surface`](ElevationIndex::ElevatedSurface) layer.
115 ///
116 /// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
117 ///
118 /// Examples: Settings Modal, Channel Management, Wizards/Setup UI, Dialogs
119 fn elevation_3(self, cx: &mut WindowContext) -> Self {
120 elevated(self, cx, ElevationIndex::ModalSurface)
121 }
122
123 /// The theme's primary border color.
124 fn border_primary(self, cx: &mut WindowContext) -> Self {
125 self.border_color(cx.theme().colors().border)
126 }
127
128 /// The theme's secondary or muted border color.
129 fn border_muted(self, cx: &mut WindowContext) -> Self {
130 self.border_color(cx.theme().colors().border_variant)
131 }
132
133 /// Sets the background color to red for debugging when building UI.
134 fn debug_bg_red(self) -> Self {
135 self.bg(hsla(0. / 360., 1., 0.5, 1.))
136 }
137
138 /// Sets the background color to green for debugging when building UI.
139 fn debug_bg_green(self) -> Self {
140 self.bg(hsla(120. / 360., 1., 0.5, 1.))
141 }
142
143 /// Sets the background color to blue for debugging when building UI.
144 fn debug_bg_blue(self) -> Self {
145 self.bg(hsla(240. / 360., 1., 0.5, 1.))
146 }
147
148 /// Sets the background color to yellow for debugging when building UI.
149 fn debug_bg_yellow(self) -> Self {
150 self.bg(hsla(60. / 360., 1., 0.5, 1.))
151 }
152
153 /// Sets the background color to cyan for debugging when building UI.
154 fn debug_bg_cyan(self) -> Self {
155 self.bg(hsla(160. / 360., 1., 0.5, 1.))
156 }
157
158 /// Sets the background color to magenta for debugging when building UI.
159 fn debug_bg_magenta(self) -> Self {
160 self.bg(hsla(300. / 360., 1., 0.5, 1.))
161 }
162}
163
164impl<E: Styled> StyledExt for E {}