refactor: Slider

This commit is contained in:
luoxiao 2024-05-30 17:11:24 +08:00
parent 61b937f688
commit add2a0bae3
6 changed files with 138 additions and 56 deletions

View file

@ -1,10 +1,7 @@
mod slider_label;
mod theme;
pub use slider_label::SliderLabel;
pub use theme::SliderTheme;
use crate::{theme::use_theme, Theme};
use leptos::*;
use thaw_components::OptionComp;
use thaw_utils::{class_list, mount_style, Model, OptionalProp};
@ -19,23 +16,6 @@ pub fn Slider(
#[prop(optional)] children: Option<Children>,
) -> impl IntoView {
mount_style("slider", include_str!("./slider.css"));
let theme = use_theme(Theme::light);
let css_vars = create_memo(move |_| {
let mut css_vars = String::new();
css_vars.push_str(&format!("--thaw-slider-max: {};", max.get()));
theme.with(|theme| {
css_vars.push_str(&format!(
"--thaw-background-color: {};",
&theme.slider.background_color
));
css_vars.push_str(&format!(
"--thaw-background-color-fill: {};",
&theme.common.color_primary
));
});
css_vars
});
let percentage = create_memo(move |_| {
if value.get() < 0.0 || max.get() <= 0.0 {
@ -116,14 +96,13 @@ pub fn Slider(
view! {
<div
class=class_list!["thaw-slider", class.map(| c | move || c.get())]
style=move || css_vars.get()
style=move || format!("--thaw-slider--direction: 90deg;--thaw-slider--progress: {:.2}%", value.get())
on:click=on_mouse_click
>
<div class="thaw-slider-rail" ref=rail_ref>
<div
class="thaw-slider-rail__fill"
style=move || format!("width: {}%", percentage.get())
></div>
<input type="range" class="thaw-slider__input"/>
<div class="thaw-slider__rail" ref=rail_ref>
</div>
<div class="thaw-slider__thumb">
</div>
<OptionComp value=children let:children>
{children()}

View file

@ -1,9 +1,130 @@
.thaw-slider {
min-width: 120px;
min-height: 32px;
justify-items: center;
touch-action: none;
display: inline-grid;
grid-template-columns: 1fr calc(100% - var(--thaw-slider__thumb--size)) 1fr;
grid-template-rows: 1fr var(--thaw-slider__thumb--size) 1fr;
position: relative;
padding: 6px 0;
cursor: pointer;
user-select: none;
align-items: center;
--thaw-slider__rail--size: 4px;
--thaw-slider__thumb--size: 20px;
--thaw-slider__thumb--color: var(--colorCompoundBrandBackground);
--thaw-slider__progress--color: var(--colorCompoundBrandBackground);
--thaw-slider__rail--color: var(--colorNeutralStrokeAccessible);
}
.thaw-slider:hover {
--thaw-slider__progress--color: var(--colorCompoundBrandBackgroundHover);
--thaw-slider__thumb--color: var(--colorCompoundBrandBackgroundHover);
}
.thaw-slider:active {
--thaw-slider__progress--color: var(--colorCompoundBrandBackgroundPressed);
--thaw-slider__thumb--color: var(--colorCompoundBrandBackgroundPressed);
}
.thaw-slider:focus,
.thaw-slider:focus-visible {
outline-style: none;
}
.thaw-slider__input {
grid-column-end: -1;
grid-column-start: 1;
grid-row-end: -1;
grid-row-start: 1;
margin: 0;
padding: 0;
opacity: 0;
width: 100%;
height: var(--thaw-slider__thumb--size);
cursor: pointer;
}
.thaw-slider__rail {
position: relative;
forced-color-adjust: none;
grid-column-end: 2;
grid-column-start: 2;
grid-row-end: 2;
grid-row-start: 2;
width: 100%;
height: var(--thaw-slider__rail--size);
background-image: linear-gradient(
var(--thaw-slider--direction),
var(--thaw-slider__progress--color) 0%,
var(--thaw-slider__progress--color) var(--thaw-slider--progress),
var(--thaw-slider__rail--color) var(--thaw-slider--progress)
);
border-radius: var(--borderRadiusXLarge);
outline: 1px solid var(--colorTransparentStroke);
pointer-events: none;
}
.thaw-slider__rail::before {
content: "";
position: absolute;
height: var(--thaw-slider__rail--size);
right: -1px;
left: -1px;
background-image: repeating-linear-gradient(
var(--thaw-slider--direction),
#0000 0%,
#0000 calc(var(--thaw-slider--steps-percent) - 1px),
var(--colorNeutralBackground1)
calc(var(--thaw-slider--steps-percent) - 1px),
var(--colorNeutralBackground1) var(--thaw-slider--steps-percent)
);
}
.thaw-slider__thumb {
position: absolute;
forced-color-adjust: none;
grid-column-end: 2;
grid-column-start: 2;
grid-row-end: 2;
grid-row-start: 2;
height: var(--thaw-slider__thumb--size);
width: var(--thaw-slider__thumb--size);
left: var(--thaw-slider--progress);
background-color: var(--thaw-slider__thumb--color);
outline-style: none;
pointer-events: none;
border-radius: var(--borderRadiusCircular);
box-shadow: 0 0 0 calc(var(--thaw-slider__thumb--size) * 0.2)
var(--colorNeutralBackground1) inset;
transform: translateX(-50%);
}
.thaw-slider__thumb::before {
content: "";
position: absolute;
bottom: 0px;
right: 0px;
left: 0px;
top: 0px;
box-sizing: border-box;
border-radius: var(--borderRadiusCircular);
border: calc(var(--thaw-slider__thumb--size) * 0.05) solid
var(--colorNeutralStroke1);
}
.thaw-slider-rail {
height: 4px;
background-color: var(--thaw-background-color);

View file

@ -1,20 +0,0 @@
use crate::theme::ThemeMethod;
#[derive(Clone)]
pub struct SliderTheme {
pub background_color: String,
}
impl ThemeMethod for SliderTheme {
fn light() -> Self {
Self {
background_color: "#dbdbdf".into(),
}
}
fn dark() -> Self {
Self {
background_color: "#ffffff33".into(),
}
}
}

View file

@ -52,6 +52,7 @@ pub struct ColorTheme {
pub color_transparent_background: String,
pub color_transparent_background_hover: String,
pub color_transparent_background_pressed: String,
pub color_transparent_stroke: String,
pub shadow4: String,
}
@ -109,6 +110,7 @@ impl ColorTheme {
color_transparent_background: "transparent".into(),
color_transparent_background_hover: "transparent".into(),
color_transparent_background_pressed: "transparent".into(),
color_transparent_stroke: "transparent".into(),
shadow4: "0 0 2px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.14)".into(),
}
@ -166,6 +168,7 @@ impl ColorTheme {
color_transparent_background: "transparent".into(),
color_transparent_background_hover: "transparent".into(),
color_transparent_background_pressed: "transparent".into(),
color_transparent_stroke: "transparent".into(),
shadow4: "0 0 2px rgba(0,0,0,0.24), 0 2px 4px rgba(0,0,0,0.28)".into(),
}

View file

@ -43,6 +43,7 @@ pub struct CommonTheme {
pub border_radius_none: String,
pub border_radius_medium: String,
pub border_radius_x_large: String,
pub border_radius_circular: String,
pub spacing_horizontal_x_x_s: String,
@ -115,6 +116,7 @@ impl CommonTheme {
border_radius_none: "0".into(),
border_radius_medium: "4px".into(),
border_radius_x_large: "8px".into(),
border_radius_circular: "10000px".into(),
spacing_horizontal_x_x_s: "2px".into(),

View file

@ -6,8 +6,8 @@ use crate::{
mobile::{NavBarTheme, TabbarTheme},
AlertTheme, AnchorTheme, AutoCompleteTheme, BackTopTheme, BreadcrumbTheme, CalendarTheme,
ColorPickerTheme, DatePickerTheme, InputTheme, MenuTheme, MessageTheme, PopoverTheme,
ProgressTheme, ScrollbarTheme, SelectTheme, SkeletionTheme, SliderTheme, SpinnerTheme,
SwitchTheme, TableTheme, TagTheme, TimePickerTheme, UploadTheme,
ProgressTheme, ScrollbarTheme, SelectTheme, SkeletionTheme, SpinnerTheme, SwitchTheme,
TableTheme, TagTheme, TimePickerTheme, UploadTheme,
};
pub use color::ColorTheme;
use leptos::*;
@ -30,7 +30,6 @@ pub struct Theme {
pub tag: TagTheme,
pub message: MessageTheme,
pub select: SelectTheme,
pub slider: SliderTheme,
pub switch: SwitchTheme,
pub spinner: SpinnerTheme,
pub upload: UploadTheme,
@ -63,7 +62,6 @@ impl Theme {
tag: TagTheme::light(),
message: MessageTheme::light(),
select: SelectTheme::light(),
slider: SliderTheme::light(),
switch: SwitchTheme::light(),
spinner: SpinnerTheme::light(),
upload: UploadTheme::light(),
@ -95,7 +93,6 @@ impl Theme {
tag: TagTheme::dark(),
message: MessageTheme::dark(),
select: SelectTheme::dark(),
slider: SliderTheme::dark(),
switch: SwitchTheme::dark(),
spinner: SpinnerTheme::dark(),
upload: UploadTheme::dark(),