Skip to main content

patternfly_yew/components/
empty.rs

1//! Empty state
2use yew::prelude::*;
3
4use crate::prelude::{Action, Button, ButtonVariant, ExtendClasses, Icon, Size, Title};
5
6/// Properties for [`EmptyState`]
7#[derive(Clone, PartialEq, Properties)]
8pub struct EmptyStateProperties {
9    #[prop_or_default]
10    pub children: Html,
11    #[prop_or_default]
12    pub title: String,
13    #[prop_or_default]
14    pub icon: Option<Icon>,
15    #[prop_or_default]
16    pub primary: Option<Action>,
17    #[prop_or_default]
18    pub secondaries: Vec<Action>,
19    #[prop_or_default]
20    pub size: Option<Size>,
21    #[prop_or_default]
22    pub full_height: bool,
23}
24
25impl EmptyStateProperties {
26    fn title_size(&self) -> Size {
27        match self.size {
28            Some(Size::XLarge)
29            | Some(Size::XXLarge)
30            | Some(Size::XXXLarge)
31            | Some(Size::XXXXLarge) => Size::XXXXLarge,
32            _ => Size::Large,
33        }
34    }
35}
36
37/// Empty State component
38///
39/// > An **empty state** is a screen that is not yet populated with data or information. Empty states typically contain a short message and next steps for the user.
40///
41/// See: <https://www.patternfly.org/components/empty-state>
42///
43/// ## Properties
44///
45/// Define by [`EmptyStateProperties`].
46#[function_component(EmptyState)]
47pub fn empty_state(props: &EmptyStateProperties) -> Html {
48    let mut classes = Classes::from("pf-v6-c-empty-state");
49
50    if props.full_height {
51        classes.push("pf-m-full-height");
52    }
53
54    classes.extend_from(&props.size);
55
56    html! (
57        <div class={classes}>
58            <div class="pf-v6-c-empty-state__content">
59                <div class="pf-v6-c-empty-state__header">
60                    if let Some(icon) = &props.icon {
61                        <div class="pf-v6-c-empty-state__icon">{ *icon }</div>
62                    }
63                    <Title
64                        size={props.title_size()}
65                    >
66                        { props.title.clone() }
67                    </Title>
68                </div>
69                <div class="pf-v6-c-empty-state__body">{ props.children.clone() }</div>
70                if props.primary.is_some() || !props.secondaries.is_empty() {
71                    <div class="pf-v6-c-empty-state__footer">
72                        if let Some(action) = &props.primary {
73                            <div class="pf-v6-c-empty-state__actions">
74                                <Button
75                                    label={action.label.clone()}
76                                    variant={ButtonVariant::Primary}
77                                    onclick={action.callback.reform(|_|{})}
78                                />
79                            </div>
80                        }
81                        if !props.secondaries.is_empty() {
82                            <div class="pf-v6-c-empty-state__actions">
83                                { for props.secondaries.iter().map(|action|{
84                                    html!{
85                                        <Button label={action.label.clone()} variant={ButtonVariant::Link} onclick={action.callback.reform(|_|{})}/>
86                                    }
87                                }) }
88                            </div>
89                        }
90                    </div>
91                }
92            </div>
93        </div>
94    )
95}