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