ui/components/
empty_state.rs1use gpui::{AnyElement, FontWeight};
2
3use crate::prelude::*;
4
5#[derive(IntoElement, RegisterComponent)]
7pub struct EmptyState {
8 icon: IconName,
9 heading: SharedString,
10 description: Option<SharedString>,
11 action: Option<AnyElement>,
12}
13
14impl EmptyState {
15 pub fn new(heading: impl Into<SharedString>) -> Self {
16 Self {
17 icon: IconName::User,
18 heading: heading.into(),
19 description: None,
20 action: None,
21 }
22 }
23
24 pub fn icon(mut self, icon: IconName) -> Self {
25 self.icon = icon;
26 self
27 }
28
29 pub fn description(mut self, description: impl Into<SharedString>) -> Self {
30 self.description = Some(description.into());
31 self
32 }
33
34 pub fn action(mut self, action: impl IntoElement) -> Self {
35 self.action = Some(action.into_any_element());
36 self
37 }
38}
39
40impl RenderOnce for EmptyState {
41 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
42 v_flex()
43 .w_full()
44 .items_center()
45 .justify_center()
46 .gap_2()
47 .py_12()
48 .child(
49 Icon::new(self.icon)
50 .size(IconSize::XLarge)
51 .color(Color::Custom(semantic::text_muted(cx))),
52 )
53 .child(Label::new(self.heading).weight(FontWeight::MEDIUM))
54 .children(
55 self.description
56 .map(|d| Label::new(d).size(LabelSize::Small).color(Color::Muted)),
57 )
58 .children(self.action)
59 }
60}
61
62impl Component for EmptyState {
63 fn scope() -> ComponentScope {
64 ComponentScope::DataDisplay
65 }
66
67 fn description() -> Option<&'static str> {
68 Some("A centered placeholder shown when a list/table/collection has no content.")
69 }
70
71 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
72 Some(
73 v_flex()
74 .gap_6()
75 .children(vec![
76 example_group_with_title(
77 "Basic",
78 vec![single_example(
79 "No description",
80 EmptyState::new("No projects").into_any_element(),
81 )],
82 ),
83 example_group_with_title(
84 "With description and action",
85 vec![single_example(
86 "Full",
87 EmptyState::new("No projects")
88 .icon(IconName::File)
89 .description("Get started by creating a new project.")
90 .action(Button::new("new_project", "New Project"))
91 .into_any_element(),
92 )],
93 ),
94 ])
95 .into_any_element(),
96 )
97 }
98}