feature: spinner (#48)

* feature: spinner

* feat: modify the spinner style

---------

Co-authored-by: Cristobal Andrada <kandrelczyk@gmail.com>
Co-authored-by: luoxiao <luoxiaozero@163.com>
This commit is contained in:
kandrelczyk 2023-12-15 09:12:12 +00:00 committed by GitHub
parent 08936c92ff
commit d94c8ed4c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 201 additions and 1 deletions

View file

@ -53,6 +53,7 @@ fn TheRouter(is_routing: RwSignal<bool>) -> impl IntoView {
<Route path="/tabs" view=TabsPage/>
<Route path="/select" view=SelectPage/>
<Route path="/space" view=SpacePage/>
<Route path="/spinner" view=SpinnerPage/>
<Route path="/table" view=TablePage/>
<Route path="/color-picker" view=ColorPickerPage/>
<Route path="/alert" view=AlertPage/>

View file

@ -221,6 +221,10 @@ pub(crate) fn gen_menu_data() -> Vec<MenuGroupOption> {
value: "progress".into(),
label: "Progress".into(),
},
MenuItemOption {
value: "spinner".into(),
label: "Spinner".into(),
},
MenuItemOption {
value: "skeleton".into(),
label: "Skeleton".into(),

View file

@ -30,6 +30,7 @@ mod select;
mod skeleton;
mod slider;
mod space;
mod spinner;
mod switch;
mod tabbar;
mod table;
@ -73,6 +74,7 @@ pub use select::*;
pub use skeleton::*;
pub use slider::*;
pub use space::*;
pub use spinner::*;
pub use switch::*;
pub use tabbar::*;
pub use table::*;

View file

@ -0,0 +1,83 @@
use crate::components::{Demo, DemoCode};
use leptos::*;
use prisms::highlight_str;
use thaw::*;
#[component]
pub fn SpinnerPage() -> impl IntoView {
view! {
<div style="width: 896px; margin: 0 auto;">
<h1>"Spinner"</h1>
<Demo>
<Space>
<Spinner/>
</Space>
<DemoCode slot>
{highlight_str!(
r#"
<Spinner/>
"#,
"rust"
)}
</DemoCode>
</Demo>
<h3>"size"</h3>
<Demo>
<Space>
<Spinner size=SpinnerSize::Tiny/>
<Spinner size=SpinnerSize::Small/>
<Spinner size=SpinnerSize::Medium/>
<Spinner size=SpinnerSize::Large/>
</Space>
<DemoCode slot>
{highlight_str!(
r#"
<Spinner size=SpinnerSize::Tiny/>
<Spinner size=SpinnerSize::Small/>
<Spinner size=SpinnerSize::Medium/>
<Spinner size=SpinnerSize::Large/>
"#,
"rust"
)}
</DemoCode>
</Demo>
<h3>"Spinner Props"</h3>
<Table single_column=true>
<thead>
<tr>
<th>"Name"</th>
<th>"Type"</th>
<th>"Default"</th>
<th>"Description"</th>
</tr>
</thead>
<tbody>
<tr>
<td>"class"</td>
<td>
<Text code=true>"MaybeSignal<String>"</Text>
</td>
<td>
<Text code=true>"Default::default()"</Text>
</td>
<td>"Additional classes for the spinner element."</td>
</tr>
<tr>
<td>"size"</td>
<td>
<Text code=true>"MaybeSignal<SpinnerSize>"</Text>
</td>
<td>
<Text code=true>"SpinnerSize::Medium"</Text>
</td>
<td>"Spinner size."</td>
</tr>
</tbody>
</Table>
</div>
}
}

View file

@ -29,6 +29,7 @@ mod select;
mod skeleton;
mod slider;
mod space;
mod spinner;
mod switch;
mod table;
mod tabs;
@ -69,6 +70,7 @@ pub use select::*;
pub use skeleton::*;
pub use slider::*;
pub use space::*;
pub use spinner::*;
pub use switch::*;
pub use table::*;
pub use tabs::*;

66
src/spinner/mod.rs Normal file
View file

@ -0,0 +1,66 @@
mod theme;
#[cfg(not(feature = "ssr"))]
use crate::utils::dyn_classes;
use crate::{
theme::use_theme,
utils::{mount_style, ssr_class},
Theme,
};
use leptos::*;
pub use theme::SpinnerTheme;
#[derive(Default, Clone)]
pub enum SpinnerSize {
Tiny,
Small,
#[default]
Medium,
Large,
}
impl SpinnerSize {
fn theme_height(&self, theme: &Theme) -> String {
match self {
SpinnerSize::Tiny => theme.common.height_tiny.clone(),
SpinnerSize::Small => theme.common.height_small.clone(),
SpinnerSize::Medium => theme.common.height_medium.clone(),
SpinnerSize::Large => theme.common.height_large.clone(),
}
}
}
#[component]
pub fn Spinner(
#[prop(optional, into)] class: MaybeSignal<String>,
#[prop(optional, into)] size: MaybeSignal<SpinnerSize>,
) -> impl IntoView {
mount_style("spinner", include_str!("./spinner.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-height: {};",
size.get().theme_height(theme)
));
css_vars.push_str(&format!(
"--thaw-background-color: {};",
&theme.spinner.background_color
));
css_vars.push_str(&format!("--thaw-color: {};", &theme.common.color_primary));
});
css_vars
});
let ssr_class = ssr_class(&class);
view! {
<div
class=ssr_class
use:dyn_classes=class
class="thaw-spinner"
style=move || css_vars.get()
></div>
}
}

17
src/spinner/spinner.css Normal file
View file

@ -0,0 +1,17 @@
.thaw-spinner {
border-color: var(--thaw-color);
border-left-color: var(--thaw-background-color);
border-style: solid;
border-radius: 100px;
border-width: 2px;
width: var(--thaw-height);
height: var(--thaw-height);
outline: 1px solid transparent;
animation: 1s linear 0s infinite normal none running spin;
box-sizing: border-box;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

20
src/spinner/theme.rs Normal file
View file

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

View file

@ -8,6 +8,8 @@
border-radius: 25px;
cursor: pointer;
box-shadow: inset 0 0 1px 0 rgba(0, 0, 0, 0.05);
transition: all 0.4s ease;
box-sizing: content-box;
}
.thaw-switch__button {

View file

@ -5,7 +5,7 @@ use crate::{
mobile::{NavBarTheme, TabbarTheme},
AlertTheme, AutoCompleteTheme, AvatarTheme, BreadcrumbTheme, ButtonTheme, CalendarTheme,
ColorPickerTheme, InputTheme, MenuTheme, MessageTheme, ProgressTheme, SelectTheme,
SkeletionTheme, SliderTheme, SwitchTheme, TableTheme, TagTheme, TimePickerTheme,
SkeletionTheme, SliderTheme, SpinnerTheme, SwitchTheme, TableTheme, TagTheme, TimePickerTheme,
TypographyTheme, UploadTheme,
};
use leptos::*;
@ -31,6 +31,7 @@ pub struct Theme {
pub select: SelectTheme,
pub slider: SliderTheme,
pub switch: SwitchTheme,
pub spinner: SpinnerTheme,
pub upload: UploadTheme,
pub nav_bar: NavBarTheme,
pub tabbar: TabbarTheme,
@ -60,6 +61,7 @@ impl Theme {
select: SelectTheme::light(),
slider: SliderTheme::light(),
switch: SwitchTheme::light(),
spinner: SpinnerTheme::light(),
upload: UploadTheme::light(),
nav_bar: NavBarTheme::light(),
tabbar: TabbarTheme::light(),
@ -88,6 +90,7 @@ impl Theme {
select: SelectTheme::dark(),
slider: SliderTheme::dark(),
switch: SwitchTheme::dark(),
spinner: SpinnerTheme::dark(),
upload: UploadTheme::dark(),
nav_bar: NavBarTheme::dark(),
tabbar: TabbarTheme::dark(),