1use gpui::AnyElement;
2use smallvec::SmallVec;
3
4use crate::{prelude::*, v_flex, Label, ListHeader};
5
6#[derive(IntoElement)]
7pub struct List {
8 /// Message to display when the list is empty
9 /// Defaults to "No items"
10 empty_message: SharedString,
11 header: Option<ListHeader>,
12 toggle: Option<bool>,
13 children: SmallVec<[AnyElement; 2]>,
14}
15
16impl Default for List {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22impl List {
23 pub fn new() -> Self {
24 Self {
25 empty_message: "No items".into(),
26 header: None,
27 toggle: None,
28 children: SmallVec::new(),
29 }
30 }
31
32 pub fn empty_message(mut self, empty_message: impl Into<SharedString>) -> Self {
33 self.empty_message = empty_message.into();
34 self
35 }
36
37 pub fn header(mut self, header: impl Into<Option<ListHeader>>) -> Self {
38 self.header = header.into();
39 self
40 }
41
42 pub fn toggle(mut self, toggle: impl Into<Option<bool>>) -> Self {
43 self.toggle = toggle.into();
44 self
45 }
46}
47
48impl ParentElement for List {
49 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
50 self.children.extend(elements)
51 }
52}
53
54impl RenderOnce for List {
55 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
56 v_flex()
57 .w_full()
58 .py(Spacing::Small.rems(cx))
59 .children(self.header)
60 .map(|this| match (self.children.is_empty(), self.toggle) {
61 (false, _) => this.children(self.children),
62 (true, Some(false)) => this,
63 (true, _) => this.child(Label::new(self.empty_message.clone()).color(Color::Muted)),
64 })
65 }
66}