Skip to main content

orbital_base_components/overlay/
panel_surface.rs

1use leptos::{ev, html, prelude::*};
2
3use super::arrow::arrow_style;
4use super::positioning::OverlayPlacementInjection;
5
6/// Node ref for the popover/tooltip angle element — wired to [`AnchorArrow::node_ref`].
7#[derive(Clone, Copy)]
8pub struct OverlayArrowInjection {
9    pub node_ref: NodeRef<html::Div>,
10}
11
12/// Panel ref and hover handlers for anchored overlay surfaces.
13#[derive(Clone, Copy)]
14pub struct OverlayPanelInjection {
15    pub panel_ref: NodeRef<html::Div>,
16    pub on_mouse_enter: Callback<ev::MouseEvent>,
17    pub on_mouse_leave: Callback<ev::MouseEvent>,
18}
19
20/// Root surface for teleported overlay content; receives binder `content_ref` via parent.
21#[component]
22pub fn OverlaySurface(
23    #[prop(into)] class: Signal<String>,
24    #[prop(optional, into)] role: MaybeProp<String>,
25    children: Children,
26) -> impl IntoView {
27    let panel = expect_context::<OverlayPanelInjection>();
28    let placement_ctx = use_context::<OverlayPlacementInjection>();
29    let arrow = use_context::<OverlayArrowInjection>().map(|inj| {
30        view! {
31            <div
32                class="orbital-popover-surface__angle"
33                style=arrow_style()
34                node_ref=inj.node_ref
35            ></div>
36        }
37        .into_any()
38    });
39
40    view! {
41        <div
42            class=class
43            role=role
44            node_ref=panel.panel_ref
45            on:mouseenter=move |e| panel.on_mouse_enter.run(e)
46            on:mouseleave=move |e| panel.on_mouse_leave.run(e)
47            prop:data-orbital-placement=move || {
48                placement_ctx
49                    .map(|ctx| ctx.placement_label.get())
50                    .unwrap_or_default()
51            }
52        >
53            {arrow}
54            {children()}
55        </div>
56    }
57}