dioxus_bootstrap_css/
tooltip.rs1use dioxus::prelude::*;
2
3#[derive(Clone, Copy, Debug, Default, PartialEq)]
5pub enum TooltipPlacement {
6 #[default]
7 Top,
8 Bottom,
9 Start,
10 End,
11}
12
13#[derive(Clone, PartialEq, Props)]
45pub struct TooltipProps {
46 pub text: String,
48 #[props(default)]
50 pub placement: TooltipPlacement,
51 #[props(default)]
53 pub class: String,
54 pub children: Element,
56}
57
58#[component]
59pub fn Tooltip(props: TooltipProps) -> Element {
60 let hovering = use_signal(|| false);
61 let is_hovering = *hovering.read();
62 let mut hover_signal = hovering;
63
64 let placement_class = match props.placement {
65 TooltipPlacement::Top => "bs-tooltip-top",
66 TooltipPlacement::Bottom => "bs-tooltip-bottom",
67 TooltipPlacement::Start => "bs-tooltip-start",
68 TooltipPlacement::End => "bs-tooltip-end",
69 };
70
71 let tooltip_class = if props.class.is_empty() {
72 format!("tooltip fade {placement_class} show")
73 } else {
74 format!("tooltip fade {placement_class} show {}", props.class)
75 };
76
77 let position_style = match props.placement {
79 TooltipPlacement::Top => {
80 "position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 0.4rem;"
81 }
82 TooltipPlacement::Bottom => {
83 "position: absolute; top: 100%; left: 50%; transform: translateX(-50%); margin-top: 0.4rem;"
84 }
85 TooltipPlacement::Start => {
86 "position: absolute; right: 100%; top: 50%; transform: translateY(-50%); margin-right: 0.4rem;"
87 }
88 TooltipPlacement::End => {
89 "position: absolute; left: 100%; top: 50%; transform: translateY(-50%); margin-left: 0.4rem;"
90 }
91 };
92
93 let arrow_placement = match props.placement {
94 TooltipPlacement::Top => "bottom: -6px; left: 50%; transform: translateX(-50%);",
95 TooltipPlacement::Bottom => "top: -6px; left: 50%; transform: translateX(-50%);",
96 TooltipPlacement::Start => "right: -6px; top: 50%; transform: translateY(-50%);",
97 TooltipPlacement::End => "left: -6px; top: 50%; transform: translateY(-50%);",
98 };
99
100 rsx! {
101 div {
102 style: "position: relative; display: inline-block;",
103 onmouseenter: move |_| hover_signal.set(true),
104 onmouseleave: move |_| hover_signal.set(false),
105 {props.children}
106 if is_hovering {
107 div {
108 class: "{tooltip_class}",
109 role: "tooltip",
110 style: "{position_style} z-index: 1080; pointer-events: none; white-space: nowrap;",
111 div { class: "tooltip-arrow", style: "position: absolute; {arrow_placement}" }
112 div { class: "tooltip-inner", "{props.text}" }
113 }
114 }
115 }
116 }
117}