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