1use dioxus::prelude::*;
2
3#[derive(Clone, Copy, PartialEq, Debug, Default)]
4pub enum CardShadow {
5 None,
6 Sm,
7 #[default]
8 Md,
9 Lg,
10 Xl,
11}
12
13impl CardShadow {
14 pub fn scss_class(&self) -> &'static str {
15 match self {
16 CardShadow::None => "sd-card--shadow-none",
17 CardShadow::Sm => "sd-card--shadow-sm",
18 CardShadow::Md => "sd-card--shadow-md",
19 CardShadow::Lg => "sd-card--shadow-lg",
20 CardShadow::Xl => "sd-card--shadow-xl",
21 }
22 }
23}
24
25#[derive(Clone, Copy, PartialEq, Debug, Default)]
26pub enum CardVariant {
27 #[default]
28 Default,
29 Elevated,
30 Interactive,
31 Metric,
32}
33
34impl CardVariant {
35 pub fn scss_class(&self) -> &'static str {
36 match self {
37 CardVariant::Default => "",
38 CardVariant::Elevated => "sd-card--elevated",
39 CardVariant::Interactive => "sd-card--interactive",
40 CardVariant::Metric => "sd-card--metric",
41 }
42 }
43}
44
45#[component]
46pub fn Card(
47 #[props(default)] title: Option<String>,
48 #[props(default)] subtitle: Option<String>,
49 #[props(default)] variant: CardVariant,
50 #[props(default)] shadow: CardShadow,
51 #[props(default)] hover_glow: bool,
52 #[props(default)] glow: Option<bool>,
53 #[props(default = false)] overflow_hidden: bool,
54 #[props(default)] class: String,
55 #[props(default)] footer: Option<Element>,
56 children: Element,
57) -> Element {
58 let variant_class = variant.scss_class();
59 let shadow_class = shadow.scss_class();
60 let overflow_class = if overflow_hidden {
61 "sd-card--overflow-hidden"
62 } else {
63 ""
64 };
65
66 #[cfg(feature = "theme")]
67 let theme = crate::theme::use_theme();
68 #[cfg(feature = "theme")]
69 let radius_class = theme().radius_scale.md();
70 #[cfg(feature = "theme")]
71 let glow_class = match glow {
72 Some(true) => match theme().primary_color {
73 crate::theme::PrimaryColor::Violet => "sd-card--glow-violet",
74 crate::theme::PrimaryColor::Obsidian => "sd-card--glow-obsidian",
75 crate::theme::PrimaryColor::Crimson => "sd-card--glow-crimson",
76 crate::theme::PrimaryColor::Cyan => "sd-card--glow-cyan",
77 crate::theme::PrimaryColor::Emerald => "sd-card--glow-emerald",
78 },
79 Some(false) => "",
80 None => {
81 if hover_glow
82 || (theme().glow_mode != crate::theme::GlowMode::Off
83 && variant == CardVariant::Interactive)
84 {
85 "sd-card--hover-glow"
86 } else {
87 ""
88 }
89 }
90 };
91
92 #[cfg(not(feature = "theme"))]
93 let radius_class = "";
94 #[cfg(not(feature = "theme"))]
95 let glow_class = if hover_glow || glow == Some(true) {
96 "sd-card--hover-glow"
97 } else {
98 ""
99 };
100
101 rsx! {
102 div {
103 class: "sd-card {variant_class} {shadow_class} {radius_class} {glow_class} {overflow_class} {class}",
104 if title.is_some() || subtitle.is_some() {
105 div { class: "sd-card__header",
106 if let Some(t) = title {
107 h3 { class: "sd-card__title", "{t}" }
108 }
109 if let Some(s) = subtitle {
110 p { class: "sd-card__subtitle", "{s}" }
111 }
112 }
113 }
114 div { class: "sd-card__body",
115 {children}
116 }
117 if let Some(f) = footer {
118 div { class: "sd-card__footer",
119 {f}
120 }
121 }
122 }
123 }
124}