elevation.rs

  1use std::fmt::{self, Display, Formatter};
  2
  3use gpui::{hsla, point, px, App, BoxShadow, Hsla};
  4use smallvec::{smallvec, SmallVec};
  5use theme::ActiveTheme;
  6
  7/// Today, elevation is primarily used to add shadows to elements, and set the correct background for elements like buttons.
  8///
  9/// Elevation can be thought of as the physical closeness of an element to the
 10/// user. Elements with lower elevations are physically further away on the
 11/// z-axis and appear to be underneath elements with higher elevations.
 12///
 13/// In the future, a more complete approach to elevation may be added.
 14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 15pub enum ElevationIndex {
 16    /// On the layer of the app background. This is under panels, panes, and
 17    /// other surfaces.
 18    Background,
 19    /// The primary surface – Contains panels, panes, containers, etc.
 20    Surface,
 21    /// The same elevation as the primary surface, but used for the editable areas, like buffers
 22    EditorSurface,
 23    /// A surface that is elevated above the primary surface. but below washes, models, and dragged elements.
 24    ElevatedSurface,
 25    /// A surface above the [ElevationIndex::ElevatedSurface] that is used for dialogs, alerts, modals, etc.
 26    ModalSurface,
 27}
 28
 29impl Display for ElevationIndex {
 30    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 31        match self {
 32            ElevationIndex::Background => write!(f, "Background"),
 33            ElevationIndex::Surface => write!(f, "Surface"),
 34            ElevationIndex::EditorSurface => write!(f, "Editor Surface"),
 35            ElevationIndex::ElevatedSurface => write!(f, "Elevated Surface"),
 36            ElevationIndex::ModalSurface => write!(f, "Modal Surface"),
 37        }
 38    }
 39}
 40
 41impl ElevationIndex {
 42    /// Returns an appropriate shadow for the given elevation index.
 43    pub fn shadow(self) -> SmallVec<[BoxShadow; 2]> {
 44        match self {
 45            ElevationIndex::Surface => smallvec![],
 46            ElevationIndex::EditorSurface => smallvec![],
 47
 48            ElevationIndex::ElevatedSurface => smallvec![BoxShadow {
 49                color: hsla(0., 0., 0., 0.12),
 50                offset: point(px(0.), px(2.)),
 51                blur_radius: px(3.),
 52                spread_radius: px(0.),
 53            }],
 54
 55            ElevationIndex::ModalSurface => smallvec![
 56                BoxShadow {
 57                    color: hsla(0., 0., 0., 0.12),
 58                    offset: point(px(0.), px(2.)),
 59                    blur_radius: px(3.),
 60                    spread_radius: px(0.),
 61                },
 62                BoxShadow {
 63                    color: hsla(0., 0., 0., 0.08),
 64                    offset: point(px(0.), px(3.)),
 65                    blur_radius: px(6.),
 66                    spread_radius: px(0.),
 67                },
 68                BoxShadow {
 69                    color: hsla(0., 0., 0., 0.04),
 70                    offset: point(px(0.), px(6.)),
 71                    blur_radius: px(12.),
 72                    spread_radius: px(0.),
 73                },
 74            ],
 75
 76            _ => smallvec![],
 77        }
 78    }
 79
 80    /// Returns the background color for the given elevation index.
 81    pub fn bg(&self, cx: &mut App) -> Hsla {
 82        match self {
 83            ElevationIndex::Background => cx.theme().colors().background,
 84            ElevationIndex::Surface => cx.theme().colors().surface_background,
 85            ElevationIndex::EditorSurface => cx.theme().colors().editor_background,
 86            ElevationIndex::ElevatedSurface => cx.theme().colors().elevated_surface_background,
 87            ElevationIndex::ModalSurface => cx.theme().colors().elevated_surface_background,
 88        }
 89    }
 90
 91    /// Returns a color that is appropriate a filled element on this elevation
 92    pub fn on_elevation_bg(&self, cx: &App) -> Hsla {
 93        match self {
 94            ElevationIndex::Background => cx.theme().colors().surface_background,
 95            ElevationIndex::Surface => cx.theme().colors().background,
 96            ElevationIndex::EditorSurface => cx.theme().colors().surface_background,
 97            ElevationIndex::ElevatedSurface => cx.theme().colors().background,
 98            ElevationIndex::ModalSurface => cx.theme().colors().background,
 99        }
100    }
101
102    /// Attempts to return a darker background color than the current elevation index's background.
103    ///
104    /// If the current background color is already dark, it will return a lighter color instead.
105    pub fn darker_bg(&self, cx: &App) -> Hsla {
106        match self {
107            ElevationIndex::Background => cx.theme().colors().surface_background,
108            ElevationIndex::Surface => cx.theme().colors().editor_background,
109            ElevationIndex::EditorSurface => cx.theme().colors().surface_background,
110            ElevationIndex::ElevatedSurface => cx.theme().colors().editor_background,
111            ElevationIndex::ModalSurface => cx.theme().colors().editor_background,
112        }
113    }
114}