maud_ui/primitives/
tooltip.rs1use maud::{html, Markup};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Placement {
8 Top,
9 Bottom,
10 Left,
11 Right,
12}
13
14impl Placement {
15 fn class(&self) -> &'static str {
16 match self {
17 Self::Top => "mui-tooltip__content--top",
18 Self::Bottom => "mui-tooltip__content--bottom",
19 Self::Left => "mui-tooltip__content--left",
20 Self::Right => "mui-tooltip__content--right",
21 }
22 }
23}
24
25#[derive(Debug, Clone)]
27pub struct Props {
28 pub content: String,
30 pub placement: Placement,
32 pub delay_ms: u32,
34 pub trigger: Markup,
36 pub id: String,
38}
39
40impl Default for Props {
41 fn default() -> Self {
42 Self {
43 content: String::new(),
44 placement: Placement::Top,
45 delay_ms: 500,
46 trigger: html! {},
47 id: "tooltip".to_string(),
48 }
49 }
50}
51
52pub fn render(props: Props) -> Markup {
54 let content_class = format!("mui-tooltip__content {}", props.placement.class());
55 let tip_id = format!("{}-tip", props.id);
56
57 html! {
58 span.mui-tooltip data-mui="tooltip" data-delay=(props.delay_ms.to_string()) {
59 span.mui-tooltip__trigger aria-describedby=(tip_id.clone()) {
60 (props.trigger)
61 }
62 span class=(content_class)
63 id=(tip_id)
64 role="tooltip"
65 hidden
66 data-visible="false"
67 {
68 (props.content)
69 }
70 }
71 }
72}
73
74pub fn showcase() -> Markup {
76 html! {
77 div.mui-showcase__grid {
78 div {
79 p.mui-showcase__caption { "Icon buttons with contextual tooltips — copy, roster, shortcut, destructive." }
80 div.mui-showcase__row {
81 (render(Props {
83 content: "Copy to clipboard".into(),
84 placement: Placement::Top,
85 delay_ms: 400,
86 trigger: html! {
87 button.mui-btn.mui-btn--ghost.mui-btn--icon type="button" aria-label="Copy" {
88 span aria-hidden="true" { "\u{2398}" }
89 }
90 },
91 id: "demo-tip-copy".into(),
92 }))
93 (render(Props {
95 content: "View full list (12 members)".into(),
96 placement: Placement::Bottom,
97 delay_ms: 400,
98 trigger: html! {
99 button.mui-btn.mui-btn--outline.mui-btn--sm type="button" aria-label="+3 more members — view all" {
100 "+3"
101 }
102 },
103 id: "demo-tip-avatars".into(),
104 }))
105 (render(Props {
107 content: "Keyboard shortcut: \u{2318}K".into(),
108 placement: Placement::Left,
109 delay_ms: 400,
110 trigger: html! {
111 button.mui-btn.mui-btn--outline.mui-btn--md type="button" aria-label="Open search" {
112 span aria-hidden="true" { "\u{1f50d}" }
113 " Search"
114 }
115 },
116 id: "demo-tip-search".into(),
117 }))
118 (render(Props {
120 content: "Delete permanently".into(),
121 placement: Placement::Right,
122 delay_ms: 400,
123 trigger: html! {
124 button.mui-btn.mui-btn--danger.mui-btn--icon type="button" aria-label="Delete" {
125 span aria-hidden="true" { "\u{1f5d1}" }
126 }
127 },
128 id: "demo-tip-delete".into(),
129 }))
130 }
131 }
132 }
133 }
134}