From 01f589e789872d81bd690cd909404979cfc7afdf Mon Sep 17 00:00:00 2001 From: Adrien Date: Fri, 15 Mar 2024 12:24:42 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20helper=5Ftext=20to=20TextInpu?= =?UTF-8?q?t=20(previously=20TextEdit)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/mod.rs | 2 +- src/components/text_field.rs | 45 ----------------- src/components/text_field.scss | 25 ---------- src/components/text_input.rs | 88 ++++++++++++++++++++++++++++++++++ src/components/text_input.scss | 47 ++++++++++++++++++ 5 files changed, 136 insertions(+), 71 deletions(-) delete mode 100644 src/components/text_field.rs delete mode 100644 src/components/text_field.scss create mode 100644 src/components/text_input.rs create mode 100644 src/components/text_input.scss diff --git a/src/components/mod.rs b/src/components/mod.rs index 79358f3..fadbf2d 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -8,5 +8,5 @@ pub mod loading; pub mod login; pub mod main_window; pub mod spinner; -pub mod text_field; +pub mod text_input; pub mod wallpaper; diff --git a/src/components/text_field.rs b/src/components/text_field.rs deleted file mode 100644 index 632c3c5..0000000 --- a/src/components/text_field.rs +++ /dev/null @@ -1,45 +0,0 @@ -use dioxus::prelude::*; - -turf::style_sheet!("src/components/text_field.scss"); - -#[derive(Props)] -pub struct TextFieldProps<'a> { - id: Option<&'a str>, - oninput: Option>>, - placeholder: Option<&'a str>, - r#type: Option<&'a str>, - value: Option<&'a str>, - #[props(default = true)] - is_value_valid: bool, -} - -pub fn TextField<'a>(cx: Scope<'a, TextFieldProps<'a>>) -> Element<'a> { - let classes = [ - ClassName::ROOT, - if !cx.props.is_value_valid { - ClassName::INVALID_DATA - } else { - "" - }, - ] - .join(" "); - - cx.render(rsx! { - style { STYLE_SHEET }, - - input { - class: "{classes}", - - id: cx.props.id.unwrap_or(""), - - oninput: move |evt| { - if let Some(cb) = &cx.props.oninput { - cb.call(evt); - } - }, - r#type: cx.props.r#type, - placeholder: cx.props.placeholder, - value: cx.props.value, - } - }) -} diff --git a/src/components/text_field.scss b/src/components/text_field.scss deleted file mode 100644 index 75ba6c5..0000000 --- a/src/components/text_field.scss +++ /dev/null @@ -1,25 +0,0 @@ -@import "../_base.scss" - -.root { - $horizontal-padding: 1vw; - - padding-left: $horizontal-padding; - padding-right: $horizontal-padding; - padding-top: 0px; - padding-bottom: 0px; - - height: calc(100% - (2 * ($border-normal-width))); - width: calc(100% - (2 * ($border-normal-width + $horizontal-padding))); - - margin: 0; - - border: $border-normal; - border-color: $color-primary-90; - border-radius: $border-radius; - - font-size: 2vh; - - &.invalid-data { - border-color: $color-critical; - } -} diff --git a/src/components/text_input.rs b/src/components/text_input.rs new file mode 100644 index 0000000..2959e1f --- /dev/null +++ b/src/components/text_input.rs @@ -0,0 +1,88 @@ +use dioxus::prelude::*; + +turf::style_sheet!("src/components/text_input.scss"); + +#[derive(Debug)] +pub struct TextInputState { + pub is_valid: bool, + pub helper_text: Option, +} + +impl TextInputState { + pub fn new() -> Self { + TextInputState { + is_valid: true, + helper_text: None, + } + } + + pub fn reset(&mut self) { + self.is_valid = true; + self.helper_text = None; + } + + pub fn invalidate(&mut self, helper_text: String) { + self.is_valid = false; + self.helper_text = Some(helper_text); + } +} + +#[derive(Props)] +pub struct TextInputProps<'a> { + id: Option<&'a str>, + r#type: Option<&'a str>, + value: Option<&'a str>, + placeholder: Option<&'a str>, + oninput: Option>>, + state: Option<&'a UseRef>, +} + +pub fn TextInput<'a>(cx: Scope<'a, TextInputProps<'a>>) -> Element<'a> { + let mut level_class = ""; + let mut helper_text: String = "".to_string(); + + match cx.props.state { + Some(state) => { + if !state.read().is_valid { + level_class = ClassName::INVALID; + } + if let Some(text) = &state.read().helper_text { + helper_text = text.to_string(); + } + } + None => {} + } + + cx.render(rsx! { + style { STYLE_SHEET }, + + div { + class: ClassName::ROOT, + + input { + class: level_class, + + id: cx.props.id.unwrap_or(""), + + oninput: move |evt| { + if let Some(cb) = &cx.props.oninput { + cb.call(evt); + } + }, + r#type: cx.props.r#type, + placeholder: cx.props.placeholder, + value: cx.props.value, + }, + + div { + class: ClassName::HELPER_TEXT, + + p { + class: level_class, + + helper_text + } + } + } + }) +} diff --git a/src/components/text_input.scss b/src/components/text_input.scss new file mode 100644 index 0000000..1825166 --- /dev/null +++ b/src/components/text_input.scss @@ -0,0 +1,47 @@ +@import "../_base.scss" + +.root { + height: 100%; + + input { + $horizontal-padding: 1vw; + + padding-left: $horizontal-padding; + padding-right: $horizontal-padding; + padding-top: 0px; + padding-bottom: 0px; + + height: calc(100% - (2 * ($border-normal-width))); + width: calc(100% - (2 * ($border-normal-width + $horizontal-padding))); + + margin: 0; + + border: $border-normal; + border-color: $color-primary-90; + border-radius: $border-radius; + + font-size: 2vh; + + &.invalid { + border-color: $color-critical; + } + } + + .helper-text { + margin: 0; + margin-top: 0.3vh; + + font-size: 1.2vh; + + color: $color-primary-90; + + p { + margin: 0; + padding-left: 1vw; + + &.invalid { + color: $color-critical; + } + } + } +}