mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 22:09:22 -05:00
refactor: switch
This commit is contained in:
parent
f5c0d2a522
commit
dd50d450ff
5 changed files with 98 additions and 83 deletions
|
@ -1,10 +1,10 @@
|
|||
# Switch
|
||||
|
||||
```rust demo
|
||||
let value = create_rw_signal(false);
|
||||
let checked = RwSignal::new(false);
|
||||
|
||||
view! {
|
||||
<Switch value />
|
||||
<Switch checked />
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -1,46 +1,51 @@
|
|||
mod theme;
|
||||
|
||||
pub use theme::SwitchTheme;
|
||||
|
||||
use crate::{theme::use_theme, Theme};
|
||||
use leptos::*;
|
||||
use thaw_utils::{class_list, mount_style, Model, OptionalProp};
|
||||
|
||||
#[component]
|
||||
pub fn Switch(
|
||||
#[prop(optional, into)] value: Model<bool>,
|
||||
#[prop(optional, into)] checked: Model<bool>,
|
||||
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
|
||||
#[prop(optional, into)] label: MaybeProp<String>,
|
||||
) -> impl IntoView {
|
||||
mount_style("switch", include_str!("./switch.css"));
|
||||
let theme = use_theme(Theme::light);
|
||||
let css_vars = create_memo(move |_| {
|
||||
let mut css_vars = String::new();
|
||||
theme.with(|theme| {
|
||||
css_vars.push_str(&format!(
|
||||
"--thaw-background-color: {};",
|
||||
theme.switch.background_color
|
||||
));
|
||||
css_vars.push_str(&format!(
|
||||
"--thaw-background-color-active: {};",
|
||||
theme.common.color_primary
|
||||
));
|
||||
});
|
||||
css_vars
|
||||
});
|
||||
|
||||
let id = uuid::Uuid::new_v4().to_string();
|
||||
let input_ref = NodeRef::<html::Input>::new();
|
||||
let on_change = move |_| {
|
||||
let input = input_ref.get_untracked().unwrap();
|
||||
checked.set(input.checked());
|
||||
};
|
||||
|
||||
view! {
|
||||
<div
|
||||
class=class_list![
|
||||
"thaw-switch", ("thaw-switch--active", move || value.get()), class.map(| c | move ||
|
||||
"thaw-switch", class.map(| c | move ||
|
||||
c.get())
|
||||
]
|
||||
|
||||
style=move || css_vars.get()
|
||||
on:click=move |_| value.set(!value.get_untracked())
|
||||
role="switch"
|
||||
aria-checked=move || if value.get() { "true" } else { "false" }
|
||||
>
|
||||
<div class="thaw-switch__button"></div>
|
||||
<input
|
||||
class="thaw-switch__input"
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
id=id.clone()
|
||||
checked=checked.get_untracked()
|
||||
ref=input_ref
|
||||
on:change=on_change
|
||||
/>
|
||||
<div aria-hidden="true" class="thaw-switch__indicator thaw-switch__button">
|
||||
<svg fill="currentColor" aria-hidden="true" width="1em" height="1em" viewBox="0 0 20 20">
|
||||
<path d="M10 2a8 8 0 1 0 0 16 8 8 0 0 0 0-16Z" fill="currentColor"></path>
|
||||
</svg>
|
||||
</div>
|
||||
{
|
||||
move || if let Some(label) = label.get() {
|
||||
view! {
|
||||
<label class="thaw-switch__label" for=id.clone()>{label}</label>
|
||||
}.into()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +1,75 @@
|
|||
.thaw-switch {
|
||||
align-items: flex-start;
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 22px;
|
||||
background-color: var(--thaw-background-color);
|
||||
border-radius: 11px;
|
||||
cursor: pointer;
|
||||
box-shadow: inset 0 0 1px 0 rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.4s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.thaw-switch__button {
|
||||
.thaw-switch__input {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 9px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3),
|
||||
inset 0 0 1px 0 rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.4s ease;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: calc(40px + 2 * var(--spacingHorizontalS));
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
opacity: 0;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.thaw-switch--active {
|
||||
background-color: var(--thaw-background-color-active);
|
||||
.thaw-switch__indicator {
|
||||
flex-shrink: 0;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
margin: var(--spacingVerticalS) var(--spacingHorizontalS);
|
||||
font-size: 18px;
|
||||
line-height: 0;
|
||||
border-radius: var(--borderRadiusCircular);
|
||||
border: 1px solid;
|
||||
box-sizing: border-box;
|
||||
fill: currentcolor;
|
||||
pointer-events: none;
|
||||
transition-duration: var(--durationNormal);
|
||||
transition-timing-function: var(--curveEasyEase);
|
||||
transition-property: background, border, color;
|
||||
}
|
||||
|
||||
.thaw-switch--active .thaw-switch__button {
|
||||
left: 20px;
|
||||
.thaw-switch__input:enabled:not(:checked) ~ .thaw-switch__indicator {
|
||||
color: var(--colorNeutralStrokeAccessible);
|
||||
border-color: var(--colorNeutralStrokeAccessible);
|
||||
}
|
||||
|
||||
.thaw-switch--active:active .thaw-switch__button {
|
||||
left: 14px;
|
||||
.thaw-switch__input:enabled:checked ~ .thaw-switch__indicator {
|
||||
background-color: var(--colorCompoundBrandBackground);
|
||||
color: var(--colorNeutralForegroundInverted);
|
||||
border-color: var(--colorTransparentStroke);
|
||||
}
|
||||
|
||||
.thaw-switch:active .thaw-switch__button {
|
||||
width: 24px;
|
||||
.thaw-switch__indicator > svg {
|
||||
display: inline;
|
||||
line-height: 0;
|
||||
|
||||
transition-duration: var(--durationNormal);
|
||||
transition-timing-function: var(--curveEasyEase);
|
||||
transition-property: transform;
|
||||
}
|
||||
|
||||
.thaw-switch__input:checked ~ .thaw-switch__indicator > svg {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.thaw-switch__label {
|
||||
margin-top: calc((20px - var(--lineHeightBase300)) / 2);
|
||||
margin-bottom: calc((20px - var(--lineHeightBase300)) / 2);
|
||||
padding: var(--spacingVerticalS) var(--spacingHorizontalS);
|
||||
padding-left: var(--spacingHorizontalXS);
|
||||
line-height: var(--lineHeightBase300);
|
||||
font-size: var(--fontSizeBase300);
|
||||
font-family: var(--fontFamilyBase);
|
||||
color: var(--colorNeutralForeground1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.thaw-switch__input:enabled:not(:checked) ~ .thaw-switch__label {
|
||||
color: var(--colorNeutralForeground1);
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
use crate::theme::ThemeMethod;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SwitchTheme {
|
||||
pub background_color: String,
|
||||
}
|
||||
|
||||
impl ThemeMethod for SwitchTheme {
|
||||
fn light() -> Self {
|
||||
Self {
|
||||
background_color: "#00000024".into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn dark() -> Self {
|
||||
Self {
|
||||
background_color: "#ffffff33".into(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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, SpinnerTheme, SwitchTheme,
|
||||
TableTheme, TagTheme, TimePickerTheme, UploadTheme,
|
||||
ProgressTheme, ScrollbarTheme, SelectTheme, SkeletionTheme, SpinnerTheme, 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 switch: SwitchTheme,
|
||||
pub spinner: SpinnerTheme,
|
||||
pub upload: UploadTheme,
|
||||
pub nav_bar: NavBarTheme,
|
||||
|
@ -62,7 +61,6 @@ impl Theme {
|
|||
tag: TagTheme::light(),
|
||||
message: MessageTheme::light(),
|
||||
select: SelectTheme::light(),
|
||||
switch: SwitchTheme::light(),
|
||||
spinner: SpinnerTheme::light(),
|
||||
upload: UploadTheme::light(),
|
||||
nav_bar: NavBarTheme::light(),
|
||||
|
@ -93,7 +91,6 @@ impl Theme {
|
|||
tag: TagTheme::dark(),
|
||||
message: MessageTheme::dark(),
|
||||
select: SelectTheme::dark(),
|
||||
switch: SwitchTheme::dark(),
|
||||
spinner: SpinnerTheme::dark(),
|
||||
upload: UploadTheme::dark(),
|
||||
nav_bar: NavBarTheme::dark(),
|
||||
|
|
Loading…
Add table
Reference in a new issue