dioxus_tw_components/components/
hovercard.rs1use crate::dioxus_core::IntoAttributeValue;
2use dioxus::prelude::*;
3use dioxus_core::AttributeValue;
4
5#[derive(Clone, Debug)]
6pub struct HoverState {
7 is_active: bool,
8}
9
10impl HoverState {
11 fn new() -> Self {
12 Self { is_active: false }
13 }
14
15 fn toggle(&mut self) {
16 self.is_active = !self.is_active;
17 }
18
19 fn open(&mut self) {
20 self.is_active = true;
21 }
22
23 fn close(&mut self) {
24 self.is_active = false;
25 }
26}
27
28impl IntoAttributeValue for HoverState {
29 fn into_value(self) -> AttributeValue {
30 match self.is_active {
31 true => AttributeValue::Text("active".to_string()),
32 false => AttributeValue::Text("inactive".to_string()),
33 }
34 }
35}
36
37#[derive(Clone, PartialEq, Props)]
38pub struct HoverCardProps {
39 #[props(extends = div, extends = GlobalAttributes)]
40 attributes: Vec<Attribute>,
41
42 children: Element,
43}
44
45#[component]
46pub fn HoverCard(mut props: HoverCardProps) -> Element {
47 let mut state = use_context_provider(|| Signal::new(HoverState::new()));
48
49 let default_classes = "hovercard";
50 crate::setup_class_attribute(&mut props.attributes, default_classes);
51
52 rsx! {
53 div {
54 "data-state": state.into_value(),
55 onmouseenter: move |_| state.write().open(),
56 onmouseleave: move |_| state.write().close(),
57 ..props.attributes,
58 {props.children}
59 }
60 }
61}
62
63#[derive(Clone, PartialEq, Props)]
64pub struct HoverCardTriggerProps {
65 #[props(extends = div, extends = GlobalAttributes)]
66 attributes: Vec<Attribute>,
67
68 #[props(optional, default)]
69 onclick: EventHandler<MouseEvent>,
70
71 children: Element,
72}
73
74#[component]
75pub fn HoverCardTrigger(mut props: HoverCardTriggerProps) -> Element {
76 let mut state = use_context::<Signal<HoverState>>();
77
78 let default_classes = "hovercard-trigger";
79 crate::setup_class_attribute(&mut props.attributes, default_classes);
80
81 let onclick = move |event| {
83 state.write().toggle();
84 props.onclick.call(event);
85 };
86
87 rsx! {
88 div {
89 role: "button",
90 "data-state": state.into_value(),
91 onclick,
92 ..props.attributes,
93 {props.children}
94 }
95 }
96}
97
98#[derive(Clone, PartialEq, Props)]
99pub struct HoverCardContentProps {
100 #[props(extends = div, extends = GlobalAttributes)]
101 attributes: Vec<Attribute>,
102
103 children: Element,
104}
105
106#[component]
107pub fn HoverCardContent(mut props: HoverCardContentProps) -> Element {
108 let state = use_context::<Signal<HoverState>>();
109
110 let default_classes = "hovercard-content";
111 crate::setup_class_attribute(&mut props.attributes, default_classes);
112
113 rsx! {
114 div {
115 "data-state": state.into_value(),
116 ..props.attributes,
117 {props.children}
118 }
119 }
120}