mirror of
https://github.com/adoyle0/thaw.git
synced 2025-02-02 08:34:15 -05:00
feat: add badge component
This commit is contained in:
parent
826a30dc01
commit
087391f0f7
7 changed files with 175 additions and 0 deletions
|
@ -28,6 +28,7 @@ pub fn App() -> impl IntoView {
|
||||||
<Route path="/grid" view=GridPage/>
|
<Route path="/grid" view=GridPage/>
|
||||||
<Route path="/auto-complete" view=AutoCompletePage/>
|
<Route path="/auto-complete" view=AutoCompletePage/>
|
||||||
<Route path="/avatar" view=AvatarPage/>
|
<Route path="/avatar" view=AvatarPage/>
|
||||||
|
<Route path="/badge" view=BadgePage/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/mobile/tabbar" view=TabbarDemoPage/>
|
<Route path="/mobile/tabbar" view=TabbarDemoPage/>
|
||||||
<Route path="/mobile/nav-bar" view=NavBarDemoPage/>
|
<Route path="/mobile/nav-bar" view=NavBarDemoPage/>
|
||||||
|
|
73
demo/src/pages/badge/mod.rs
Normal file
73
demo/src/pages/badge/mod.rs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
use crate::components::{Demo, DemoCode};
|
||||||
|
use leptos::*;
|
||||||
|
use melt_ui::*;
|
||||||
|
use prisms::highlight_str;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn BadgePage() -> impl IntoView {
|
||||||
|
let value = create_rw_signal(0);
|
||||||
|
view! {
|
||||||
|
<div style="width: 896px; margin: 0 auto;">
|
||||||
|
<h1>"Badge"</h1>
|
||||||
|
<Demo>
|
||||||
|
<Space>
|
||||||
|
<Badge value=value max_value=10>
|
||||||
|
<Avatar/>
|
||||||
|
</Badge>
|
||||||
|
<Badge color=BadgeColor::Success value=value max_value=10>
|
||||||
|
<Avatar/>
|
||||||
|
</Badge>
|
||||||
|
<Badge color=BadgeColor::Warning value=value max_value=10>
|
||||||
|
<Avatar/>
|
||||||
|
</Badge>
|
||||||
|
<Badge color=BadgeColor::Warning dot=true>
|
||||||
|
<Avatar/>
|
||||||
|
</Badge>
|
||||||
|
<Button on_click=move |_| value.update(|v| *v += 1)>"+1"</Button>
|
||||||
|
<Button on_click=move |_| {
|
||||||
|
value
|
||||||
|
.update(|v| {
|
||||||
|
if *v != 0 {
|
||||||
|
*v -= 1;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}>"-1"</Button>
|
||||||
|
"value:"
|
||||||
|
{move || value.get()}
|
||||||
|
</Space>
|
||||||
|
<DemoCode
|
||||||
|
slot
|
||||||
|
html=highlight_str!(
|
||||||
|
r#"
|
||||||
|
let value = create_rw_signal(0);
|
||||||
|
view! {
|
||||||
|
<Space>
|
||||||
|
<Badge value=value max_value=10>
|
||||||
|
<Avatar />
|
||||||
|
</Badge>
|
||||||
|
<Badge color=BadgeColor::Success value=value max_value=10>
|
||||||
|
<Avatar />
|
||||||
|
</Badge>
|
||||||
|
<Badge color=BadgeColor::Warning value=value max_value=10>
|
||||||
|
<Avatar />
|
||||||
|
</Badge>
|
||||||
|
<Badge color=BadgeColor::Warning dot=true>
|
||||||
|
<Avatar />
|
||||||
|
</Badge>
|
||||||
|
<Button on_click=move |_| value.update(|v| *v += 1)>"+1"</Button>
|
||||||
|
<Button on_click=move |_| value.update(|v| if *v != 0 { *v -= 1 })>"-1"</Button>
|
||||||
|
"value:"
|
||||||
|
{move || value.get()}
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
"rust"
|
||||||
|
)
|
||||||
|
>
|
||||||
|
|
||||||
|
""
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
|
@ -152,6 +152,10 @@ fn gen_menu_data() -> Vec<MenuGroupOption> {
|
||||||
value: "alert".into(),
|
value: "alert".into(),
|
||||||
label: "Alert".into(),
|
label: "Alert".into(),
|
||||||
},
|
},
|
||||||
|
MenuItemOption {
|
||||||
|
value: "badge".into(),
|
||||||
|
label: "Badge".into(),
|
||||||
|
},
|
||||||
MenuItemOption {
|
MenuItemOption {
|
||||||
value: "modal".into(),
|
value: "modal".into(),
|
||||||
label: "Modal".into(),
|
label: "Modal".into(),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod alert;
|
mod alert;
|
||||||
mod auto_complete;
|
mod auto_complete;
|
||||||
mod avatar;
|
mod avatar;
|
||||||
|
mod badge;
|
||||||
mod button;
|
mod button;
|
||||||
mod checkbox;
|
mod checkbox;
|
||||||
mod color_picker;
|
mod color_picker;
|
||||||
|
@ -24,6 +25,7 @@ mod toast;
|
||||||
pub use alert::*;
|
pub use alert::*;
|
||||||
pub use auto_complete::*;
|
pub use auto_complete::*;
|
||||||
pub use avatar::*;
|
pub use avatar::*;
|
||||||
|
pub use badge::*;
|
||||||
pub use button::*;
|
pub use button::*;
|
||||||
pub use checkbox::*;
|
pub use checkbox::*;
|
||||||
pub use color_picker::*;
|
pub use color_picker::*;
|
||||||
|
|
27
src/badge/badge.css
Normal file
27
src/badge/badge.css
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
.melt-badge {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.melt-badge__sup {
|
||||||
|
position: absolute;
|
||||||
|
color: var(--font-color);
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
.melt-badge__sup--value {
|
||||||
|
top: -9px;
|
||||||
|
right: -9px;
|
||||||
|
font-size: 12px;
|
||||||
|
height: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
border-radius: 9px;
|
||||||
|
padding: 0 6px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.melt-badge__sup--dot {
|
||||||
|
top: -5px;
|
||||||
|
right: -5px;
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
66
src/badge/mod.rs
Normal file
66
src/badge/mod.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use crate::{mount_style, theme::use_theme, Theme};
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub enum BadgeColor {
|
||||||
|
Success,
|
||||||
|
Warning,
|
||||||
|
#[default]
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BadgeColor {
|
||||||
|
pub fn theme_color(&self, theme: &Theme) -> String {
|
||||||
|
match self {
|
||||||
|
BadgeColor::Success => theme.common.color_success.clone(),
|
||||||
|
BadgeColor::Warning => theme.common.color_warning.clone(),
|
||||||
|
BadgeColor::Error => theme.common.color_error.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Badge(
|
||||||
|
#[prop(optional, into)] value: MaybeSignal<u32>,
|
||||||
|
#[prop(default = MaybeSignal::Static(u32::MAX), into)] max_value: MaybeSignal<u32>,
|
||||||
|
#[prop(optional, into)] color: MaybeSignal<BadgeColor>,
|
||||||
|
#[prop(optional, into)] dot: MaybeSignal<bool>,
|
||||||
|
children: Children,
|
||||||
|
) -> impl IntoView {
|
||||||
|
let theme = use_theme(Theme::light);
|
||||||
|
mount_style("badge", include_str!("./badge.css"));
|
||||||
|
let css_vars = create_memo(move |_| {
|
||||||
|
let mut css_vars = String::new();
|
||||||
|
css_vars.push_str(&format!("--font-color: #fff;"));
|
||||||
|
theme.with(|theme| {
|
||||||
|
css_vars.push_str(&format!(
|
||||||
|
"--background-color: {};",
|
||||||
|
color.get().theme_color(theme)
|
||||||
|
));
|
||||||
|
});
|
||||||
|
css_vars
|
||||||
|
});
|
||||||
|
let value = create_memo(move |_| {
|
||||||
|
let value = value.get();
|
||||||
|
let max_value = max_value.get();
|
||||||
|
if value == 0 {
|
||||||
|
String::new()
|
||||||
|
} else if max_value < value {
|
||||||
|
format!("{max_value}+")
|
||||||
|
} else {
|
||||||
|
value.to_string()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
view! {
|
||||||
|
<div class="melt-badge" style=move || css_vars.get()>
|
||||||
|
<div
|
||||||
|
class="melt-badge__sup"
|
||||||
|
class=("melt-badge__sup--value", move || !dot.get() && !value.get().is_empty())
|
||||||
|
class=("melt-badge__sup--dot", move || dot.get())
|
||||||
|
>
|
||||||
|
{move || value.get()}
|
||||||
|
</div>
|
||||||
|
{children()}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
mod alert;
|
mod alert;
|
||||||
mod auto_complete;
|
mod auto_complete;
|
||||||
mod avatar;
|
mod avatar;
|
||||||
|
mod badge;
|
||||||
mod button;
|
mod button;
|
||||||
mod card;
|
mod card;
|
||||||
mod checkbox;
|
mod checkbox;
|
||||||
|
@ -29,6 +30,7 @@ mod wave;
|
||||||
pub use alert::*;
|
pub use alert::*;
|
||||||
pub use auto_complete::*;
|
pub use auto_complete::*;
|
||||||
pub use avatar::*;
|
pub use avatar::*;
|
||||||
|
pub use badge::*;
|
||||||
pub use button::*;
|
pub use button::*;
|
||||||
pub use card::*;
|
pub use card::*;
|
||||||
pub use checkbox::*;
|
pub use checkbox::*;
|
||||||
|
|
Loading…
Add table
Reference in a new issue