Skip to content

Commit 6c6fb99

Browse files
authored
Theme elevation + Palette Style (#3305)
[[PR Description]] Release Notes: - N/A
2 parents 1c02690 + 800ad1d commit 6c6fb99

File tree

9 files changed

+150
-48
lines changed

9 files changed

+150
-48
lines changed

crates/command_palette2/src/command_palette.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use gpui::{
88
use picker::{Picker, PickerDelegate};
99
use std::cmp::{self, Reverse};
1010
use theme::ActiveTheme;
11-
use ui::{modal, Label};
11+
use ui::{v_stack, Label, StyledExt};
1212
use util::{
1313
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
1414
ResultExt,
@@ -76,8 +76,8 @@ impl Modal for CommandPalette {
7676
impl Render for CommandPalette {
7777
type Element = Div<Self>;
7878

79-
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
80-
modal(cx).w_96().child(self.picker.clone())
79+
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
80+
v_stack().w_96().child(self.picker.clone())
8181
}
8282
}
8383

@@ -305,15 +305,13 @@ impl PickerDelegate for CommandPaletteDelegate {
305305
};
306306

307307
div()
308+
.px_1()
308309
.text_color(colors.text)
309-
.when(selected, |s| {
310-
s.border_l_10().border_color(colors.terminal_ansi_yellow)
311-
})
312-
.hover(|style| {
313-
style
314-
.bg(colors.element_active)
315-
.text_color(colors.text_accent)
316-
})
310+
.text_ui()
311+
.bg(colors.ghost_element_background)
312+
.rounded_md()
313+
.when(selected, |this| this.bg(colors.ghost_element_selected))
314+
.hover(|this| this.bg(colors.ghost_element_hover))
317315
.child(Label::new(command.name.clone()))
318316
}
319317

crates/editor2/src/editor.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ use text::{OffsetUtf16, Rope};
9797
use theme::{
9898
ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings,
9999
};
100-
use ui::IconButton;
100+
use ui::{IconButton, StyledExt};
101101
use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
102102
use workspace::{
103103
item::ItemEvent, searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace,
@@ -1555,6 +1555,7 @@ impl CodeActionsMenu {
15551555
let colors = cx.theme().colors();
15561556
div()
15571557
.px_2()
1558+
.text_ui()
15581559
.text_color(colors.text)
15591560
.when(selected, |style| {
15601561
style
@@ -1582,7 +1583,7 @@ impl CodeActionsMenu {
15821583
.collect()
15831584
},
15841585
)
1585-
.bg(cx.theme().colors().element_background)
1586+
.elevation_1(cx)
15861587
.px_2()
15871588
.py_1()
15881589
.with_width_from_item(

crates/picker2/src/picker2.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use gpui::{
55
WindowContext,
66
};
77
use std::cmp;
8-
use theme::ActiveTheme;
9-
use ui::v_stack;
8+
use ui::{prelude::*, v_stack, Divider};
109

1110
pub struct Picker<D: PickerDelegate> {
1211
pub delegate: D,
@@ -145,31 +144,24 @@ impl<D: PickerDelegate> Render for Picker<D> {
145144
.id("picker-container")
146145
.focusable()
147146
.size_full()
147+
.elevation_2(cx)
148148
.on_action(Self::select_next)
149149
.on_action(Self::select_prev)
150150
.on_action(Self::select_first)
151151
.on_action(Self::select_last)
152152
.on_action(Self::cancel)
153153
.on_action(Self::confirm)
154154
.on_action(Self::secondary_confirm)
155-
.child(
156-
v_stack().gap_px().child(
157-
v_stack()
158-
.py_0p5()
159-
.px_1()
160-
.child(div().px_2().py_0p5().child(self.editor.clone())),
161-
),
162-
)
163-
.child(
164-
div()
165-
.h_px()
166-
.w_full()
167-
.bg(cx.theme().colors().element_background),
168-
)
169155
.child(
170156
v_stack()
171157
.py_0p5()
172158
.px_1()
159+
.child(div().px_1().py_0p5().child(self.editor.clone())),
160+
)
161+
.child(Divider::horizontal())
162+
.child(
163+
v_stack()
164+
.p_1()
173165
.grow()
174166
.child(
175167
uniform_list("candidates", self.delegate.match_count(), {

crates/ui2/src/components.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod button;
33
mod checkbox;
44
mod context_menu;
55
mod details;
6+
mod divider;
67
mod elevated_surface;
78
mod facepile;
89
mod icon;
@@ -31,6 +32,7 @@ pub use button::*;
3132
pub use checkbox::*;
3233
pub use context_menu::*;
3334
pub use details::*;
35+
pub use divider::*;
3436
pub use elevated_surface::*;
3537
pub use facepile::*;
3638
pub use icon::*;

crates/ui2/src/components/divider.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use crate::prelude::*;
2+
3+
enum DividerDirection {
4+
Horizontal,
5+
Vertical,
6+
}
7+
8+
#[derive(Component)]
9+
pub struct Divider {
10+
direction: DividerDirection,
11+
inset: bool,
12+
}
13+
14+
impl Divider {
15+
pub fn horizontal() -> Self {
16+
Self {
17+
direction: DividerDirection::Horizontal,
18+
inset: false,
19+
}
20+
}
21+
22+
pub fn vertical() -> Self {
23+
Self {
24+
direction: DividerDirection::Vertical,
25+
inset: false,
26+
}
27+
}
28+
29+
pub fn inset(mut self) -> Self {
30+
self.inset = true;
31+
self
32+
}
33+
34+
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
35+
div()
36+
.map(|this| match self.direction {
37+
DividerDirection::Horizontal => {
38+
this.h_px().w_full().when(self.inset, |this| this.mx_1p5())
39+
}
40+
DividerDirection::Vertical => {
41+
this.w_px().h_full().when(self.inset, |this| this.my_1p5())
42+
}
43+
})
44+
.bg(cx.theme().colors().border_variant)
45+
}
46+
}

crates/ui2/src/components/elevated_surface.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ pub fn elevated_surface<V: 'static>(level: ElevationIndex, cx: &mut ViewContext<
2424
}
2525

2626
pub fn modal<V>(cx: &mut ViewContext<V>) -> Div<V> {
27-
elevated_surface(ElevationIndex::ModalSurfaces, cx)
27+
elevated_surface(ElevationIndex::ModalSurface, cx)
2828
}

crates/ui2/src/elevation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ Material Design 3 has a some great visualizations of elevation that may be helpf
3434

3535
The app background constitutes the lowest elevation layer, appearing behind all other surfaces and components. It is predominantly used for the background color of the app.
3636

37-
### UI Surface
37+
### Surface
3838

39-
The UI Surface, located above the app background, is the standard level for all elements
39+
The Surface elevation level, located above the app background, is the standard level for all elements
4040

4141
Example Elements: Title Bar, Panel, Tab Bar, Editor
4242

crates/ui2/src/elevation.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,43 +11,53 @@ pub enum Elevation {
1111

1212
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1313
pub enum ElevationIndex {
14-
AppBackground,
15-
UISurface,
14+
Background,
15+
Surface,
1616
ElevatedSurface,
1717
Wash,
18-
ModalSurfaces,
18+
ModalSurface,
1919
DraggedElement,
2020
}
2121

2222
impl ElevationIndex {
2323
pub fn z_index(self) -> u32 {
2424
match self {
25-
ElevationIndex::AppBackground => 0,
26-
ElevationIndex::UISurface => 100,
25+
ElevationIndex::Background => 0,
26+
ElevationIndex::Surface => 100,
2727
ElevationIndex::ElevatedSurface => 200,
2828
ElevationIndex::Wash => 300,
29-
ElevationIndex::ModalSurfaces => 400,
29+
ElevationIndex::ModalSurface => 400,
3030
ElevationIndex::DraggedElement => 900,
3131
}
3232
}
3333

3434
pub fn shadow(self) -> SmallVec<[BoxShadow; 2]> {
3535
match self {
36-
ElevationIndex::AppBackground => smallvec![],
36+
ElevationIndex::Surface => smallvec![],
3737

38-
ElevationIndex::UISurface => smallvec![BoxShadow {
38+
ElevationIndex::ElevatedSurface => smallvec![BoxShadow {
3939
color: hsla(0., 0., 0., 0.12),
4040
offset: point(px(0.), px(1.)),
4141
blur_radius: px(3.),
4242
spread_radius: px(0.),
4343
}],
4444

45-
_ => smallvec![BoxShadow {
46-
color: hsla(0., 0., 0., 0.32),
47-
offset: point(px(1.), px(3.)),
48-
blur_radius: px(12.),
49-
spread_radius: px(0.),
50-
}],
45+
ElevationIndex::ModalSurface => smallvec![
46+
BoxShadow {
47+
color: hsla(0., 0., 0., 0.12),
48+
offset: point(px(0.), px(1.)),
49+
blur_radius: px(3.),
50+
spread_radius: px(0.),
51+
},
52+
BoxShadow {
53+
color: hsla(0., 0., 0., 0.16),
54+
offset: point(px(3.), px(1.)),
55+
blur_radius: px(12.),
56+
spread_radius: px(0.),
57+
},
58+
],
59+
60+
_ => smallvec![],
5161
}
5262
}
5363
}

crates/ui2/src/styled_ext.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
use gpui::{Div, ElementFocus, ElementInteractivity, Styled};
1+
use gpui::{Div, ElementFocus, ElementInteractivity, Styled, UniformList, ViewContext};
2+
use theme2::ActiveTheme;
23

3-
use crate::UITextSize;
4+
use crate::{ElevationIndex, UITextSize};
5+
6+
fn elevated<E: Styled, V: 'static>(this: E, cx: &mut ViewContext<V>, index: ElevationIndex) -> E {
7+
this.bg(cx.theme().colors().elevated_surface_background)
8+
.rounded_lg()
9+
.border()
10+
.border_color(cx.theme().colors().border_variant)
11+
.shadow(index.shadow())
12+
}
413

514
/// Extends [`Styled`](gpui::Styled) with Zed specific styling methods.
615
pub trait StyledExt: Styled {
@@ -64,6 +73,48 @@ pub trait StyledExt: Styled {
6473

6574
self.text_size(size)
6675
}
76+
77+
/// The [`Surface`](ui2::ElevationIndex::Surface) elevation level, located above the app background, is the standard level for all elements
78+
///
79+
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
80+
///
81+
/// Example Elements: Title Bar, Panel, Tab Bar, Editor
82+
fn elevation_1<V: 'static>(self, cx: &mut ViewContext<V>) -> Self
83+
where
84+
Self: Styled + Sized,
85+
{
86+
elevated(self, cx, ElevationIndex::Surface)
87+
}
88+
89+
/// Non-Modal Elevated Surfaces appear above the [`Surface`](ui2::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.
90+
///
91+
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
92+
///
93+
/// Examples: Notifications, Palettes, Detached/Floating Windows, Detached/Floating Panels
94+
fn elevation_2<V: 'static>(self, cx: &mut ViewContext<V>) -> Self
95+
where
96+
Self: Styled + Sized,
97+
{
98+
elevated(self, cx, ElevationIndex::ElevatedSurface)
99+
}
100+
101+
// There is no elevation 3, as the third elevation level is reserved for wash layers. See [`Elevation`](ui2::Elevation).
102+
103+
/// 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.
104+
///
105+
/// 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.
106+
///
107+
/// If the element does not have this behavior, it should be rendered at the [`Elevated Surface`](ui2::ElevationIndex::ElevatedSurface) layer.
108+
///
109+
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
110+
///
111+
/// Examples: Settings Modal, Channel Management, Wizards/Setup UI, Dialogs
112+
fn elevation_4<V: 'static>(self, cx: &mut ViewContext<V>) -> Self
113+
where
114+
Self: Styled + Sized,
115+
{
116+
elevated(self, cx, ElevationIndex::ModalSurface)
117+
}
67118
}
68119

69120
impl<V, I, F> StyledExt for Div<V, I, F>
@@ -72,3 +123,5 @@ where
72123
F: ElementFocus<V>,
73124
{
74125
}
126+
127+
impl<V> StyledExt for UniformList<V> {}

0 commit comments

Comments
 (0)