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