mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-23 06:19:22 -05:00
✨ feat: add menu component
This commit is contained in:
parent
571191fb4f
commit
a9e82e994e
7 changed files with 118 additions and 1 deletions
|
@ -10,6 +10,9 @@ pub fn App(cx: Scope) -> impl IntoView {
|
||||||
<Route path="/" view=move |cx| view! {cx,
|
<Route path="/" view=move |cx| view! {cx,
|
||||||
<Home />
|
<Home />
|
||||||
} />
|
} />
|
||||||
|
<Route path="/menu" view=move |cx| view! {cx,
|
||||||
|
<MenuPage />
|
||||||
|
} />
|
||||||
<Route path="/slider" view=move |cx| view! {cx,
|
<Route path="/slider" view=move |cx| view! {cx,
|
||||||
<SliderPage />
|
<SliderPage />
|
||||||
} />
|
} />
|
||||||
|
|
13
examples/basic/src/pages/menu/mod.rs
Normal file
13
examples/basic/src/pages/menu/mod.rs
Normal 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>
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
mod home;
|
mod home;
|
||||||
|
mod menu;
|
||||||
mod slider;
|
mod slider;
|
||||||
|
|
||||||
pub use home::*;
|
pub use home::*;
|
||||||
|
pub use menu::*;
|
||||||
pub use slider::*;
|
pub use slider::*;
|
|
@ -3,6 +3,7 @@ mod card;
|
||||||
mod checkbox;
|
mod checkbox;
|
||||||
mod components;
|
mod components;
|
||||||
mod input;
|
mod input;
|
||||||
|
mod menu;
|
||||||
mod modal;
|
mod modal;
|
||||||
mod progress;
|
mod progress;
|
||||||
mod slider;
|
mod slider;
|
||||||
|
@ -16,6 +17,7 @@ mod wave;
|
||||||
pub use button::*;
|
pub use button::*;
|
||||||
pub use checkbox::*;
|
pub use checkbox::*;
|
||||||
pub use input::*;
|
pub use input::*;
|
||||||
|
pub use menu::*;
|
||||||
pub use modal::*;
|
pub use modal::*;
|
||||||
pub use progress::*;
|
pub use progress::*;
|
||||||
pub use slider::*;
|
pub use slider::*;
|
||||||
|
|
16
src/menu/menu-item.css
Normal file
16
src/menu/menu-item.css
Normal 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
36
src/menu/menu_item.rs
Normal 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
45
src/menu/mod.rs
Normal 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")
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue