From b691d1baf24d23a465490f809e35527a3314a607 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 9 Jul 2024 11:27:47 -0400 Subject: [PATCH] Improve experience when themes provide transparent status colors (#13996) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We shouldn't assume all themes will give us solid status color backgrounds. This change makes it so the status color renders on top of a normal elevated surface background. #### Before | After (Transparent status background color – Fixed) ![CleanShot 2024-07-09 at 10 50 17@2x](https://github.com/zed-industries/zed/assets/1714999/5f4b24c1-335a-4ed8-a1d0-f511e217e4a5) ![CleanShot 2024-07-09 at 10 50 31@2x](https://github.com/zed-industries/zed/assets/1714999/38c06533-bda5-4cfb-822a-ed5a9639fc33) --- #### Before | After (Solid status background color – No change) ![CleanShot 2024-07-09 at 10 49 43@2x](https://github.com/zed-industries/zed/assets/1714999/bd60c807-a7bb-4f60-ab47-ddba17288e93) ![CleanShot 2024-07-09 at 10 49 58@2x](https://github.com/zed-industries/zed/assets/1714999/6ab27d60-5a77-448c-a23b-569b337f11e1) Release Notes: - Improved support for transparent status colors in themes. --- crates/editor/src/hover_popover.rs | 31 +++++++++++++++++++----------- crates/ui/src/styled_ext.rs | 31 ++++++++++++++++++++++++++++-- crates/ui/src/styles.rs | 2 ++ crates/ui/src/styles/appearance.rs | 26 +++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 13 deletions(-) create mode 100644 crates/ui/src/styles/appearance.rs diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index e0351cc2edca2dc6b2785567288bef4c3272251c..192c2d592870d9bdfb1f970209bfaafc14d168f3 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -19,7 +19,7 @@ use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart}; use settings::Settings; use smol::stream::StreamExt; use std::{ops::Range, sync::Arc, time::Duration}; -use ui::{prelude::*, Tooltip}; +use ui::{prelude::*, window_is_transparent, Tooltip}; use util::TryFutureExt; use workspace::Workspace; @@ -587,15 +587,12 @@ impl DiagnosticPopover { div() .id("diagnostic") .block() - .elevation_2(cx) - .overflow_y_scroll() - .px_2() - .py_1() - .bg(diagnostic_colors.background) - .text_color(style.text.color) - .border_1() - .border_color(diagnostic_colors.border) - .rounded_md() + .elevation_2_borderless(cx) + // Don't draw the background color if the theme + // allows transparent surfaces. + .when(window_is_transparent(cx), |this| { + this.bg(gpui::transparent_black()) + }) .max_w(max_size.width) .max_h(max_size.height) .cursor(CursorStyle::PointingHand) @@ -607,7 +604,19 @@ impl DiagnosticPopover { // because that would move the cursor. .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation()) .on_click(cx.listener(|editor, _, cx| editor.go_to_diagnostic(&Default::default(), cx))) - .child(SharedString::from(text)) + .child( + div() + .id("diagnostic-inner") + .overflow_y_scroll() + .px_2() + .py_1() + .bg(diagnostic_colors.background) + .text_color(style.text.color) + .border_1() + .border_color(diagnostic_colors.border) + .rounded_lg() + .child(SharedString::from(text)), + ) .into_any_element() } diff --git a/crates/ui/src/styled_ext.rs b/crates/ui/src/styled_ext.rs index b7f8c86a558655e449656daf99231fe27f4cf8b9..997e80ca8642e615955b96b69b58effaf2972ea6 100644 --- a/crates/ui/src/styled_ext.rs +++ b/crates/ui/src/styled_ext.rs @@ -1,16 +1,22 @@ -use gpui::{hsla, px, Styled, WindowContext}; +use gpui::{hsla, Styled, WindowContext}; use crate::prelude::*; use crate::ElevationIndex; fn elevated(this: E, cx: &mut WindowContext, index: ElevationIndex) -> E { this.bg(cx.theme().colors().elevated_surface_background) - .rounded(px(8.)) + .rounded_lg() .border_1() .border_color(cx.theme().colors().border_variant) .shadow(index.shadow()) } +fn elevated_borderless(this: E, cx: &mut WindowContext, index: ElevationIndex) -> E { + this.bg(cx.theme().colors().elevated_surface_background) + .rounded_lg() + .shadow(index.shadow()) +} + /// Extends [`gpui::Styled`] with Zed-specific styling methods. pub trait StyledExt: Styled + Sized { /// Horizontally stacks elements. @@ -36,6 +42,13 @@ pub trait StyledExt: Styled + Sized { elevated(self, cx, ElevationIndex::Surface) } + /// See [`elevation_1`]. + /// + /// Renders a borderless version [`elevation_1`]. + fn elevation_1_borderless(self, cx: &mut WindowContext) -> Self { + elevated_borderless(self, cx, ElevationIndex::Surface) + } + /// 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. /// /// Sets `bg()`, `rounded_lg()`, `border()`, `border_color()`, `shadow()` @@ -45,6 +58,13 @@ pub trait StyledExt: Styled + Sized { elevated(self, cx, ElevationIndex::ElevatedSurface) } + /// See [`elevation_2`]. + /// + /// Renders a borderless version [`elevation_2`]. + fn elevation_2_borderless(self, cx: &mut WindowContext) -> Self { + elevated_borderless(self, cx, ElevationIndex::ElevatedSurface) + } + /// 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. @@ -58,6 +78,13 @@ pub trait StyledExt: Styled + Sized { elevated(self, cx, ElevationIndex::ModalSurface) } + /// See [`elevation_3`]. + /// + /// Renders a borderless version [`elevation_3`]. + fn elevation_3_borderless(self, cx: &mut WindowContext) -> Self { + elevated_borderless(self, cx, ElevationIndex::ModalSurface) + } + /// The theme's primary border color. fn border_primary(self, cx: &mut WindowContext) -> Self { self.border_color(cx.theme().colors().border) diff --git a/crates/ui/src/styles.rs b/crates/ui/src/styles.rs index 02b9c9b1a0aa815a0143a5d0157f003e8942d716..91b016cdd8631cb942e86ddca2acc7fb2428bdbe 100644 --- a/crates/ui/src/styles.rs +++ b/crates/ui/src/styles.rs @@ -1,3 +1,4 @@ +mod appearance; mod color; mod elevation; mod platform; @@ -5,6 +6,7 @@ mod spacing; mod typography; mod units; +pub use appearance::*; pub use color::*; pub use elevation::*; pub use platform::*; diff --git a/crates/ui/src/styles/appearance.rs b/crates/ui/src/styles/appearance.rs new file mode 100644 index 0000000000000000000000000000000000000000..8e0eb51552e8e0224ed7a8e8d05c343865831255 --- /dev/null +++ b/crates/ui/src/styles/appearance.rs @@ -0,0 +1,26 @@ +use crate::prelude::*; +use gpui::{WindowBackgroundAppearance, WindowContext}; +use theme::Appearance; + +/// Returns the current [Appearance]. +pub fn appearance(cx: &WindowContext) -> Appearance { + cx.theme().appearance +} + +/// Returns the [WindowBackgroundAppearance]. +pub fn window_appearance(cx: &WindowContext) -> WindowBackgroundAppearance { + cx.theme().styles.window_background_appearance +} + +/// Returns if the window and it's surfaces are expected +/// to be transparent. +/// +/// Helps determine if you need to take extra steps to prevent +/// transparent backgrounds. +pub fn window_is_transparent(cx: &WindowContext) -> bool { + match window_appearance(cx) { + WindowBackgroundAppearance::Transparent => true, + WindowBackgroundAppearance::Blurred => true, + _ => false, + } +}