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-v5-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-v5-c-empty-state__content">
59                <div class="pf-v5-c-empty-state__header">
60                    if let Some(icon) = &props.icon {
61                        <div class="pf-v5-c-empty-state__icon">
62                            { *icon }
63                        </div>
64                    }
65                    <Title size={ props.title_size() }>{ props.title.clone() }</Title>
66                </div>
67                <div class="pf-v5-c-empty-state__body">
68                    { props.children.clone() }
69                </div>
70                if props.primary.is_some() || !props.secondaries.is_empty() {
71                    <div class="pf-v5-c-empty-state__footer">
72                        if let Some(action) = &props.primary {
73                            <div class="pf-v5-c-empty-state__actions">
74                                <Button label={action.label.clone()} variant={ButtonVariant::Primary} onclick={action.callback.reform(|_|{})}/>
75                            </div>
76                        }
77
78                        if !props.secondaries.is_empty() {
79                            <div class="pf-v5-c-empty-state__actions">
80                                { for props.secondaries.iter().map(|action|{
81                                    html!{
82                                        <Button label={action.label.clone()} variant={ButtonVariant::Link} onclick={action.callback.reform(|_|{})}/>
83                                    }
84                                }) }
85                            </div>
86                        }
87                    </div>
88                }
89            </div>
90        </div>
91    )
92}