gpui_ui_kit/
card.rs

1//! Card component for content containers
2//!
3//! A flexible card component with optional header, content, and footer sections.
4
5use gpui::prelude::*;
6use gpui::*;
7
8/// A card container with optional sections
9pub struct Card {
10    header: Option<AnyElement>,
11    content: Option<AnyElement>,
12    footer: Option<AnyElement>,
13    /// Additional styling
14    extra_classes: Vec<Box<dyn FnOnce(Div) -> Div>>,
15}
16
17impl Card {
18    /// Create a new empty card
19    pub fn new() -> Self {
20        Self {
21            header: None,
22            content: None,
23            footer: None,
24            extra_classes: Vec::new(),
25        }
26    }
27
28    /// Set the card header
29    pub fn header(mut self, element: impl IntoElement) -> Self {
30        self.header = Some(element.into_any_element());
31        self
32    }
33
34    /// Set the card content
35    pub fn content(mut self, element: impl IntoElement) -> Self {
36        self.content = Some(element.into_any_element());
37        self
38    }
39
40    /// Set the card footer
41    pub fn footer(mut self, element: impl IntoElement) -> Self {
42        self.footer = Some(element.into_any_element());
43        self
44    }
45
46    /// Add custom styling to the card container
47    pub fn style(mut self, f: impl FnOnce(Div) -> Div + 'static) -> Self {
48        self.extra_classes.push(Box::new(f));
49        self
50    }
51
52    /// Build the card into an element
53    pub fn build(self) -> Div {
54        let mut card = div()
55            .flex()
56            .flex_col()
57            .bg(rgb(0x1e1e1e))
58            .border_1()
59            .border_color(rgb(0x3a3a3a))
60            .rounded_lg()
61            .shadow_md()
62            .overflow_hidden();
63
64        // Apply extra classes
65        for class_fn in self.extra_classes {
66            card = class_fn(card);
67        }
68
69        // Header section
70        if let Some(header) = self.header {
71            card = card.child(
72                div()
73                    .px_4()
74                    .py_3()
75                    .border_b_1()
76                    .border_color(rgb(0x3a3a3a))
77                    .child(header),
78            );
79        }
80
81        // Content section
82        if let Some(content) = self.content {
83            card = card.child(div().px_4().py_4().child(content));
84        }
85
86        // Footer section
87        if let Some(footer) = self.footer {
88            card = card.child(
89                div()
90                    .px_4()
91                    .py_3()
92                    .border_t_1()
93                    .border_color(rgb(0x3a3a3a))
94                    .child(footer),
95            );
96        }
97
98        card
99    }
100}
101
102impl Default for Card {
103    fn default() -> Self {
104        Self::new()
105    }
106}
107
108impl IntoElement for Card {
109    type Element = Div;
110
111    fn into_element(self) -> Self::Element {
112        self.build()
113    }
114}