kitchen_ui/widgets/
empty.rs1use gpui_kit::component::{Icon, h_flex, v_flex};
4use gpui_kit::prelude::FluentBuilder as _;
5use gpui_kit::{AnyElement, App, FontWeight, IntoElement, ParentElement, RenderOnce, SharedString, Styled as _, Window, div, px};
6
7use crate::theme::{self, color};
8
9#[derive(IntoElement)]
11pub struct EmptyState {
12 icon: Icon,
13 title: SharedString,
14 description: SharedString,
15 actions: Vec<AnyElement>,
16}
17
18impl EmptyState {
19 pub fn new(icon: impl Into<Icon>, title: impl Into<SharedString>, description: impl Into<SharedString>) -> Self {
22 Self { icon: icon.into(), title: title.into(), description: description.into(), actions: Vec::new() }
23 }
24}
25
26impl ParentElement for EmptyState {
27 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
28 self.actions.extend(elements);
29 }
30}
31
32impl RenderOnce for EmptyState {
33 fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
34 let has_actions = !self.actions.is_empty();
35 v_flex()
36 .size_full()
37 .items_center()
38 .justify_center()
39 .gap(px(theme::SM))
40 .p(px(theme::LG))
41 .child(self.icon.size(px(32.)).text_color(color::text_muted()))
42 .child(div().pt(px(theme::XS)).text_lg().font_weight(FontWeight::SEMIBOLD).text_center().child(self.title))
43 .child(div().max_w(px(460.)).text_sm().text_center().text_color(color::text_muted()).child(self.description))
45 .when(has_actions, |d| d.child(h_flex().pt(px(theme::SM)).gap(px(theme::SM)).flex_wrap().justify_center().children(self.actions)))
46 }
47}