Skip to main content

orbital_base_components/overlay/menu/
item.rs

1use 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}