/ libs / ui / src / components / hover_card.rs
hover_card.rs
 1  use dioxus::prelude::*;
 2  use dioxus_primitives::hover_card::{
 3      HoverCard as PrimitiveHoverCard, HoverCardContent as PrimitiveHoverCardContent,
 4      HoverCardTrigger as PrimitiveHoverCardTrigger,
 5  };
 6  
 7  use dioxus::html::GlobalAttributesExtension;
 8  pub use dioxus_primitives::{ContentAlign as HoverCardAlign, ContentSide as HoverCardSide};
 9  
10  /// HoverCard main container, styled with Tailwind
11  #[derive(Props, Clone, PartialEq)]
12  pub struct HoverCardProps {
13      #[props(default)]
14      pub class: Option<String>,
15      pub children: Element,
16  }
17  
18  #[component]
19  pub fn HoverCard(props: HoverCardProps) -> Element {
20      let default_classes = "relative inline-block";
21      let class = if let Some(extra) = &props.class {
22          format!("{} {}", extra, default_classes)
23      } else {
24          default_classes.to_string()
25      };
26  
27      rsx! {
28          PrimitiveHoverCard {
29              class: class,
30              {props.children}
31          }
32      }
33  }
34  
35  /// HoverCardTrigger: The element that triggers the hover card, styled with Tailwind
36  #[derive(Props, Clone, PartialEq)]
37  pub struct HoverCardTriggerProps {
38      #[props(default)]
39      pub class: Option<String>,
40      pub children: Element,
41  }
42  
43  #[component]
44  pub fn HoverCardTrigger(props: HoverCardTriggerProps) -> Element {
45      let default_classes = "cursor-pointer focus:outline-none";
46      let class = if let Some(extra) = &props.class {
47          format!("{} {}", extra, default_classes)
48      } else {
49          default_classes.to_string()
50      };
51  
52      rsx! {
53          PrimitiveHoverCardTrigger {
54              class: class,
55              {props.children}
56          }
57      }
58  }
59  
60  /// HoverCardContent: The floating card content, styled with Tailwind
61  #[derive(Props, Clone, PartialEq)]
62  pub struct HoverCardContentProps {
63      #[props(default)]
64      pub class: Option<String>,
65      #[props(default)]
66      pub side: Option<HoverCardSide>,
67      #[props(default)]
68      pub align: Option<HoverCardAlign>,
69      pub children: Element,
70  }
71  
72  #[component]
73  pub fn HoverCardContent(props: HoverCardContentProps) -> Element {
74      let default_classes = "pointer-events-none opacity-0 data-[state=open]:pointer-events-auto data-[state=open]:opacity-100 absolute top-full z-50 transition-all duration-200 py-2";
75      let class = if let Some(extra) = &props.class {
76          format!("{} {}", extra, default_classes)
77      } else {
78          default_classes.to_string()
79      };
80  
81      rsx! {
82          PrimitiveHoverCardContent {
83              class: class,
84              side: props.side.unwrap_or(HoverCardSide::Top),
85              align: props.align.unwrap_or(HoverCardAlign::Center),
86              div {
87                  class: "min-w-[16rem] max-w-[22rem] bg-popover border border-border rounded-xl shadow-xl p-5",
88                  {props.children}
89              }
90          }
91      }
92  }