jinya_ui/widgets/form/
radio.rs1use yew::prelude::*;
2use yew::{Callback, Component, ComponentLink, Html};
3
4pub fn get_css<'a>() -> &'a str {
5 "
7.jinya-radio__color-container {
8 flex: 0 0 100%;
9}
10
11.jinya-radio__color-container--default {
12 --state-color: var(--primary-color);
13}
14
15.jinya-radio__color-container--negative {
16 --state-color: var(--negative-color);
17}
18
19.jinya-radio__color-container--positive {
20 --state-color: var(--positive-color);
21}
22
23.jinya-radio__color-container--disabled {
24 --state-color: var(--disabled-border-color);
25}
26
27.jinya-radio__input {
28 visibility: hidden;
29 position: absolute;
30}
31
32.jinya-radio__input:invalid {
33 outline: none;
34 box-shadow: none;
35 border: none;
36}
37
38.jinya-radio__label {
39 display: block;
40 font-size: var(--font-size-16);
41 color: var(--state-color);
42 background: var(--white);
43 padding-left: 0.25rem;
44 padding-right: 0.25rem;
45 box-sizing: border-box;
46 position: relative;
47}
48
49.jinya-radio__label::before,
50.jinya-radio__label::after {
51 content: '';
52 display: none;
53}
54
55.jinya-radio__label::before {
56 width: 1rem;
57 height: 1rem;
58 display: inline-block;
59 border: 2px solid var(--state-color);
60 border-radius: 50%;
61 box-sizing: border-box;
62 margin-right: 0.5rem;
63 background: var(--white);
64}
65
66.jinya-radio__label:hover::before {
67 background: var(--input-background-color);
68}
69
70.jinya-radio__label::after {
71 position: absolute;
72 top: 5px;
73 left: 7px;
74 height: 10px;
75 width: 10px;
76 border-radius: 50%;
77 transform: rotate(45deg);
78 background: var(--state-color);
79}
80
81.jinya-radio__input:checked + .jinya-radio__label::after {
82 display: block;
83}
84
85.jinya-radio__validation-message {
86 display: block;
87 font-size: var(--font-size-12);
88 color: var(--state-color);
89}
90"
91}
92
93#[derive(Clone, PartialEq)]
94pub enum RadioState {
95 Default,
96 Negative,
97 Positive,
98}
99
100pub struct Radio {
101 link: ComponentLink<Self>,
102 label: String,
103 on_change: Callback<()>,
104 state: RadioState,
105 validation_message: String,
106 checked: bool,
107 group: String,
108 value: String,
109 disabled: bool,
110}
111
112#[derive(Clone, PartialEq, Properties)]
113pub struct RadioProps {
114 pub label: String,
115 pub on_change: Callback<()>,
116 #[prop_or(RadioState::Default)]
117 pub state: RadioState,
118 #[prop_or("".to_string())]
119 pub validation_message: String,
120 pub checked: bool,
121 pub group: String,
122 pub value: String,
123 #[prop_or(false)]
124 pub disabled: bool,
125}
126
127pub enum Msg {
128 Change,
129}
130
131impl Default for RadioState {
132 fn default() -> Self {
133 RadioState::Default
134 }
135}
136
137impl Radio {
138 fn get_radio_container_class(&self) -> String {
139 let class = match self.state {
140 RadioState::Default => {
141 "jinya-radio__color-container jinya-radio__color-container--default"
142 }
143 RadioState::Negative => {
144 "jinya-radio__color-container jinya-radio__color-container--negative"
145 }
146 RadioState::Positive => {
147 "jinya-radio__color-container jinya-radio__color-container--positive"
148 }
149 }
150 .to_string();
151
152 if self.disabled {
153 "jinya-radio__color-container jinya-radio__color-container--disabled".to_string()
154 } else {
155 class
156 }
157 }
158}
159
160impl Component for Radio {
161 type Message = Msg;
162 type Properties = RadioProps;
163
164 fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
165 Radio {
166 link,
167 label: props.label,
168 state: props.state,
169 validation_message: props.validation_message,
170 on_change: props.on_change,
171 checked: props.checked,
172 group: props.group,
173 value: props.value,
174 disabled: props.disabled,
175 }
176 }
177
178 fn update(&mut self, msg: Self::Message) -> bool {
179 match msg {
180 Msg::Change => {
181 self.on_change.emit(());
182 }
183 }
184
185 false
186 }
187
188 fn change(&mut self, _props: Self::Properties) -> bool {
189 self.label = _props.label;
190 self.state = _props.state;
191 self.validation_message = _props.validation_message;
192 self.on_change = _props.on_change;
193 self.checked = _props.checked;
194 self.group = _props.group;
195 self.value = _props.value;
196 self.disabled = _props.disabled;
197
198 true
199 }
200
201 fn view(&self) -> Html {
202 let id = super::super::super::id_generator::generate_id();
203 html! {
204 <div class=self.get_radio_container_class()>
205 <div class="jinya-radio__container">
206 <input
207 id=id
208 type="radio"
209 onchange=self.link.callback(|_| Msg::Change)
210 checked=self.checked
211 name=&self.group
212 class="jinya-radio__input"
213 value=&self.value
214 disabled=self.disabled
215 />
216 <label for=id class="jinya-radio__label">{&self.label}</label>
217 </div>
218 <span class="jinya-radio__validation-message">{&self.validation_message}</span>
219 </div>
220 }
221 }
222}