patternfly_yew/components/form/
radio.rs1use crate::ouia;
2use crate::prelude::OuiaComponentType;
3use crate::utils::OuiaSafe;
4use crate::{prelude::use_prop_id, utils::Ouia};
5use std::mem::swap;
6use yew::prelude::*;
7
8const OUIA: Ouia = ouia!("Radio");
9
10#[derive(PartialEq, Properties)]
12pub struct RadioProperties {
13 #[prop_or_default]
15 pub class: Classes,
16
17 #[prop_or_default]
19 pub input_class: Classes,
20
21 #[prop_or_default]
22 pub id: Option<String>,
23
24 #[prop_or_default]
26 pub name: Option<AttrValue>,
27
28 #[prop_or_default]
29 pub value: Option<AttrValue>,
30
31 #[prop_or_default]
33 pub children: Children,
34
35 #[prop_or_default]
36 pub checked: bool,
37
38 #[prop_or_default]
39 pub reversed: bool,
40
41 #[prop_or_default]
42 pub disabled: bool,
43
44 #[prop_or_default]
46 pub description: Option<Html>,
47
48 #[prop_or_default]
50 pub body: Option<Html>,
51
52 #[prop_or_default]
54 pub onchange: Callback<()>,
55
56 #[prop_or_default]
59 pub input_onclick: Option<Callback<MouseEvent>>,
60
61 #[prop_or_default]
63 pub force_label: bool,
64
65 #[prop_or_default]
67 pub ouia_id: Option<String>,
68 #[prop_or(OUIA.component_type())]
70 pub ouia_type: OuiaComponentType,
71 #[prop_or(OuiaSafe::TRUE)]
73 pub ouia_safe: OuiaSafe,
74}
75
76#[function_component(Radio)]
86pub fn radio(props: &RadioProperties) -> Html {
87 let ouia_id = use_memo(props.ouia_id.clone(), |id| {
88 id.clone().unwrap_or(OUIA.generated_id())
89 });
90 let class = classes!("pf-v5-c-radio", props.class.clone());
91
92 let id = use_prop_id(props.id.clone());
93
94 let mut input_class = classes!(props.input_class.clone(), "pf-v5-c-radio__input");
95
96 if props.children.is_empty() && !props.force_label {
97 input_class.extend(classes!("pf-m-standalone"));
98 }
99
100 let onchange = use_callback(props.onchange.clone(), |_, onchange| {
101 onchange.emit(());
102 });
103
104 let mut first = html!(
105 <input
106 class={input_class}
107 type="radio"
108 id={(*id).clone()}
109 name={&props.name}
110 checked={props.checked}
111 disabled={props.disabled}
112 value={&props.value}
113 {onchange}
114 onclick={props.input_onclick.clone()}
115 data-ouia-component-id={(*ouia_id).clone()}
116 data-ouia-component-type={props.ouia_type}
117 data-ouia-safe={props.ouia_safe}
118 />
119 );
120
121 let mut label_class = classes!("pf-v5-c-radio__label");
122 if props.disabled {
123 label_class.extend(classes!("pf-m-disabled"));
124 }
125
126 let mut second = html!(
127 <>
128 if !props.children.is_empty() || props.force_label {
129 <label
130 class={label_class}
131 for={(*id).clone()}
132 >
133 { props.children.clone() }
134 </label>
135 }
136 </>
137 );
138
139 if props.reversed {
140 swap(&mut first, &mut second);
141 }
142
143 html!(
144 <div {class}>
145 {first} {second}
146
147 if let Some(description) = &props.description {
148 <span class="pf-v5-c-radio__description">
149 { description.clone() }
150 </span>
151 }
152
153 if let Some(body) = &props.body {
154 <span class="pf-v5-c-radio__body">
155 { body.clone() }
156 </span>
157 }
158 </div>
159 )
160}