yew_bs/components/
tooltips.rs

1use yew::prelude::*;
2use web_sys::Element;
3use wasm_bindgen::JsValue;
4use crate::interop::BsTooltip;
5#[derive(Clone, Copy, PartialEq, Debug)]
6pub enum TooltipPlacement {
7    Auto,
8    Top,
9    Bottom,
10    Left,
11    Right,
12}
13impl TooltipPlacement {
14    pub fn as_str(&self) -> &'static str {
15        match self {
16            TooltipPlacement::Auto => "auto",
17            TooltipPlacement::Top => "top",
18            TooltipPlacement::Bottom => "bottom",
19            TooltipPlacement::Left => "left",
20            TooltipPlacement::Right => "right",
21        }
22    }
23}
24/// Tooltip trigger options
25#[derive(Clone, Copy, PartialEq, Debug)]
26pub enum TooltipTrigger {
27    Hover,
28    Focus,
29    Click,
30    Manual,
31}
32impl TooltipTrigger {
33    pub fn as_str(&self) -> &'static str {
34        match self {
35            TooltipTrigger::Hover => "hover",
36            TooltipTrigger::Focus => "focus",
37            TooltipTrigger::Click => "click",
38            TooltipTrigger::Manual => "manual",
39        }
40    }
41}
42#[derive(Properties, PartialEq)]
43pub struct TooltipProps {
44    #[prop_or_default]
45    pub children: Children,
46    pub title: AttrValue,
47    #[prop_or(TooltipPlacement::Top)]
48    pub placement: TooltipPlacement,
49    #[prop_or(TooltipTrigger::Hover)]
50    pub trigger: TooltipTrigger,
51    #[prop_or_default]
52    pub show: bool,
53    #[prop_or_default]
54    pub class: Option<AttrValue>,
55    #[prop_or_default]
56    pub node_ref: NodeRef,
57}
58#[function_component(Tooltip)]
59pub fn tooltip(props: &TooltipProps) -> Html {
60    let node_ref = props.node_ref.clone();
61    let options = {
62        let opts = js_sys::Object::new();
63        js_sys::Reflect::set(
64                &opts,
65                &"title".into(),
66                &JsValue::from(props.title.as_str()),
67            )
68            .unwrap();
69        js_sys::Reflect::set(
70                &opts,
71                &"placement".into(),
72                &JsValue::from(props.placement.as_str()),
73            )
74            .unwrap();
75        js_sys::Reflect::set(
76                &opts,
77                &"trigger".into(),
78                &JsValue::from(props.trigger.as_str()),
79            )
80            .unwrap();
81        JsValue::from(opts)
82    };
83    {
84        let node_ref = node_ref.clone();
85        let trigger = props.trigger;
86        use_effect_with(
87            (options.clone(), props.show),
88            move |(options, show)| {
89                if let Some(element) = node_ref.cast::<Element>() {
90                    let bs_tooltip = BsTooltip::new(&element, Some(&options));
91                    match trigger {
92                        TooltipTrigger::Manual => {
93                            if *show {
94                                bs_tooltip.show();
95                            } else {
96                                bs_tooltip.hide();
97                            }
98                        }
99                        _ => {}
100                    }
101                }
102                || ()
103            },
104        );
105    }
106    let children = props.children.clone();
107    html! {
108        < span ref = { props.node_ref.clone() } data - bs - toggle = "tooltip" data - bs
109        - title = { props.title.clone() } data - bs - placement = { props.placement
110        .as_str() } data - bs - trigger = { props.trigger.as_str() } class = { props
111        .class.clone() } > { for children.iter() } </ span >
112    }
113}