patternfly_yew/components/page/
section.rs

1use crate::core::{AsClasses, ExtendClasses, WithBreakpoints};
2use yew::html::IntoPropValue;
3use yew::prelude::*;
4
5/// Properties for [`PageSection`]
6#[derive(Copy, Clone, Default, Eq, PartialEq)]
7pub enum PageSectionVariant {
8    #[default]
9    Default,
10    Darker,
11    Dark,
12    Light,
13}
14
15impl AsClasses for PageSectionVariant {
16    fn extend_classes(&self, classes: &mut Classes) {
17        match self {
18            Self::Default => {}
19            Self::Darker => classes.push("pf-m-dark-100"),
20            Self::Dark => classes.push("pf-m-dark-200"),
21            Self::Light => classes.push("pf-m-light"),
22        }
23    }
24}
25
26#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
27pub enum PageSectionType {
28    #[default]
29    Default,
30    Breadcrumbs,
31    Navigation,
32    SubNavigation,
33    Tabs,
34    Wizard,
35}
36
37impl AsClasses for PageSectionType {
38    fn extend_classes(&self, classes: &mut Classes) {
39        match self {
40            Self::Default => classes.push("pf-v5-c-page__main-section"),
41            Self::Breadcrumbs => classes.push("pf-v5-c-page__main-breadcrumb"),
42            Self::Navigation => classes.push("pf-v5-c-page__main-nav"),
43            Self::SubNavigation => classes.push("pf-v5-c-page__main-subnav"),
44            Self::Tabs => classes.push("pf-v5-c-page__main-tabs"),
45            Self::Wizard => classes.push("pf-v5-c-page__main-wizard"),
46        }
47    }
48}
49
50#[derive(Clone, PartialEq, Properties)]
51pub struct PageSectionProperties {
52    #[prop_or_default]
53    pub children: Html,
54    #[prop_or_default]
55    pub r#type: PageSectionType,
56    #[prop_or_default]
57    pub variant: PageSectionVariant, // Should only be used on PageSectionType::Main
58    #[prop_or_default]
59    pub fill: PageSectionFill,
60    #[prop_or_default]
61    pub limit_width: bool,
62    #[prop_or_default]
63    pub shadow: PageSectionShadow,
64    #[prop_or_default]
65    pub align_center: bool,
66    #[prop_or_default]
67    pub overflow_scroll: bool,
68    #[prop_or_default]
69    pub sticky: WithBreakpoints<PageSectionSticky>,
70
71    #[prop_or_default]
72    pub id: Option<AttrValue>,
73    #[prop_or_default]
74    pub class: Classes,
75    #[prop_or_default]
76    pub style: Option<AttrValue>,
77
78    #[prop_or_default]
79    pub hidden: bool,
80}
81
82#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
83pub enum PageSectionShadow {
84    #[default]
85    None,
86    Top,
87    Bottom,
88    Both,
89}
90
91impl AsClasses for PageSectionShadow {
92    fn extend_classes(&self, classes: &mut Classes) {
93        match self {
94            Self::None => {}
95            Self::Top => classes.push("pf-m-shadow-top"),
96            Self::Bottom => classes.push("pf-m-shadow-bottom"),
97            Self::Both => classes.push("pf-m-shadow-top pf-m-shadow-bottom"),
98        }
99    }
100}
101
102#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
103pub enum PageSectionSticky {
104    #[default]
105    None,
106    Top,
107    Bottom,
108    Both,
109}
110
111impl AsClasses for PageSectionSticky {
112    fn extend_classes(&self, classes: &mut Classes) {
113        match self {
114            Self::None => {}
115            Self::Top => classes.push("pf-m-sticky-top"),
116            Self::Bottom => classes.push("pf-m-sticky-bottom"),
117            Self::Both => classes.push("pf-m-sticky-top pf-m-sticky-bottom"),
118        }
119    }
120}
121
122#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
123pub enum PageSectionFill {
124    #[default]
125    Default,
126    Fill,
127    NoFill,
128}
129
130impl AsClasses for PageSectionFill {
131    fn extend_classes(&self, classes: &mut Classes) {
132        match self {
133            Self::Default => {}
134            Self::Fill => classes.push("pf-m-fill"),
135            Self::NoFill => classes.push("pf-m-no-fill"),
136        }
137    }
138}
139
140impl IntoPropValue<PageSectionFill> for bool {
141    fn into_prop_value(self) -> PageSectionFill {
142        match self {
143            true => PageSectionFill::Fill,
144            false => PageSectionFill::NoFill,
145        }
146    }
147}
148
149/// A page section, a child of a [`Page`](crate::prelude::Page) component.
150///
151/// ## Properties
152///
153/// Defined by [`PageSectionProperties`].
154///
155/// ## Example
156///
157/// ```rust
158/// use yew::prelude::*;
159/// use patternfly_yew::prelude::*;
160///
161/// #[function_component(MyPage)]
162/// fn my_page() -> Html {
163///   html!(
164///     <Page>
165///       <PageSection>{"my content"}</PageSection>
166///     </Page>
167///   )
168/// }
169/// ```
170#[function_component(PageSection)]
171pub fn page_section(props: &PageSectionProperties) -> Html {
172    // start with the main type
173
174    let mut class = props.r#type.as_classes();
175
176    // extend with options
177
178    class.extend_from(&props.variant);
179    class.extend_from(&props.fill);
180    class.extend_from(&props.sticky);
181    class.extend_from(&props.shadow);
182
183    if props.limit_width {
184        class.push("pf-m-limit-width");
185    }
186
187    if props.align_center {
188        class.push("pf-m-align-center"); // Can only be used with limit_width
189    }
190
191    if props.overflow_scroll {
192        class.push("pf-m-overflow-scroll"); // Can only be used with PageSectionType::Default
193    }
194
195    class.extend(&props.class);
196
197    // render
198
199    html! (
200        <section {class} id={&props.id} hidden={props.hidden} style={props.style.clone()}>
201            if props.limit_width {
202                <div class="pf-v5-c-page__main-body">
203                    { props.children.clone() }
204                </div>
205            } else {
206                { props.children.clone() }
207            }
208         </section>
209    )
210}
211
212/// Properties for [`PageSectionGroup`]
213#[derive(PartialEq, Properties)]
214pub struct PageSectionGroupProperties {
215    pub children: Html,
216    #[prop_or_default]
217    pub shadow: PageSectionShadow,
218    #[prop_or_default]
219    pub sticky: WithBreakpoints<PageSectionSticky>,
220    #[prop_or_default]
221    pub overflow_scroll: bool,
222}
223
224#[function_component(PageSectionGroup)]
225pub fn page_section_group(props: &PageSectionGroupProperties) -> Html {
226    let mut class = Classes::from("pf-v5-c-page__main-group");
227
228    class.extend_from(&props.shadow);
229    class.extend_from(&props.sticky);
230
231    if props.overflow_scroll {
232        class.push("pf-m-overflow-scroll");
233    }
234
235    html!(
236        <div {class}>
237            { props.children.clone() }
238        </div>
239    )
240}