refactor: input

This commit is contained in:
luoxiao 2024-05-10 15:47:01 +08:00
parent ed425b90f0
commit 824ca9c4b1
6 changed files with 120 additions and 110 deletions

View file

@ -1,7 +1,7 @@
# Input
```rust demo
let value = create_rw_signal(String::from("o"));
let value = RwSignal::new(String::from("o"));
view! {
<Space vertical=true>
@ -12,10 +12,35 @@ view! {
}
```
## Prefix & Suffix
```rust demo
let value = RwSignal::new(String::from("o"));
view! {
<Space vertical=true>
<Input value>
<InputPrefix slot>
<Icon icon=icondata::AiUserOutlined/>
</InputPrefix>
</Input>
<Input value>
<InputSuffix slot>
<Icon icon=icondata::AiGithubOutlined/>
</InputSuffix>
</Input>
<Input value>
<InputPrefix slot>"$"</InputPrefix>
<InputSuffix slot>".00"</InputSuffix>
</Input>
</Space>
}
```
### Disabled
```rust demo
let value = create_rw_signal(String::from("o"));
let value = RwSignal::new(String::from("o"));
view! {
<Space vertical=true>
@ -25,6 +50,14 @@ view! {
}
```
### Placeholder
```rust demo
view! {
<Input placeholder="This is a placeholder"/>
}
```
### Invalid
```rust demo
@ -78,29 +111,7 @@ view! {
}
```
## Prefix & Suffix
```rust demo
let value = create_rw_signal(String::from("o"));
view! {
<Space vertical=true>
<Input value>
<InputPrefix slot>
<Icon icon=icondata::AiUserOutlined/>
</InputPrefix>
</Input>
<Input value>
<InputSuffix slot>"$"</InputSuffix>
</Input>
<Input value>
<InputSuffix slot>
<Icon icon=icondata::AiGithubOutlined/>
</InputSuffix>
</Input>
</Space>
}
```
### Input Props

View file

@ -16,9 +16,6 @@
border: 1px solid var(--colorNeutralStroke1);
border-bottom-color: var(--colorNeutralStrokeAccessible);
border-radius: var(--borderRadiusMedium);
cursor: text;
transition: all 0.3s;
}
.thaw-input:hover {
@ -26,7 +23,12 @@
border-bottom-color: var(--colorNeutralStrokeAccessibleHover);
}
.thaw-input:active .thaw-input:focus-within {
.thaw-input:focus-within {
outline: transparent solid 2px;
}
.thaw-input:active,
.thaw-input:focus-within {
border-color: var(--colorNeutralStroke1Pressed);
border-bottom-color: var(--colorNeutralStrokeAccessiblePressed);
}
@ -56,7 +58,11 @@
transition-delay: var(--curveDecelerateMid);
}
.thaw-input__input-el {
.r1qp7m7v:focus-within:active::after {
border-bottom-color: var(--colorCompoundBrandStrokePressed);
}
.thaw-input__input {
align-self: stretch;
box-sizing: border-box;
flex-grow: 1;
@ -72,44 +78,51 @@
line-height: inherit;
}
.thaw-input--focus,
.thaw-input:hover:not(.thaw-input--disabled, .thaw-input--invalid) {
border-color: var(--thaw-border-color-hover);
.thaw-input__input::placeholder {
color: var(--colorNeutralForeground4);
opacity: 1;
}
.thaw-input--disabled,
.thaw-input--disabled .thaw-input__input-el {
.thaw-input--prefix {
padding-left: var(--spacingHorizontalMNudge);
}
.thaw-input--prefix > .thaw-input__input {
padding-left: var(--spacingHorizontalXXS);
}
.thaw-input--suffix {
padding-right: var(--spacingHorizontalMNudge);
}
.thaw-input--suffix > .thaw-input__input {
padding-right: var(--spacingHorizontalXXS);
}
.thaw-input__prefix,
.thaw-input__suffix {
display: inline-flex;
align-items: center;
justify-content: center;
}
.thaw-input.thaw-input--disabled {
border-color: var(--colorNeutralStrokeDisabled);
border-bottom-color: var(--colorNeutralStrokeDisabled);
background-color: var(--colorTransparentBackground);
cursor: not-allowed;
background-color: var(--thaw-background-color-disabled);
color: var(--thaw-font-color-disabled);
}
.thaw-input--disabled > .thaw-input__input {
background-color: var(--colorTransparentBackground);
color: var(--colorNeutralForegroundDisabled);
cursor: not-allowed;
}
.thaw-input--disabled > .thaw-input__input::placeholder {
color: var(--colorNeutralForegroundDisabled);
}
.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);
}
.thaw-input--focus.thaw-input--invalid {
box-shadow: 0 0 0 2px var(--thaw-box-shadow-color-invalid);
}
.thaw-input__input-el::placeholder {
color: var(--thaw-placeholder-color);
}
.thaw-input__prefix {
display: inline-flex;
align-items: center;
justify-content: center;
margin-right: 4px;
}
.thaw-input__suffix {
display: inline-flex;
align-items: center;
justify-content: center;
margin-left: 4px;
}

View file

@ -4,7 +4,6 @@ mod theme;
pub use text_area::{TextArea, TextAreaRef};
pub use theme::InputTheme;
use crate::theme::{use_theme, Theme};
use leptos::*;
use thaw_utils::{class_list, mount_style, ComponentRef, Model, OptionalProp};
@ -54,10 +53,9 @@ pub fn Input(
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
) -> impl IntoView {
let theme = use_theme(Theme::light);
mount_style("input", include_str!("./input.css"));
let value_trigger = create_trigger();
let value_trigger = Trigger::new();
let on_input = move |ev| {
let input_value = event_target_value(&ev);
if let Some(allow_value) = allow_value.as_ref() {
@ -68,7 +66,7 @@ pub fn Input(
}
value.set(input_value);
};
let is_focus = create_rw_signal(false);
let is_focus = RwSignal::new(false);
let on_internal_focus = move |ev| {
is_focus.set(true);
if let Some(on_focus) = on_focus.as_ref() {
@ -82,47 +80,7 @@ pub fn Input(
}
};
let css_vars = create_memo(move |_| {
let mut css_vars = String::new();
theme.with(|theme| {
let border_color_hover = theme.common.color_primary.clone();
css_vars.push_str(&format!("--thaw-border-color-hover: {border_color_hover};"));
css_vars.push_str(&format!("--thaw-box-shadow-color: {border_color_hover}33;"));
let border_radius = theme.common.border_radius.clone();
css_vars.push_str(&format!("--thaw-border-radius: {border_radius};"));
css_vars.push_str(&format!(
"--thaw-background-color: {};",
theme.input.background_color
));
css_vars.push_str(&format!("--thaw-font-color: {};", theme.input.font_color));
css_vars.push_str(&format!(
"--thaw-border-color: {};",
theme.input.border_color
));
css_vars.push_str(&format!(
"--thaw-border-color-error: {};",
theme.common.color_error
));
css_vars.push_str(&format!(
"--thaw-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
});
let input_ref = create_node_ref::<html::Input>();
let input_ref = NodeRef::<html::Input>::new();
input_ref.on_load(move |_| {
comp_ref.load(InputRef { input_ref });
});
@ -166,12 +124,13 @@ pub fn Input(
view! {
<span
class=class_list![
"thaw-input", ("thaw-input--focus", move || is_focus.get()),
"thaw-input",
("thaw-input--prefix", input_prefix.as_ref().map_or(false, |prefix| prefix.if_)),
("thaw-input--suffix", input_suffix.as_ref().map_or(false, |suffix| suffix.if_)),
("thaw-input--disabled", move || disabled.get()), ("thaw-input--invalid", move ||
invalid.get()), class.map(| c | move || c.get())
]
style=move || css_vars.get()
on:mousedown=on_mousedown
>
{if let Some(prefix) = input_prefix.and_then(|prefix| prefix.if_.then_some(prefix)) {
@ -192,7 +151,7 @@ pub fn Input(
on:input=on_input
on:focus=on_internal_focus
on:blur=on_internal_blur
class="thaw-input__input-el"
class="thaw-input__input"
disabled=move || disabled.get()
placeholder=placeholder.map(|p| move || p.get())
ref=input_ref

View file

@ -16,6 +16,7 @@ pub struct ColorTheme {
pub color_neutral_foreground_2_pressed: String,
pub color_neutral_foreground_2_brand_hover: String,
pub color_neutral_foreground_2_brand_pressed: String,
pub color_neutral_foreground_4: String,
pub color_neutral_foreground_on_brand: String,
pub color_neutral_stroke_disabled: String,
@ -23,6 +24,8 @@ pub struct ColorTheme {
pub color_neutral_stroke_1_hover: String,
pub color_neutral_stroke_1_pressed: String,
pub color_neutral_stroke_accessible: String,
pub color_neutral_stroke_accessible_hover: String,
pub color_neutral_stroke_accessible_pressed: String,
pub color_compound_brand_stroke: String,
@ -53,6 +56,7 @@ impl ColorTheme {
color_neutral_foreground_2_pressed: "#242424".into(),
color_neutral_foreground_2_brand_hover: "#0f6cbd".into(),
color_neutral_foreground_2_brand_pressed: "#115ea3".into(),
color_neutral_foreground_4: "#707070".into(),
color_neutral_foreground_on_brand: "#fff".into(),
color_neutral_stroke_disabled: "#e0e0e0".into(),
@ -60,6 +64,8 @@ impl ColorTheme {
color_neutral_stroke_1_hover: "#c7c7c7".into(),
color_neutral_stroke_1_pressed: "#b3b3b3".into(),
color_neutral_stroke_accessible: "#616161".into(),
color_neutral_stroke_accessible_hover: "#575757".into(),
color_neutral_stroke_accessible_pressed: "#4d4d4d".into(),
color_compound_brand_stroke: "#0f6cbd".into(),
@ -90,6 +96,7 @@ impl ColorTheme {
color_neutral_foreground_2_pressed: "#fff".into(),
color_neutral_foreground_2_brand_hover: "#479ef5".into(),
color_neutral_foreground_2_brand_pressed: "#2886de".into(),
color_neutral_foreground_4: "#999999".into(),
color_neutral_foreground_on_brand: "#fff".into(),
color_neutral_stroke_disabled: "#424242".into(),
@ -97,6 +104,8 @@ impl ColorTheme {
color_neutral_stroke_1_hover: "#757575".into(),
color_neutral_stroke_1_pressed: "#6b6b6b".into(),
color_neutral_stroke_accessible: "#adadad".into(),
color_neutral_stroke_accessible_hover: "#bdbdbd".into(),
color_neutral_stroke_accessible_pressed: "#b3b3b3".into(),
color_compound_brand_stroke: "#479ef5".into(),

View file

@ -38,14 +38,18 @@ pub struct CommonTheme {
pub border_radius_medium: String,
pub border_radius_circular: String,
pub spacing_horizontal_x_x_s: String,
pub spacing_horizontal_s_nudge: String,
pub spacing_horizontal_s: String,
pub spacing_horizontal_m_nudge: String,
pub spacing_horizontal_m: String,
pub spacing_horizontal_l: String,
pub duration_ultra_fast: String,
pub duration_faster: String,
pub duration_normal: String,
pub curve_accelerate_mid: String,
pub curve_decelerate_mid: String,
pub curve_easy_ease: String,
pub height_tiny: String,
@ -95,14 +99,18 @@ impl CommonTheme {
border_radius_medium: "4px".into(),
border_radius_circular: "10000px".into(),
spacing_horizontal_x_x_s: "2px".into(),
spacing_horizontal_s_nudge: "6px".into(),
spacing_horizontal_s: "8px".into(),
spacing_horizontal_m_nudge: "10px".into(),
spacing_horizontal_m: "12px".into(),
spacing_horizontal_l: "16px".into(),
duration_ultra_fast: "50ms".into(),
duration_faster: "100ms".into(),
duration_normal: "200ms".into(),
curve_accelerate_mid: "cubic-bezier(1,0,1,1)".into(),
curve_decelerate_mid: "cubic-bezier(0,0,0,1)".into(),
curve_easy_ease: "cubic-bezier(0.33,0,0.67,1)".into(),
height_tiny: "22px".into(),

View file

@ -163,6 +163,16 @@ where
}
}
impl IntoClass for (&'static str, bool) {
fn into_class(self) -> Class {
if self.1 {
Class::String(self.0.into())
} else {
Class::None
}
}
}
impl IntoClass for (&'static str, Memo<bool>) {
fn into_class(self) -> Class {
Class::Fn(self.0.into(), Box::new(move || self.1.get()))