orbital_base_components/overlay/menu/
item.rs1use leptos::prelude::*;
2
3use crate::overlay::OverlayDismiss;
4use crate::Handler;
5
6#[derive(Clone)]
7pub struct MenuInjection<V> {
8 pub has_icon: RwSignal<bool>,
9 pub on_select: Handler<V>,
10}
11
12impl<V: Clone + Send + Sync + 'static> MenuInjection<V> {
13 pub fn expect_context() -> Self {
14 expect_context::<Self>()
15 }
16}
17
18#[component]
19pub fn BaseMenuItem<V>(
20 #[prop(optional, into)] class: MaybeProp<String>,
21 #[prop(optional, into)] icon: MaybeProp<icondata_core::Icon>,
22 value: V,
23 #[prop(optional, into)] disabled: Signal<bool>,
24 children: Children,
25) -> impl IntoView
26where
27 V: Clone + Send + Sync + 'static,
28{
29 let MenuInjection {
30 has_icon,
31 on_select,
32 } = MenuInjection::expect_context();
33
34 if icon.with_untracked(|i| i.is_some()) {
35 has_icon.set(true);
36 }
37
38 let on_click = move |_| {
39 if disabled.get_untracked() {
40 return;
41 }
42 on_select.run(value.clone());
43 if let Some(dismiss) = use_context::<OverlayDismiss>() {
44 dismiss.close.run(());
45 }
46 };
47
48 view! {
49 <div
50 class=move || {
51 let mut parts = vec!["orbital-menu-item".to_string()];
52 if disabled.get() {
53 parts.push("orbital-menu-item--disabled".to_string());
54 }
55 if let Some(extra) = class.get() {
56 if !extra.is_empty() {
57 parts.push(extra);
58 }
59 }
60 parts.join(" ")
61 }
62 role="menuitem"
63 tabindex="-1"
64 aria-disabled=move || disabled.get().then_some("true")
65 on:click=on_click
66 >
67 {move || icon.get().map(|_| view! { <span class="orbital-menu-item__icon" aria-hidden="true"></span> })}
68 <span class="orbital-menu-item__label">{children()}</span>
69 </div>
70 }
71}