jinya_ui/widgets/form/
checkbox.rs

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