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)]
41pub struct TooltipProps {
42 pub text: String,
44 #[props(default)]
46 pub placement: TooltipPlacement,
47 #[props(default)]
49 pub class: String,
50 pub children: Element,
52}
53
54#[component]
55pub fn Tooltip(props: TooltipProps) -> Element {
56 let hovering = use_signal(|| false);
57 let is_hovering = *hovering.read();
58 let mut hover_signal = hovering;
59
60 let placement_class = match props.placement {
61 TooltipPlacement::Top => "bs-tooltip-top",
62 TooltipPlacement::Bottom => "bs-tooltip-bottom",
63 TooltipPlacement::Start => "bs-tooltip-start",
64 TooltipPlacement::End => "bs-tooltip-end",
65 };
66
67 let tooltip_class = if props.class.is_empty() {
68 format!("tooltip fade {placement_class} show")
69 } else {
70 format!("tooltip fade {placement_class} show {}", props.class)
71 };
72
73 let position_style = match props.placement {
75 TooltipPlacement::Top => {
76 "position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 0.4rem;"
77 }
78 TooltipPlacement::Bottom => {
79 "position: absolute; top: 100%; left: 50%; transform: translateX(-50%); margin-top: 0.4rem;"
80 }
81 TooltipPlacement::Start => {
82 "position: absolute; right: 100%; top: 50%; transform: translateY(-50%); margin-right: 0.4rem;"
83 }
84 TooltipPlacement::End => {
85 "position: absolute; left: 100%; top: 50%; transform: translateY(-50%); margin-left: 0.4rem;"
86 }
87 };
88
89 let arrow_placement = match props.placement {
90 TooltipPlacement::Top => "bottom: -6px; left: 50%; transform: translateX(-50%);",
91 TooltipPlacement::Bottom => "top: -6px; left: 50%; transform: translateX(-50%);",
92 TooltipPlacement::Start => "right: -6px; top: 50%; transform: translateY(-50%);",
93 TooltipPlacement::End => "left: -6px; top: 50%; transform: translateY(-50%);",
94 };
95
96 rsx! {
97 div {
98 style: "position: relative; display: inline-block;",
99 onmouseenter: move |_| hover_signal.set(true),
100 onmouseleave: move |_| hover_signal.set(false),
101 {props.children}
102 if is_hovering {
103 div {
104 class: "{tooltip_class}",
105 role: "tooltip",
106 style: "{position_style} z-index: 1080; pointer-events: none; white-space: nowrap;",
107 div { class: "tooltip-arrow", style: "position: absolute; {arrow_placement}" }
108 div { class: "tooltip-inner", "{props.text}" }
109 }
110 }
111 }
112 }
113}