Skip to main content

guise/
paper.rs

1//! `Paper` — a raised surface: themed background, radius, padding, optional
2//! border and shadow. The base container most other surfaces build on.
3
4use gpui::prelude::*;
5use gpui::{div, px, AnyElement, App, Div, IntoElement, Window};
6
7use crate::devtools::Probed;
8use crate::theme::{theme, Size};
9
10/// A surface container.
11#[derive(IntoElement)]
12pub struct Paper {
13  children: Vec<AnyElement>,
14  padding: Size,
15  radius: Option<Size>,
16  with_border: bool,
17  shadow: Option<Size>,
18}
19
20impl Paper {
21  pub fn new() -> Self {
22    Paper {
23      children: Vec::new(),
24      padding: Size::Md,
25      radius: None,
26      with_border: false,
27      shadow: None,
28    }
29  }
30
31  pub fn padding(mut self, padding: Size) -> Self {
32    self.padding = padding;
33    self
34  }
35
36  pub fn radius(mut self, radius: Size) -> Self {
37    self.radius = Some(radius);
38    self
39  }
40
41  pub fn with_border(mut self, with_border: bool) -> Self {
42    self.with_border = with_border;
43    self
44  }
45
46  pub fn shadow(mut self, shadow: Size) -> Self {
47    self.shadow = Some(shadow);
48    self
49  }
50}
51
52impl Default for Paper {
53  fn default() -> Self {
54    Paper::new()
55  }
56}
57
58impl ParentElement for Paper {
59  fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
60    self.children.extend(elements);
61  }
62}
63
64impl RenderOnce for Paper {
65  fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
66    let t = theme(cx);
67    let radius = t.radius(self.radius.unwrap_or(t.default_radius));
68    let mut el = div()
69      .bg(t.surface().hsla())
70      .rounded(px(radius))
71      .p(px(t.spacing(self.padding)));
72    if self.with_border {
73      el = el.border_1().border_color(t.border().hsla());
74    }
75    el = apply_shadow(el, self.shadow);
76    el.children(self.children).probe("Paper")
77  }
78}
79
80pub(crate) fn apply_shadow(el: Div, shadow: Option<Size>) -> Div {
81  match shadow {
82    Some(Size::Xs) => el.shadow_xs(),
83    Some(Size::Sm) => el.shadow_sm(),
84    Some(Size::Md) => el.shadow_md(),
85    Some(Size::Lg) => el.shadow_lg(),
86    Some(Size::Xl) => el.shadow_xl(),
87    None => el,
88  }
89}