Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T04:47:19.034Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

list.rs

140 lines · 4.2 KB · rust
1use component::{Component, ComponentScope, example_group_with_title, single_example};
2use gpui::AnyElement;
3use smallvec::SmallVec;
4
5use crate::{Label, ListHeader, ListItem, prelude::*};
6
7pub enum EmptyMessage {
8    Text(SharedString),
9    Element(AnyElement),
10}
11
12#[derive(IntoElement, RegisterComponent)]
13pub struct List {
14    /// Message to display when the list is empty
15    /// Defaults to "No items"
16    empty_message: EmptyMessage,
17    header: Option<ListHeader>,
18    toggle: Option<bool>,
19    children: SmallVec<[AnyElement; 2]>,
20}
21
22impl Default for List {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl List {
29    pub fn new() -> Self {
30        Self {
31            empty_message: EmptyMessage::Text("No items".into()),
32            header: None,
33            toggle: None,
34            children: SmallVec::new(),
35        }
36    }
37
38    pub fn empty_message(mut self, message: impl Into<EmptyMessage>) -> Self {
39        self.empty_message = message.into();
40        self
41    }
42
43    pub fn header(mut self, header: impl Into<Option<ListHeader>>) -> Self {
44        self.header = header.into();
45        self
46    }
47
48    pub fn toggle(mut self, toggle: impl Into<Option<bool>>) -> Self {
49        self.toggle = toggle.into();
50        self
51    }
52}
53
54impl ParentElement for List {
55    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
56        self.children.extend(elements)
57    }
58}
59
60impl From<String> for EmptyMessage {
61    fn from(s: String) -> Self {
62        EmptyMessage::Text(SharedString::from(s))
63    }
64}
65
66impl From<&str> for EmptyMessage {
67    fn from(s: &str) -> Self {
68        EmptyMessage::Text(SharedString::from(s.to_owned()))
69    }
70}
71
72impl From<AnyElement> for EmptyMessage {
73    fn from(e: AnyElement) -> Self {
74        EmptyMessage::Element(e)
75    }
76}
77
78impl RenderOnce for List {
79    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
80        v_flex()
81            .w_full()
82            .py(DynamicSpacing::Base04.rems(cx))
83            .children(self.header)
84            .map(|this| match (self.children.is_empty(), self.toggle) {
85                (false, _) => this.children(self.children),
86                (true, Some(false)) => this,
87                (true, _) => match self.empty_message {
88                    EmptyMessage::Text(text) => {
89                        this.px_2().child(Label::new(text).color(Color::Muted))
90                    }
91                    EmptyMessage::Element(element) => this.child(element),
92                },
93            })
94    }
95}
96
97impl Component for List {
98    fn scope() -> ComponentScope {
99        ComponentScope::Layout
100    }
101
102    fn description() -> &'static str {
103        "A container component for displaying a collection of list items \
104        with optional header and empty state."
105    }
106
107    fn preview(_window: &mut Window, _cx: &mut App) -> AnyElement {
108        v_flex()
109            .gap_6()
110            .children(vec![example_group_with_title(
111                "Basic Lists",
112                vec![
113                    single_example(
114                        "Simple List",
115                        List::new()
116                            .child(ListItem::new("item1").child(Label::new("Item 1")))
117                            .child(ListItem::new("item2").child(Label::new("Item 2")))
118                            .child(ListItem::new("item3").child(Label::new("Item 3")))
119                            .into_any_element(),
120                    ),
121                    single_example(
122                        "With Header",
123                        List::new()
124                            .header(ListHeader::new("Section Header"))
125                            .child(ListItem::new("item1").child(Label::new("Item 1")))
126                            .child(ListItem::new("item2").child(Label::new("Item 2")))
127                            .into_any_element(),
128                    ),
129                    single_example(
130                        "Empty List",
131                        List::new()
132                            .empty_message("No items to display")
133                            .into_any_element(),
134                    ),
135                ],
136            )])
137            .into_any_element()
138    }
139}
140
Served at tenant.openagents/omega Member data and write actions are omitted.