1use ironhtml::typed::Element;
8use ironhtml_elements::{Button, A};
9
10extern crate alloc;
11use alloc::format;
12
13#[derive(Clone, Copy, Default)]
15pub enum Placement {
16 #[default]
17 Top,
18 Right,
19 Bottom,
20 Left,
21}
22
23impl Placement {
24 const fn as_str(self) -> &'static str {
25 match self {
26 Self::Top => "top",
27 Self::Right => "right",
28 Self::Bottom => "bottom",
29 Self::Left => "left",
30 }
31 }
32}
33
34#[must_use]
46pub fn tooltip_button(
47 color: crate::Color,
48 text: &str,
49 tooltip: &str,
50 placement: Placement,
51) -> Element<Button> {
52 let class = format!("btn btn-{}", color.as_str());
53 Element::<Button>::new()
54 .attr("type", "button")
55 .class(&class)
56 .attr("data-bs-toggle", "tooltip")
57 .attr("data-bs-placement", placement.as_str())
58 .attr("data-bs-title", tooltip)
59 .text(text)
60}
61
62#[must_use]
64pub fn tooltip_link(href: &str, text: &str, tooltip: &str, placement: Placement) -> Element<A> {
65 Element::<A>::new()
66 .attr("href", href)
67 .attr("data-bs-toggle", "tooltip")
68 .attr("data-bs-placement", placement.as_str())
69 .attr("data-bs-title", tooltip)
70 .text(text)
71}
72
73#[must_use]
75pub fn tooltip_html_button(
76 color: crate::Color,
77 text: &str,
78 tooltip_html: &str,
79 placement: Placement,
80) -> Element<Button> {
81 let class = format!("btn btn-{}", color.as_str());
82 Element::<Button>::new()
83 .attr("type", "button")
84 .class(&class)
85 .attr("data-bs-toggle", "tooltip")
86 .attr("data-bs-placement", placement.as_str())
87 .attr("data-bs-html", "true")
88 .attr("data-bs-title", tooltip_html)
89 .text(text)
90}
91
92#[must_use]
110pub fn popover_button(
111 color: crate::Color,
112 text: &str,
113 title: &str,
114 content: &str,
115 placement: Placement,
116) -> Element<Button> {
117 let class = format!("btn btn-{}", color.as_str());
118 Element::<Button>::new()
119 .attr("type", "button")
120 .class(&class)
121 .attr("data-bs-toggle", "popover")
122 .attr("data-bs-placement", placement.as_str())
123 .attr("data-bs-title", title)
124 .attr("data-bs-content", content)
125 .text(text)
126}
127
128#[must_use]
130pub fn popover_dismissible(
131 color: crate::Color,
132 text: &str,
133 title: &str,
134 content: &str,
135) -> Element<A> {
136 let class = format!("btn btn-{}", color.as_str());
137 Element::<A>::new()
138 .attr("tabindex", "0")
139 .class(&class)
140 .attr("role", "button")
141 .attr("data-bs-toggle", "popover")
142 .attr("data-bs-trigger", "focus")
143 .attr("data-bs-title", title)
144 .attr("data-bs-content", content)
145 .text(text)
146}
147
148#[must_use]
150pub fn popover_html(
151 color: crate::Color,
152 text: &str,
153 title: &str,
154 content_html: &str,
155 placement: Placement,
156) -> Element<Button> {
157 let class = format!("btn btn-{}", color.as_str());
158 Element::<Button>::new()
159 .attr("type", "button")
160 .class(&class)
161 .attr("data-bs-toggle", "popover")
162 .attr("data-bs-placement", placement.as_str())
163 .attr("data-bs-html", "true")
164 .attr("data-bs-title", title)
165 .attr("data-bs-content", content_html)
166 .text(text)
167}
168
169#[must_use]
171pub fn popover_hover(href: &str, text: &str, title: &str, content: &str) -> Element<A> {
172 Element::<A>::new()
173 .attr("href", href)
174 .attr("data-bs-toggle", "popover")
175 .attr("data-bs-trigger", "hover focus")
176 .attr("data-bs-title", title)
177 .attr("data-bs-content", content)
178 .text(text)
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184
185 #[test]
186 fn test_tooltip_button() {
187 let btn = tooltip_button(
188 crate::Color::Primary,
189 "Hover",
190 "Tooltip text",
191 Placement::Top,
192 );
193 let html = btn.render();
194 assert!(html.contains(r#"data-bs-toggle="tooltip"#));
195 assert!(html.contains(r#"data-bs-placement="top"#));
196 assert!(html.contains("data-bs-title"));
197 }
198
199 #[test]
200 fn test_popover_button() {
201 let btn = popover_button(
202 crate::Color::Secondary,
203 "Click",
204 "Title",
205 "Content",
206 Placement::Right,
207 );
208 let html = btn.render();
209 assert!(html.contains(r#"data-bs-toggle="popover"#));
210 assert!(html.contains(r#"data-bs-placement="right"#));
211 assert!(html.contains("data-bs-title"));
212 assert!(html.contains("data-bs-content"));
213 }
214
215 #[test]
216 fn test_tooltip_placements() {
217 for placement in [
218 Placement::Top,
219 Placement::Right,
220 Placement::Bottom,
221 Placement::Left,
222 ] {
223 let btn = tooltip_button(crate::Color::Info, "Test", "Tip", placement);
224 assert!(btn
225 .render()
226 .contains(&format!(r#"data-bs-placement="{}""#, placement.as_str())));
227 }
228 }
229}