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 }