diff --git a/examples/basic/src/app.rs b/examples/basic/src/app.rs
index 147ae9a..0e5e748 100644
--- a/examples/basic/src/app.rs
+++ b/examples/basic/src/app.rs
@@ -10,6 +10,9 @@ pub fn App(cx: Scope) -> impl IntoView {
} />
+
+ } />
} />
diff --git a/examples/basic/src/pages/menu/mod.rs b/examples/basic/src/pages/menu/mod.rs
new file mode 100644
index 0000000..9a8a7e2
--- /dev/null
+++ b/examples/basic/src/pages/menu/mod.rs
@@ -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,
+
+ }
+}
diff --git a/examples/basic/src/pages/mod.rs b/examples/basic/src/pages/mod.rs
index dbabfb0..39db5b8 100644
--- a/examples/basic/src/pages/mod.rs
+++ b/examples/basic/src/pages/mod.rs
@@ -1,5 +1,7 @@
mod home;
+mod menu;
mod slider;
pub use home::*;
-pub use slider::*;
\ No newline at end of file
+pub use menu::*;
+pub use slider::*;
diff --git a/src/lib.rs b/src/lib.rs
index ec538d4..4bc7f4a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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::*;
diff --git a/src/menu/menu-item.css b/src/menu/menu-item.css
new file mode 100644
index 0000000..0df4feb
--- /dev/null
+++ b/src/menu/menu-item.css
@@ -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);
+}
diff --git a/src/menu/menu_item.rs b/src/menu/menu_item.rs
new file mode 100644
index 0000000..84735a2
--- /dev/null
+++ b/src/menu/menu_item.rs
@@ -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,
+) -> 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,
+
+ }
+}
diff --git a/src/menu/mod.rs b/src/menu/mod.rs
new file mode 100644
index 0000000..e0f77f6
--- /dev/null
+++ b/src/menu/mod.rs
@@ -0,0 +1,45 @@
+mod menu_item;
+
+use leptos::*;
+pub use menu_item::*;
+
+#[component]
+pub fn Menu(
+ cx: Scope,
+ #[prop(into)] selected: RwSignal,
+ children: Children,
+) -> impl IntoView {
+ let menu_injection_key = create_rw_signal(cx, MenuInjectionKey::new(selected));
+ provide_context(cx, menu_injection_key);
+ view! {cx,
+
+ }
+}
+
+#[derive(Clone)]
+pub struct MenuInjectionKey {
+ value: RwSignal,
+}
+
+
+impl MenuInjectionKey {
+ pub fn new(value: RwSignal) -> 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 {
+ use_context::>(cx).expect("MenuInjectionKey not exist")
+}