1use gpui::prelude::*;
4use gpui::{div, px, AnyElement, App, IntoElement, Window};
5
6use crate::paper::apply_shadow;
7use crate::theme::{theme, Size};
8
9#[derive(IntoElement)]
11pub struct Card {
12 children: Vec<AnyElement>,
13 padding: Size,
14 radius: Option<Size>,
15 with_border: bool,
16 shadow: Option<Size>,
17}
18
19impl Card {
20 pub fn new() -> Self {
21 Card {
22 children: Vec::new(),
23 padding: Size::Lg,
24 radius: Some(Size::Md),
25 with_border: true,
26 shadow: Some(Size::Sm),
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 Card {
52 fn default() -> Self {
53 Card::new()
54 }
55}
56
57impl ParentElement for Card {
58 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
59 self.children.extend(elements);
60 }
61}
62
63impl RenderOnce for Card {
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(Size::Md));
67 let mut el = div()
68 .flex()
69 .flex_col()
70 .bg(t.surface().hsla())
71 .rounded(px(radius))
72 .p(px(t.spacing(self.padding)));
73 if self.with_border {
74 el = el.border_1().border_color(t.border().hsla());
75 }
76 el = apply_shadow(el, self.shadow);
77 el.children(self.children)
78 }
79}