feat: add menu component

This commit is contained in:
luoxiao 2023-05-18 17:14:54 +08:00
parent 571191fb4f
commit a9e82e994e
7 changed files with 118 additions and 1 deletions

View file

@ -10,6 +10,9 @@ pub fn App(cx: Scope) -> impl IntoView {
<Route path="/" view=move |cx| view! {cx,
<Home />
} />
<Route path="/menu" view=move |cx| view! {cx,
<MenuPage />
} />
<Route path="/slider" view=move |cx| view! {cx,
<SliderPage />
} />

View file

@ -0,0 +1,13 @@
use leptos::*;
use melt_ui::*;
#[component]
pub fn MenuPage(cx: Scope) -> impl IntoView {
let selected = create_rw_signal(cx, String::from("o"));
view! { cx,
<Menu selected>
<MenuItem key="a" label="and"/>
<MenuItem key="o" label="or"/>
</Menu>
}
}

View file

@ -1,5 +1,7 @@
mod home;
mod menu;
mod slider;
pub use home::*;
pub use menu::*;
pub use slider::*;

View file

@ -3,6 +3,7 @@ mod card;
mod checkbox;
mod components;
mod input;
mod menu;
mod modal;
mod progress;
mod slider;
@ -16,6 +17,7 @@ mod wave;
pub use button::*;
pub use checkbox::*;
pub use input::*;
pub use menu::*;
pub use modal::*;
pub use progress::*;
pub use slider::*;

16
src/menu/menu-item.css Normal file
View file

@ -0,0 +1,16 @@
.melt-menu-item__content {
margin: 6px 8px;
padding: 12px 10px;
padding-left: 14px;
cursor: pointer;
border-radius: var(--border-radius);
}
.melt-menu-item__content:hover {
color: var(--font-color);
}
.melt-menu-item__content--selected {
color: var(--font-color);
background-color: var(--bg-color);
}

36
src/menu/menu_item.rs Normal file
View file

@ -0,0 +1,36 @@
use super::{use_menu, MenuInjectionKey};
use crate::{theme::use_theme, utils::mount_style::mount_style, Theme};
use leptos::*;
use stylers::style_sheet_str;
#[component]
pub fn MenuItem(
cx: Scope,
#[prop(into)] key: MaybeSignal<&'static str>,
#[prop(into)] label: MaybeSignal<String>,
) -> impl IntoView {
let class_name = mount_style("menu-item", || style_sheet_str!("./src/menu/menu-item.css"));
let theme = use_theme(cx, Theme::light);
let menu = use_menu(cx);
let onclick_select = move |_| {
menu.set(MenuInjectionKey::from_string(cx, key.get().to_string()));
};
let css_vars = create_memo(cx, move |_| {
let mut css_vars = String::new();
let theme = theme.get();
let font_color = theme.common.color_primary.clone();
css_vars.push_str(&format!("--font-color: {font_color};"));
css_vars.push_str(&format!("--bg-color: {font_color}1a;"));
let border_radius = theme.common.border_radius.clone();
css_vars.push_str(&format!("--border-radius: {border_radius};"));
css_vars
});
view! {cx, class=class_name,
<div class="melt-menu-item">
<div class="melt-menu-item__content" class=("melt-menu-item__content--selected", move || menu.get().value() == key.get()) on:click=onclick_select style=move || css_vars.get()>
{ move || label.get() }
</div>
</div>
}
}

45
src/menu/mod.rs Normal file
View file

@ -0,0 +1,45 @@
mod menu_item;
use leptos::*;
pub use menu_item::*;
#[component]
pub fn Menu(
cx: Scope,
#[prop(into)] selected: RwSignal<String>,
children: Children,
) -> impl IntoView {
let menu_injection_key = create_rw_signal(cx, MenuInjectionKey::new(selected));
provide_context(cx, menu_injection_key);
view! {cx,
<div class="melt-menu">
{ children(cx) }
</div>
}
}
#[derive(Clone)]
pub struct MenuInjectionKey {
value: RwSignal<String>,
}
impl MenuInjectionKey {
pub fn new(value: RwSignal<String>) -> Self {
Self { value }
}
pub fn from_string(cx: Scope, value: String) -> Self {
Self {
value: create_rw_signal(cx, value),
}
}
pub fn value(&self) -> String {
self.value.get()
}
}
pub fn use_menu(cx: Scope) -> RwSignal<MenuInjectionKey> {
use_context::<RwSignal<MenuInjectionKey>>(cx).expect("MenuInjectionKey not exist")
}