dioxus_ui_system/molecules/
tooltip.rs1use crate::styles::Style;
6use crate::theme::{use_style, use_theme};
7use dioxus::prelude::*;
8
9#[derive(Props, Clone, PartialEq)]
11pub struct TooltipProps {
12 pub children: Element,
14 pub content: String,
16 #[props(default)]
18 pub placement: TooltipPlacement,
19 #[props(default = 200)]
21 pub delay: u64,
22 #[props(default)]
24 pub style: Option<String>,
25}
26
27#[derive(Default, Clone, PartialEq)]
29pub enum TooltipPlacement {
30 #[default]
32 Top,
33 TopStart,
35 TopEnd,
37 Right,
39 RightStart,
41 RightEnd,
43 Bottom,
45 BottomStart,
47 BottomEnd,
49 Left,
51 LeftStart,
53 LeftEnd,
55}
56
57#[component]
59pub fn Tooltip(props: TooltipProps) -> Element {
60 let _theme = use_theme();
61 let mut is_visible = use_signal(|| false);
62 let show_timeout = use_signal(|| None::<i32>);
63
64 let position_style = match props.placement {
65 TooltipPlacement::Top => {
66 "bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);"
67 }
68 TooltipPlacement::TopStart => "bottom: calc(100% + 6px); left: 0;",
69 TooltipPlacement::TopEnd => "bottom: calc(100% + 6px); right: 0;",
70 TooltipPlacement::Right => "left: calc(100% + 6px); top: 50%; transform: translateY(-50%);",
71 TooltipPlacement::RightStart => "left: calc(100% + 6px); top: 0;",
72 TooltipPlacement::RightEnd => "left: calc(100% + 6px); bottom: 0;",
73 TooltipPlacement::Bottom => {
74 "top: calc(100% + 6px); left: 50%; transform: translateX(-50%);"
75 }
76 TooltipPlacement::BottomStart => "top: calc(100% + 6px); left: 0;",
77 TooltipPlacement::BottomEnd => "top: calc(100% + 6px); right: 0;",
78 TooltipPlacement::Left => "right: calc(100% + 6px); top: 50%; transform: translateY(-50%);",
79 TooltipPlacement::LeftStart => "right: calc(100% + 6px); top: 0;",
80 TooltipPlacement::LeftEnd => "right: calc(100% + 6px); bottom: 0;",
81 };
82
83 let tooltip_style = use_style(|t| {
84 Style::new()
85 .absolute()
86 .px(&t.spacing, "sm")
87 .py(&t.spacing, "xs")
88 .rounded(&t.radius, "md")
89 .bg(&t.colors.foreground)
90 .text_color(&t.colors.background)
91 .font_size(12)
92 .font_weight(500)
93 .whitespace_nowrap()
94 .z_index(100)
95 .build()
96 });
97
98 let mut show_tooltip = move || {
99 is_visible.set(true);
103 };
104
105 let mut hide_tooltip = move || {
106 if let Some(timeout) = show_timeout() {
107 let _ = timeout;
109 }
110 is_visible.set(false);
111 };
112
113 rsx! {
114 span {
115 style: "position: relative; display: inline-block;",
116 onmouseenter: move |_| show_tooltip(),
117 onmouseleave: move |_| hide_tooltip(),
118 onfocus: move |_| show_tooltip(),
119 onblur: move |_| hide_tooltip(),
120
121 {props.children}
122
123 if is_visible() {
124 div {
125 role: "tooltip",
126 style: "{tooltip_style} {position_style} {props.style.clone().unwrap_or_default()}",
127 "{props.content}"
128 }
129 }
130 }
131 }
132}
133
134#[derive(Props, Clone, PartialEq)]
136pub struct SimpleTooltipProps {
137 pub children: Element,
139 pub text: String,
141 #[props(default)]
143 pub placement: TooltipPlacement,
144}
145
146#[component]
148pub fn SimpleTooltip(props: SimpleTooltipProps) -> Element {
149 rsx! {
150 Tooltip {
151 content: props.text,
152 placement: props.placement,
153 {props.children}
154 }
155 }
156}