elevation.rs

 1use std::fmt::{self, Display, Formatter};
 2
 3use gpui::{hsla, point, px, BoxShadow, Hsla, WindowContext};
 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 that is above all non-modal surfaces, and separates the app from focused intents, like dialogs, alerts, modals, etc.
26    Wash,
27    /// A surface above the [ElevationIndex::Wash] that is used for dialogs, alerts, modals, etc.
28    ModalSurface,
29    /// A surface above all other surfaces, reserved exclusively for dragged elements, like a dragged file, tab or other draggable element.
30    DraggedElement,
31}
32
33impl Display for ElevationIndex {
34    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
35        match self {
36            ElevationIndex::Background => write!(f, "Background"),
37            ElevationIndex::Surface => write!(f, "Surface"),
38            ElevationIndex::EditorSurface => write!(f, "Editor Surface"),
39            ElevationIndex::ElevatedSurface => write!(f, "Elevated Surface"),
40            ElevationIndex::Wash => write!(f, "Wash"),
41            ElevationIndex::ModalSurface => write!(f, "Modal Surface"),
42            ElevationIndex::DraggedElement => write!(f, "Dragged Element"),
43        }
44    }
45}
46
47impl ElevationIndex {
48    /// Returns an appropriate shadow for the given elevation index.
49    pub fn shadow(self) -> SmallVec<[BoxShadow; 2]> {
50        match self {
51            ElevationIndex::Surface => smallvec![],
52            ElevationIndex::EditorSurface => smallvec![],
53
54            ElevationIndex::ElevatedSurface => smallvec![BoxShadow {
55                color: hsla(0., 0., 0., 0.12),
56                offset: point(px(0.), px(2.)),
57                blur_radius: px(3.),
58                spread_radius: px(0.),
59            }],
60
61            ElevationIndex::ModalSurface => smallvec![
62                BoxShadow {
63                    color: hsla(0., 0., 0., 0.12),
64                    offset: point(px(0.), px(2.)),
65                    blur_radius: px(3.),
66                    spread_radius: px(0.),
67                },
68                BoxShadow {
69                    color: hsla(0., 0., 0., 0.08),
70                    offset: point(px(0.), px(3.)),
71                    blur_radius: px(6.),
72                    spread_radius: px(0.),
73                },
74                BoxShadow {
75                    color: hsla(0., 0., 0., 0.04),
76                    offset: point(px(0.), px(6.)),
77                    blur_radius: px(12.),
78                    spread_radius: px(0.),
79                },
80            ],
81
82            _ => smallvec![],
83        }
84    }
85
86    /// Returns the background color for the given elevation index.
87    pub fn bg(&self, cx: &WindowContext) -> Hsla {
88        match self {
89            ElevationIndex::Background => cx.theme().colors().background,
90            ElevationIndex::Surface => cx.theme().colors().surface_background,
91            ElevationIndex::EditorSurface => cx.theme().colors().editor_background,
92            ElevationIndex::ElevatedSurface => cx.theme().colors().elevated_surface_background,
93            ElevationIndex::Wash => gpui::transparent_black(),
94            ElevationIndex::ModalSurface => cx.theme().colors().elevated_surface_background,
95            ElevationIndex::DraggedElement => gpui::transparent_black(),
96        }
97    }
98}