ashlar_ui/content/
empty_state.rs1use egui::{Response, RichText, Sense, Ui, vec2};
4
5use crate::automation::{self, Details, Role};
6use crate::controls::{Button, IconPainter, Variant};
7use crate::tokens;
8
9pub struct EmptyState<'a> {
12 id: &'a str,
13 title: &'a str,
14 body: Option<&'a str>,
15 action: Option<&'a str>,
16 icon: Option<IconPainter<'a>>,
17}
18
19pub struct EmptyStateOutput {
21 pub response: Response,
23 pub action: bool,
25}
26
27impl<'a> EmptyState<'a> {
28 pub fn new(id: &'a str, title: &'a str) -> Self {
29 EmptyState { id, title, body: None, action: None, icon: None }
30 }
31 pub fn body(mut self, text: &'a str) -> Self {
33 self.body = Some(text);
34 self
35 }
36 pub fn action(mut self, label: &'a str) -> Self {
38 self.action = Some(label);
39 self
40 }
41 pub fn icon(mut self, paint: IconPainter<'a>) -> Self {
43 self.icon = Some(paint);
44 self
45 }
46
47 pub fn show(self, ui: &mut Ui) -> EmptyStateOutput {
48 let t = tokens::current(ui.ctx());
49 let mut action = false;
50 let inner = ui.vertical_centered(|ui| {
51 let title = self.title;
52 ui.ctx().accesskit_node_builder(ui.unique_id(), |node| {
53 node.set_role(egui::accesskit::Role::Group);
54 node.set_label(title);
55 });
56 ui.add_space(t.space.xl);
57 if let Some(paint) = self.icon {
58 let side = t.control_height * 1.5;
59 let (rect, _) = ui.allocate_exact_size(vec2(side, side), Sense::hover());
60 paint(ui.painter(), rect, t.text.secondary);
61 ui.add_space(t.space.md);
62 }
63 ui.label(RichText::new(self.title).size(t.type_scale.heading).strong().color(t.text.primary));
64 if let Some(body) = self.body {
65 ui.add_space(t.space.xs);
66 ui.label(RichText::new(body).color(t.text.secondary));
67 }
68 if let Some(label) = self.action {
69 ui.add_space(t.space.lg);
70 action = Button::new(self.id, label).part("action").variant(Variant::Primary).show(ui).clicked();
71 }
72 ui.add_space(t.space.xl);
73 });
74 let response = inner.response;
75 automation::register_with(ui, &response, self.id, self.title, Role::Group, Details { value: self.body, selected: None });
76 EmptyStateOutput { response, action }
77 }
78}