mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-23 06:19:22 -05:00
Add disabled and invalid statuses to input (#35)
* Add disabled and invalid statuses to input * pref: input component theme and style --------- Co-authored-by: Cristobal Andrada <kandrelczyk@gmail.com> Co-authored-by: luoxiao <luoxiaozero@163.com>
This commit is contained in:
parent
d0133191ec
commit
00e42b94a6
10 changed files with 187 additions and 11 deletions
|
@ -52,6 +52,32 @@ pub fn AutoCompletePage() -> impl IntoView {
|
||||||
|
|
||||||
</DemoCode>
|
</DemoCode>
|
||||||
</Demo>
|
</Demo>
|
||||||
|
<h3>"disabled"</h3>
|
||||||
|
<Demo>
|
||||||
|
<AutoComplete value options placeholder="Email" disabled=true/>
|
||||||
|
<DemoCode slot>
|
||||||
|
{highlight_str!(
|
||||||
|
r#"
|
||||||
|
<AutoComplete value options placeholder="Email" disabled=true/>
|
||||||
|
"#,
|
||||||
|
"rust"
|
||||||
|
)}
|
||||||
|
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
|
<h3>"invalid"</h3>
|
||||||
|
<Demo>
|
||||||
|
<AutoComplete value options placeholder="Email" invalid=true/>
|
||||||
|
<DemoCode slot>
|
||||||
|
{highlight_str!(
|
||||||
|
r#"
|
||||||
|
<AutoComplete value options placeholder="Email" invalid=true/>
|
||||||
|
"#,
|
||||||
|
"rust"
|
||||||
|
)}
|
||||||
|
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
<h3>"AutoComplete Props"</h3>
|
<h3>"AutoComplete Props"</h3>
|
||||||
<Table single_column=true>
|
<Table single_column=true>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -81,6 +107,18 @@ pub fn AutoCompletePage() -> impl IntoView {
|
||||||
<td>"Vec::new()"</td>
|
<td>"Vec::new()"</td>
|
||||||
<td>"Options to autocomplete from."</td>
|
<td>"Options to autocomplete from."</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"disabled"</td>
|
||||||
|
<td>"MaybeSignal<bool>"</td>
|
||||||
|
<td>"false"</td>
|
||||||
|
<td>"Whether the input is disabled."</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"invalid"</td>
|
||||||
|
<td>"MaybeSignal<bool>"</td>
|
||||||
|
<td>"false"</td>
|
||||||
|
<td>"Whether the input is invalid."</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>"clear_after_select"</td>
|
<td>"clear_after_select"</td>
|
||||||
<td>"MaybeSignal<bool>"</td>
|
<td>"MaybeSignal<bool>"</td>
|
||||||
|
|
|
@ -269,7 +269,7 @@ fn LoadingButton() -> impl IntoView {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
view! {
|
view! {
|
||||||
<h3>"Loading"</h3>
|
<h3>"loading"</h3>
|
||||||
<Demo>
|
<Demo>
|
||||||
<Space>
|
<Space>
|
||||||
<Button loading on_click icon=icondata::AiIcon::AiCloseOutlined>
|
<Button loading on_click icon=icondata::AiIcon::AiCloseOutlined>
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub fn ComponentsPage() -> impl IntoView {
|
||||||
|
|
||||||
_ = select_name.watch(move |name| {
|
_ = select_name.watch(move |name| {
|
||||||
let pathname = loaction.pathname.get_untracked();
|
let pathname = loaction.pathname.get_untracked();
|
||||||
if !pathname.starts_with(&format!("/thaw/components/{name}")) {
|
if !pathname.eq(&format!("/thaw/components/{name}")) {
|
||||||
navigate(&format!("/components/{name}"), Default::default());
|
navigate(&format!("/components/{name}"), Default::default());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,6 +32,38 @@ pub fn InputPage() -> impl IntoView {
|
||||||
|
|
||||||
</DemoCode>
|
</DemoCode>
|
||||||
</Demo>
|
</Demo>
|
||||||
|
<h3>disabled</h3>
|
||||||
|
<Demo>
|
||||||
|
<Space vertical=true>
|
||||||
|
<Input value disabled=true/>
|
||||||
|
</Space>
|
||||||
|
<DemoCode slot>
|
||||||
|
|
||||||
|
{highlight_str!(
|
||||||
|
r#"
|
||||||
|
<Input value disabled=true/>
|
||||||
|
"#,
|
||||||
|
"rust"
|
||||||
|
)}
|
||||||
|
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
|
<h3>invalid</h3>
|
||||||
|
<Demo>
|
||||||
|
<Space vertical=true>
|
||||||
|
<Input value invalid=true/>
|
||||||
|
</Space>
|
||||||
|
<DemoCode slot>
|
||||||
|
|
||||||
|
{highlight_str!(
|
||||||
|
r#"
|
||||||
|
<Input value invalid=true/>
|
||||||
|
"#,
|
||||||
|
"rust"
|
||||||
|
)}
|
||||||
|
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
<h1>"Prefix & Suffix"</h1>
|
<h1>"Prefix & Suffix"</h1>
|
||||||
<Demo>
|
<Demo>
|
||||||
<Space vertical=true>
|
<Space vertical=true>
|
||||||
|
@ -101,7 +133,7 @@ pub fn InputPage() -> impl IntoView {
|
||||||
<td>"variant"</td>
|
<td>"variant"</td>
|
||||||
<td>"MaybeSignal<InputVariant>"</td>
|
<td>"MaybeSignal<InputVariant>"</td>
|
||||||
<td>"InputVariant::Text"</td>
|
<td>"InputVariant::Text"</td>
|
||||||
<td>"Button's variant."</td>
|
<td>"Input's variant."</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>"placeholder"</td>
|
<td>"placeholder"</td>
|
||||||
|
@ -109,6 +141,18 @@ pub fn InputPage() -> impl IntoView {
|
||||||
<td>"Default::default()"</td>
|
<td>"Default::default()"</td>
|
||||||
<td>"Placeholder of input."</td>
|
<td>"Placeholder of input."</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"disabled"</td>
|
||||||
|
<td>"MaybeSignal<bool>"</td>
|
||||||
|
<td>"false"</td>
|
||||||
|
<td>"Whether the input is disabled."</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"invalid"</td>
|
||||||
|
<td>"MaybeSignal<bool>"</td>
|
||||||
|
<td>"false"</td>
|
||||||
|
<td>"Whether the input is invalid."</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>"allow_value"</td>
|
<td>"allow_value"</td>
|
||||||
<td>"Option<Callback<String, bool>>"</td>
|
<td>"Option<Callback<String, bool>>"</td>
|
||||||
|
|
|
@ -33,6 +33,38 @@ pub fn InputNumberPage() -> impl IntoView {
|
||||||
|
|
||||||
</DemoCode>
|
</DemoCode>
|
||||||
</Demo>
|
</Demo>
|
||||||
|
<h3>"disabled"</h3>
|
||||||
|
<Demo>
|
||||||
|
<Space vertical=true>
|
||||||
|
<InputNumber value step=1 disabled=true/>
|
||||||
|
</Space>
|
||||||
|
<DemoCode slot>
|
||||||
|
|
||||||
|
{highlight_str!(
|
||||||
|
r#"
|
||||||
|
<InputNumber value step=1 disabled=true/>
|
||||||
|
"#,
|
||||||
|
"rust"
|
||||||
|
)}
|
||||||
|
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
|
<h3>"invalid"</h3>
|
||||||
|
<Demo>
|
||||||
|
<Space vertical=true>
|
||||||
|
<InputNumber value step=1 invalid=true/>
|
||||||
|
</Space>
|
||||||
|
<DemoCode slot>
|
||||||
|
|
||||||
|
{highlight_str!(
|
||||||
|
r#"
|
||||||
|
<InputNumber value step=1 invalid=true/>
|
||||||
|
"#,
|
||||||
|
"rust"
|
||||||
|
)}
|
||||||
|
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
<h3>"InputNumber Props"</h3>
|
<h3>"InputNumber Props"</h3>
|
||||||
<Table single_column=true>
|
<Table single_column=true>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -64,6 +96,18 @@ pub fn InputNumberPage() -> impl IntoView {
|
||||||
"The number which the current value is increased or decreased on key or button press."
|
"The number which the current value is increased or decreased on key or button press."
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"disabled"</td>
|
||||||
|
<td>"MaybeSignal<bool>"</td>
|
||||||
|
<td>"false"</td>
|
||||||
|
<td>"Whether the input is disabled."</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>"invalid"</td>
|
||||||
|
<td>"MaybeSignal<bool>"</td>
|
||||||
|
<td>"false"</td>
|
||||||
|
<td>"Whether the input is invalid."</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
<h3>"T impl"</h3>
|
<h3>"T impl"</h3>
|
||||||
|
|
|
@ -22,6 +22,8 @@ pub fn AutoComplete(
|
||||||
#[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>,
|
#[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>,
|
||||||
#[prop(optional, into)] clear_after_select: MaybeSignal<bool>,
|
#[prop(optional, into)] clear_after_select: MaybeSignal<bool>,
|
||||||
#[prop(optional, into)] on_select: Option<Callback<String>>,
|
#[prop(optional, into)] on_select: Option<Callback<String>>,
|
||||||
|
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||||
|
#[prop(optional, into)] invalid: MaybeSignal<bool>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("auto-complete", include_str!("./auto-complete.css"));
|
mount_style("auto-complete", include_str!("./auto-complete.css"));
|
||||||
let theme = use_theme(Theme::light);
|
let theme = use_theme(Theme::light);
|
||||||
|
@ -111,6 +113,8 @@ pub fn AutoComplete(
|
||||||
<Input
|
<Input
|
||||||
value
|
value
|
||||||
placeholder
|
placeholder
|
||||||
|
disabled
|
||||||
|
invalid
|
||||||
on_focus=move |_| open_menu()
|
on_focus=move |_| open_menu()
|
||||||
on_blur=move |_| is_show_menu.set(false)
|
on_blur=move |_| is_show_menu.set(false)
|
||||||
allow_value
|
allow_value
|
||||||
|
|
|
@ -13,18 +13,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-input--focus,
|
.thaw-input--focus,
|
||||||
.thaw-input:hover {
|
.thaw-input:hover:not(.thaw-input--disabled, .thaw-input--invalid) {
|
||||||
border-color: var(--thaw-border-color-hover);
|
border-color: var(--thaw-border-color-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-input--focus {
|
.thaw-input--disabled,
|
||||||
|
.thaw-input--disabled .thaw-input__input-el {
|
||||||
|
cursor: not-allowed;
|
||||||
|
background-color: var(--thaw-background-color-disabled);
|
||||||
|
color: var(--thaw-font-color-disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-input--invalid {
|
||||||
|
border-color: var(--thaw-border-color-error);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-input--focus:not(.thaw-input--invalid) {
|
||||||
box-shadow: 0 0 0 2px var(--thaw-box-shadow-color);
|
box-shadow: 0 0 0 2px var(--thaw-box-shadow-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thaw-input--focus.thaw-input--invalid {
|
||||||
|
box-shadow: 0 0 0 2px var(--thaw-box-shadow-color-invalid);
|
||||||
|
}
|
||||||
|
|
||||||
.thaw-input__input-el {
|
.thaw-input__input-el {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
background-color: transparent;
|
background-color: transparent !important;
|
||||||
color: var(--thaw-font-color);
|
color: var(--thaw-font-color);
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
|
|
|
@ -41,6 +41,8 @@ pub fn Input(
|
||||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||||
#[prop(optional, into)] on_focus: Option<Callback<ev::FocusEvent>>,
|
#[prop(optional, into)] on_focus: Option<Callback<ev::FocusEvent>>,
|
||||||
#[prop(optional, into)] on_blur: Option<Callback<ev::FocusEvent>>,
|
#[prop(optional, into)] on_blur: Option<Callback<ev::FocusEvent>>,
|
||||||
|
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||||
|
#[prop(optional, into)] invalid: MaybeSignal<bool>,
|
||||||
#[prop(optional)] input_prefix: Option<InputPrefix>,
|
#[prop(optional)] input_prefix: Option<InputPrefix>,
|
||||||
#[prop(optional)] input_suffix: Option<InputSuffix>,
|
#[prop(optional)] input_suffix: Option<InputSuffix>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
@ -89,10 +91,26 @@ pub fn Input(
|
||||||
"--thaw-border-color: {};",
|
"--thaw-border-color: {};",
|
||||||
theme.input.border_color
|
theme.input.border_color
|
||||||
));
|
));
|
||||||
|
css_vars.push_str(&format!(
|
||||||
|
"--thaw-border-color-error: {};",
|
||||||
|
theme.common.color_error
|
||||||
|
));
|
||||||
css_vars.push_str(&format!(
|
css_vars.push_str(&format!(
|
||||||
"--thaw-placeholder-color: {};",
|
"--thaw-placeholder-color: {};",
|
||||||
theme.input.placeholder_color
|
theme.input.placeholder_color
|
||||||
));
|
));
|
||||||
|
css_vars.push_str(&format!(
|
||||||
|
"--thaw-background-color-disabled: {};",
|
||||||
|
theme.input.background_color_disabled
|
||||||
|
));
|
||||||
|
css_vars.push_str(&format!(
|
||||||
|
"--thaw-font-color-disabled: {};",
|
||||||
|
theme.input.font_color_disabled
|
||||||
|
));
|
||||||
|
css_vars.push_str(&format!(
|
||||||
|
"--thaw-box-shadow-color-invalid: {}33;",
|
||||||
|
theme.common.color_error
|
||||||
|
));
|
||||||
});
|
});
|
||||||
css_vars
|
css_vars
|
||||||
});
|
});
|
||||||
|
@ -100,6 +118,8 @@ pub fn Input(
|
||||||
<div
|
<div
|
||||||
class="thaw-input"
|
class="thaw-input"
|
||||||
class=("thaw-input--focus", move || is_focus.get())
|
class=("thaw-input--focus", move || is_focus.get())
|
||||||
|
class=("thaw-input--disabled", move || disabled.get())
|
||||||
|
class=("thaw-input--invalid", move || invalid.get())
|
||||||
style=move || css_vars.get()
|
style=move || css_vars.get()
|
||||||
>
|
>
|
||||||
{if let Some(prefix) = input_prefix {
|
{if let Some(prefix) = input_prefix {
|
||||||
|
@ -119,6 +139,7 @@ pub fn Input(
|
||||||
on:focus=on_internal_focus
|
on:focus=on_internal_focus
|
||||||
on:blur=on_internal_blur
|
on:blur=on_internal_blur
|
||||||
class="thaw-input__input-el"
|
class="thaw-input__input-el"
|
||||||
|
disabled=move || disabled.get()
|
||||||
placeholder=move || placeholder.get()
|
placeholder=move || placeholder.get()
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ pub struct InputTheme {
|
||||||
pub placeholder_color: String,
|
pub placeholder_color: String,
|
||||||
pub border_color: String,
|
pub border_color: String,
|
||||||
pub background_color: String,
|
pub background_color: String,
|
||||||
|
pub font_color_disabled: String,
|
||||||
|
pub background_color_disabled: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ThemeMethod for InputTheme {
|
impl ThemeMethod for InputTheme {
|
||||||
|
@ -15,6 +17,8 @@ impl ThemeMethod for InputTheme {
|
||||||
placeholder_color: "#c2c2c2".into(),
|
placeholder_color: "#c2c2c2".into(),
|
||||||
border_color: "#e0e0e6".into(),
|
border_color: "#e0e0e6".into(),
|
||||||
background_color: "#fff".into(),
|
background_color: "#fff".into(),
|
||||||
|
font_color_disabled: "#c2c2c2".into(),
|
||||||
|
background_color_disabled: "#fafafc".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +28,8 @@ impl ThemeMethod for InputTheme {
|
||||||
placeholder_color: "#c2c2c2".into(),
|
placeholder_color: "#c2c2c2".into(),
|
||||||
border_color: "#0000".into(),
|
border_color: "#0000".into(),
|
||||||
background_color: "#ffffff1a".into(),
|
background_color: "#ffffff1a".into(),
|
||||||
|
font_color_disabled: "#ffffff61".into(),
|
||||||
|
background_color_disabled: "#ffffff0f".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ pub fn InputNumber<T>(
|
||||||
#[prop(optional, into)] value: RwSignal<T>,
|
#[prop(optional, into)] value: RwSignal<T>,
|
||||||
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
#[prop(optional, into)] placeholder: MaybeSignal<String>,
|
||||||
#[prop(into)] step: MaybeSignal<T>,
|
#[prop(into)] step: MaybeSignal<T>,
|
||||||
|
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||||
|
#[prop(optional, into)] invalid: MaybeSignal<bool>,
|
||||||
) -> impl IntoView
|
) -> impl IntoView
|
||||||
where
|
where
|
||||||
T: Add<Output = T> + Sub<Output = T>,
|
T: Add<Output = T> + Sub<Output = T>,
|
||||||
|
@ -35,19 +37,21 @@ where
|
||||||
});
|
});
|
||||||
let step: StoredMaybeSignal<_> = step.into();
|
let step: StoredMaybeSignal<_> = step.into();
|
||||||
|
|
||||||
let add = Callback::<ev::MouseEvent>::new(move |_| {
|
let add = Callback::<ev::MouseEvent>::new(move |e: ev::MouseEvent| {
|
||||||
|
e.prevent_default();
|
||||||
value.set(value.get_untracked() + step.get_untracked());
|
value.set(value.get_untracked() + step.get_untracked());
|
||||||
});
|
});
|
||||||
let sub = Callback::<ev::MouseEvent>::new(move |_| {
|
let sub = Callback::<ev::MouseEvent>::new(move |e: ev::MouseEvent| {
|
||||||
|
e.prevent_default();
|
||||||
value.set(value.get_untracked() - step.get_untracked());
|
value.set(value.get_untracked() - step.get_untracked());
|
||||||
});
|
});
|
||||||
view! {
|
view! {
|
||||||
<Input value=input_value allow_value placeholder>
|
<Input value=input_value allow_value placeholder disabled invalid>
|
||||||
<InputSuffix slot>
|
<InputSuffix slot>
|
||||||
<Button variant=ButtonVariant::Link on_click=sub>
|
<Button disabled variant=ButtonVariant::Link on_click=sub>
|
||||||
<Icon icon=Icon::from(AiIcon::AiMinusOutlined) style="font-size: 18px"/>
|
<Icon icon=Icon::from(AiIcon::AiMinusOutlined) style="font-size: 18px"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant=ButtonVariant::Link on_click=add>
|
<Button disabled variant=ButtonVariant::Link on_click=add>
|
||||||
<Icon icon=Icon::from(AiIcon::AiPlusOutlined) style="font-size: 18px"/>
|
<Icon icon=Icon::from(AiIcon::AiPlusOutlined) style="font-size: 18px"/>
|
||||||
</Button>
|
</Button>
|
||||||
</InputSuffix>
|
</InputSuffix>
|
||||||
|
|
Loading…
Add table
Reference in a new issue