Skip to main content

fc_dioxus/components/
empty_state.rs

1//! What a region shows when it has nothing to show, from empty-state.css.
2use crate::{
3    core::{assets, attrs::component_attributes},
4    prelude::*,
5    theme::use_stylesheets,
6};
7const BEM: Bem = Bem::new("fc-empty");
8fc_modifier! { enum EmptySize for BEM { Regular => None, Compact => "compact" } }
9fc_modifier! { enum EmptyTone for BEM { Neutral => None, Error => "error" } }
10
11/// An empty or failed region: an icon, a title, a sentence, and what to do next.
12#[component]
13pub fn EmptyState(
14    #[props(default)] title: Option<Element>,
15    #[props(default)] heading: HeadingLevel,
16    /// Decorative; hidden from assistive technology.
17    #[props(default)]
18    icon: Option<Element>,
19    #[props(default)] body: Option<Element>,
20    #[props(default)] actions: Option<Element>,
21    #[props(default)] compact: bool,
22    #[props(default)] error: bool,
23    /// Announce the error. Set it only when a user action led here, so a page that
24    /// merely loads empty does not interrupt.
25    #[props(default)]
26    announce: bool,
27    #[props(default)] class: Option<String>,
28    #[props(extends = GlobalAttributes)] attributes: Vec<Attribute>,
29) -> Element {
30    let classes = ClassList::new(BEM.block())
31        .with_modifier(
32            BEM,
33            if compact {
34                EmptySize::Compact
35            } else {
36                EmptySize::Regular
37            },
38        )
39        .with_modifier(
40            BEM,
41            if error {
42                EmptyTone::Error
43            } else {
44                EmptyTone::Neutral
45            },
46        )
47        .extend(class.as_deref());
48    let mut attributes = component_attributes(attributes, classes, &["role"]);
49    if error && announce {
50        attributes.push(Attribute::new("role", "alert", None, false));
51    }
52    rsx! {
53        if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_EMPTY_STATE_CSS } }
54        div { ..attributes,
55            if let Some(icon) = icon { span { class: BEM.element("icon"), aria_hidden: "true", {icon} } }
56            if let Some(title) = title { {super::heading(heading, BEM.element("title"), title)} }
57            if let Some(body) = body { p { class: BEM.element("body"), {body} } }
58            if let Some(actions) = actions { div { class: BEM.element("actions"), {actions} } }
59        }
60    }
61}