Theme elevation + Palette Style (#3305)

[[PR Description]]

Release Notes:

- N/A
This commit is contained in:
Nate Butler
2023-11-12 22:29:25 -05:00
committed by GitHub
9 changed files with 150 additions and 48 deletions
+9 -11
View File
@@ -8,7 +8,7 @@ use gpui::{
use picker::{Picker, PickerDelegate};
use std::cmp::{self, Reverse};
use theme::ActiveTheme;
use ui::{modal, Label};
use ui::{v_stack, Label, StyledExt};
use util::{
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
ResultExt,
@@ -76,8 +76,8 @@ impl Modal for CommandPalette {
impl Render for CommandPalette {
type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
modal(cx).w_96().child(self.picker.clone())
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
v_stack().w_96().child(self.picker.clone())
}
}
@@ -305,15 +305,13 @@ impl PickerDelegate for CommandPaletteDelegate {
};
div()
.px_1()
.text_color(colors.text)
.when(selected, |s| {
s.border_l_10().border_color(colors.terminal_ansi_yellow)
})
.hover(|style| {
style
.bg(colors.element_active)
.text_color(colors.text_accent)
})
.text_ui()
.bg(colors.ghost_element_background)
.rounded_md()
.when(selected, |this| this.bg(colors.ghost_element_selected))
.hover(|this| this.bg(colors.ghost_element_hover))
.child(Label::new(command.name.clone()))
}
+3 -2
View File
@@ -97,7 +97,7 @@ use text::{OffsetUtf16, Rope};
use theme::{
ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings,
};
use ui::IconButton;
use ui::{IconButton, StyledExt};
use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
use workspace::{
item::ItemEvent, searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace,
@@ -1555,6 +1555,7 @@ impl CodeActionsMenu {
let colors = cx.theme().colors();
div()
.px_2()
.text_ui()
.text_color(colors.text)
.when(selected, |style| {
style
@@ -1582,7 +1583,7 @@ impl CodeActionsMenu {
.collect()
},
)
.bg(cx.theme().colors().element_background)
.elevation_1(cx)
.px_2()
.py_1()
.with_width_from_item(
+8 -16
View File
@@ -5,8 +5,7 @@ use gpui::{
WindowContext,
};
use std::cmp;
use theme::ActiveTheme;
use ui::v_stack;
use ui::{prelude::*, v_stack, Divider};
pub struct Picker<D: PickerDelegate> {
pub delegate: D,
@@ -145,6 +144,7 @@ impl<D: PickerDelegate> Render for Picker<D> {
.id("picker-container")
.focusable()
.size_full()
.elevation_2(cx)
.on_action(Self::select_next)
.on_action(Self::select_prev)
.on_action(Self::select_first)
@@ -152,24 +152,16 @@ impl<D: PickerDelegate> Render for Picker<D> {
.on_action(Self::cancel)
.on_action(Self::confirm)
.on_action(Self::secondary_confirm)
.child(
v_stack().gap_px().child(
v_stack()
.py_0p5()
.px_1()
.child(div().px_2().py_0p5().child(self.editor.clone())),
),
)
.child(
div()
.h_px()
.w_full()
.bg(cx.theme().colors().element_background),
)
.child(
v_stack()
.py_0p5()
.px_1()
.child(div().px_1().py_0p5().child(self.editor.clone())),
)
.child(Divider::horizontal())
.child(
v_stack()
.p_1()
.grow()
.child(
uniform_list("candidates", self.delegate.match_count(), {
+2
View File
@@ -3,6 +3,7 @@ mod button;
mod checkbox;
mod context_menu;
mod details;
mod divider;
mod elevated_surface;
mod facepile;
mod icon;
@@ -31,6 +32,7 @@ pub use button::*;
pub use checkbox::*;
pub use context_menu::*;
pub use details::*;
pub use divider::*;
pub use elevated_surface::*;
pub use facepile::*;
pub use icon::*;
+46
View File
@@ -0,0 +1,46 @@
use crate::prelude::*;
enum DividerDirection {
Horizontal,
Vertical,
}
#[derive(Component)]
pub struct Divider {
direction: DividerDirection,
inset: bool,
}
impl Divider {
pub fn horizontal() -> Self {
Self {
direction: DividerDirection::Horizontal,
inset: false,
}
}
pub fn vertical() -> Self {
Self {
direction: DividerDirection::Vertical,
inset: false,
}
}
pub fn inset(mut self) -> Self {
self.inset = true;
self
}
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
div()
.map(|this| match self.direction {
DividerDirection::Horizontal => {
this.h_px().w_full().when(self.inset, |this| this.mx_1p5())
}
DividerDirection::Vertical => {
this.w_px().h_full().when(self.inset, |this| this.my_1p5())
}
})
.bg(cx.theme().colors().border_variant)
}
}
@@ -24,5 +24,5 @@ pub fn elevated_surface<V: 'static>(level: ElevationIndex, cx: &mut ViewContext<
}
pub fn modal<V>(cx: &mut ViewContext<V>) -> Div<V> {
elevated_surface(ElevationIndex::ModalSurfaces, cx)
elevated_surface(ElevationIndex::ModalSurface, cx)
}
+2 -2
View File
@@ -34,9 +34,9 @@ Material Design 3 has a some great visualizations of elevation that may be helpf
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.
### UI Surface
### Surface
The UI Surface, located above the app background, is the standard level for all elements
The Surface elevation level, located above the app background, is the standard level for all elements
Example Elements: Title Bar, Panel, Tab Bar, Editor
+24 -14
View File
@@ -11,43 +11,53 @@ pub enum Elevation {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ElevationIndex {
AppBackground,
UISurface,
Background,
Surface,
ElevatedSurface,
Wash,
ModalSurfaces,
ModalSurface,
DraggedElement,
}
impl ElevationIndex {
pub fn z_index(self) -> u32 {
match self {
ElevationIndex::AppBackground => 0,
ElevationIndex::UISurface => 100,
ElevationIndex::Background => 0,
ElevationIndex::Surface => 100,
ElevationIndex::ElevatedSurface => 200,
ElevationIndex::Wash => 300,
ElevationIndex::ModalSurfaces => 400,
ElevationIndex::ModalSurface => 400,
ElevationIndex::DraggedElement => 900,
}
}
pub fn shadow(self) -> SmallVec<[BoxShadow; 2]> {
match self {
ElevationIndex::AppBackground => smallvec![],
ElevationIndex::Surface => smallvec![],
ElevationIndex::UISurface => smallvec![BoxShadow {
ElevationIndex::ElevatedSurface => smallvec![BoxShadow {
color: hsla(0., 0., 0., 0.12),
offset: point(px(0.), px(1.)),
blur_radius: px(3.),
spread_radius: px(0.),
}],
_ => smallvec![BoxShadow {
color: hsla(0., 0., 0., 0.32),
offset: point(px(1.), px(3.)),
blur_radius: px(12.),
spread_radius: px(0.),
}],
ElevationIndex::ModalSurface => smallvec![
BoxShadow {
color: hsla(0., 0., 0., 0.12),
offset: point(px(0.), px(1.)),
blur_radius: px(3.),
spread_radius: px(0.),
},
BoxShadow {
color: hsla(0., 0., 0., 0.16),
offset: point(px(3.), px(1.)),
blur_radius: px(12.),
spread_radius: px(0.),
},
],
_ => smallvec![],
}
}
}
+55 -2
View File
@@ -1,6 +1,15 @@
use gpui::{Div, ElementFocus, ElementInteractivity, Styled};
use gpui::{Div, ElementFocus, ElementInteractivity, Styled, UniformList, ViewContext};
use theme2::ActiveTheme;
use crate::UITextSize;
use crate::{ElevationIndex, UITextSize};
fn elevated<E: Styled, V: 'static>(this: E, cx: &mut ViewContext<V>, index: ElevationIndex) -> E {
this.bg(cx.theme().colors().elevated_surface_background)
.rounded_lg()
.border()
.border_color(cx.theme().colors().border_variant)
.shadow(index.shadow())
}
/// Extends [`Styled`](gpui::Styled) with Zed specific styling methods.
pub trait StyledExt: Styled {
@@ -64,6 +73,48 @@ pub trait StyledExt: Styled {
self.text_size(size)
}
/// The [`Surface`](ui2::ElevationIndex::Surface) elevation level, located above the app background, is the standard level for all elements
///
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
///
/// Example Elements: Title Bar, Panel, Tab Bar, Editor
fn elevation_1<V: 'static>(self, cx: &mut ViewContext<V>) -> Self
where
Self: Styled + Sized,
{
elevated(self, cx, ElevationIndex::Surface)
}
/// 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.
///
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
///
/// Examples: Notifications, Palettes, Detached/Floating Windows, Detached/Floating Panels
fn elevation_2<V: 'static>(self, cx: &mut ViewContext<V>) -> Self
where
Self: Styled + Sized,
{
elevated(self, cx, ElevationIndex::ElevatedSurface)
}
// There is no elevation 3, as the third elevation level is reserved for wash layers. See [`Elevation`](ui2::Elevation).
/// 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.
///
/// 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.
///
/// If the element does not have this behavior, it should be rendered at the [`Elevated Surface`](ui2::ElevationIndex::ElevatedSurface) layer.
///
/// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()`
///
/// Examples: Settings Modal, Channel Management, Wizards/Setup UI, Dialogs
fn elevation_4<V: 'static>(self, cx: &mut ViewContext<V>) -> Self
where
Self: Styled + Sized,
{
elevated(self, cx, ElevationIndex::ModalSurface)
}
}
impl<V, I, F> StyledExt for Div<V, I, F>
@@ -72,3 +123,5 @@ where
F: ElementFocus<V>,
{
}
impl<V> StyledExt for UniformList<V> {}