patternfly_yew/components/
toggle_group.rs

1use std::rc::Rc;
2use yew::prelude::*;
3
4use crate::prelude::OptionalHtml;
5
6#[derive(Debug, Clone, PartialEq, Properties)]
7pub struct ToggleGroupProperties {
8    /// Content rendered inside the toggle group
9    #[prop_or_default]
10    pub children: ChildrenWithProps<ToggleGroupItem>,
11    /// Additional classes added to the toggle group
12    #[prop_or_default]
13    pub class: Classes,
14    /// Modifies the toggle group to include compact styling
15    #[prop_or_default]
16    pub compact: bool,
17    /// Disable all toggle group items under this component
18    #[prop_or_default]
19    pub all_disabled: bool,
20}
21
22#[function_component(ToggleGroup)]
23pub fn toggle_group(props: &ToggleGroupProperties) -> Html {
24    let mut class = classes!(props.class.clone(), "pf-v5-c-toggle-group");
25    if props.compact {
26        class.push("pf-m-compact");
27    };
28    html! {
29        <div {class} role="group">
30            {for props.children.iter().map(|mut item| {
31                let item_props = Rc::make_mut(&mut item.props);
32                item_props.disabled |= props.all_disabled;
33                item
34            })}
35        </div>
36    }
37}
38
39#[derive(Debug, Clone, PartialEq, Properties)]
40pub struct ToggleGroupItemProperties {
41    /// Text rendered inside the toggle group item
42    #[prop_or_default]
43    pub text: OptionalHtml,
44    /// Icon rendered inside the toggle group item
45    #[prop_or_default]
46    pub icon: OptionalHtml,
47    /// Additional classes added to the toggle group item
48    #[prop_or_default]
49    pub class: Classes,
50    /// Flag indicating if the toggle group item is disabled
51    #[prop_or_default]
52    pub disabled: bool,
53    /// Flag indicating if the toggle group item is selected
54    #[prop_or_default]
55    pub selected: bool,
56    /// A callback for when the toggle group item selection changes
57    #[prop_or_default]
58    pub onchange: Callback<()>,
59    /// A reference to the button which emits the event for onchange.
60    #[prop_or_default]
61    pub button_ref: NodeRef,
62}
63
64#[function_component(ToggleGroupItem)]
65pub fn toggle_group_item(props: &ToggleGroupItemProperties) -> Html {
66    let mut class = classes!(props.class.clone(), "pf-v5-c-toggle-group__item");
67    let mut button_class = classes!("pf-v5-c-toggle-group__button");
68    if props.selected {
69        class.push("pf-m-selected");
70        button_class.push("pf-m-selected");
71    }
72    let onclick = use_callback(props.onchange.clone(), |_, onchange| onchange.emit(()));
73    html! {
74        <div {class}>
75            <button
76                type="button"
77                class={button_class}
78                {onclick}
79                disabled={props.disabled}
80                ref={props.button_ref.clone()}
81            >
82                if let Some(icon) = (*props.icon).as_ref() {
83                    <ToggleGroupItemElement
84                        variant={ToggleGroupItemElementVariant::Icon(icon.clone())}
85                    />
86                }
87                if let Some(text) = (*props.text).as_ref() {
88                    <ToggleGroupItemElement
89                        variant={ToggleGroupItemElementVariant::Text(text.clone())}
90                    />
91                }
92            </button>
93        </div>
94    }
95}
96
97#[derive(Debug, Clone, PartialEq)]
98pub enum ToggleGroupItemElementVariant {
99    Icon(Html),
100    Text(Html),
101}
102
103#[derive(Debug, Clone, PartialEq, Properties)]
104pub struct ToggleGroupItemElementProperties {
105    #[prop_or_default]
106    variant: Option<ToggleGroupItemElementVariant>,
107}
108
109#[function_component(ToggleGroupItemElement)]
110pub fn toggle_group_item_element(props: &ToggleGroupItemElementProperties) -> Html {
111    let (class, children) = props
112        .variant
113        .as_ref()
114        .map(|v| match v {
115            ToggleGroupItemElementVariant::Icon(children) => {
116                ("pf-v5-c-toggle-group__icon", children)
117            }
118            ToggleGroupItemElementVariant::Text(children) => {
119                ("pf-v5-c-toggle-group__text", children)
120            }
121        })
122        .unzip();
123    html! {
124        <span {class} id="foo">
125            if let Some(children) = children {
126                {(*children).clone()}
127            }
128        </span>
129    }
130}