Skip to main content

shadow_design/
badge.rs

1use dioxus::prelude::*;
2
3#[derive(Clone, Copy, PartialEq, Debug, Default)]
4pub enum BadgeVariant {
5    #[default]
6    Default,
7    Primary,
8    Success,
9    Warning,
10    Danger,
11    Outline,
12}
13
14impl BadgeVariant {
15    pub fn scss_class(&self) -> &'static str {
16        match self {
17            BadgeVariant::Default => "sd-badge--default",
18            BadgeVariant::Primary => "sd-badge--primary",
19            BadgeVariant::Success => "sd-badge--success",
20            BadgeVariant::Warning => "sd-badge--warning",
21            BadgeVariant::Danger => "sd-badge--danger",
22            BadgeVariant::Outline => "sd-badge--outline",
23        }
24    }
25
26    pub fn name(&self) -> &'static str {
27        match self {
28            BadgeVariant::Default => "default",
29            BadgeVariant::Primary => "primary",
30            BadgeVariant::Success => "success",
31            BadgeVariant::Warning => "warning",
32            BadgeVariant::Danger => "danger",
33            BadgeVariant::Outline => "outline",
34        }
35    }
36
37    pub fn dot_color_class(&self) -> &'static str {
38        match self {
39            BadgeVariant::Default => "default",
40            BadgeVariant::Primary => "primary",
41            BadgeVariant::Success => "success",
42            BadgeVariant::Warning => "warning",
43            BadgeVariant::Danger => "danger",
44            BadgeVariant::Outline => "outline",
45        }
46    }
47}
48
49#[component]
50pub fn Badge(
51    label: String,
52    #[props(default)] variant: BadgeVariant,
53    #[props(default)] pill: bool,
54    #[props(default)] dot: bool,
55    #[props(default)] glow: Option<bool>,
56    #[props(default)] class: String,
57) -> Element {
58    let pill_class = if pill { "sd-badge--pill" } else { "" };
59
60    #[cfg(feature = "theme")]
61    let theme_val = crate::theme::use_theme()();
62    #[cfg(feature = "theme")]
63    let radius = if pill {
64        ""
65    } else {
66        theme_val.radius_scale.sm()
67    };
68    #[cfg(feature = "theme")]
69    let base_override = theme_val.resolve_component_base("badge").unwrap_or("");
70    #[cfg(feature = "theme")]
71    let class_modifiers = theme_val.resolve_class_modifiers("badge", &class);
72    #[cfg(feature = "theme")]
73    let default_badge_variant = match variant {
74        BadgeVariant::Default => &theme_val.badge_default,
75        BadgeVariant::Primary => &theme_val.badge_primary,
76        BadgeVariant::Success => &theme_val.badge_success,
77        BadgeVariant::Warning => &theme_val.badge_warning,
78        BadgeVariant::Danger => &theme_val.badge_danger,
79        BadgeVariant::Outline => &theme_val.badge_outline,
80    };
81    #[cfg(feature = "theme")]
82    let variant_class = theme_val.resolve_variant_class("badge", variant.name(), default_badge_variant);
83    #[cfg(feature = "theme")]
84    let glow_class = theme_val.resolve_elevation_class("badge", glow);
85
86    #[cfg(not(feature = "theme"))]
87    let base_override = "";
88    #[cfg(not(feature = "theme"))]
89    let class_modifiers = String::new();
90    #[cfg(not(feature = "theme"))]
91    let variant_class = variant.scss_class().to_string();
92    #[cfg(not(feature = "theme"))]
93    let radius = "";
94    #[cfg(not(feature = "theme"))]
95    let glow_class = if glow == Some(true) || (glow.is_none() && variant == BadgeVariant::Primary) {
96        "sd-badge--glow".to_string()
97    } else {
98        String::new()
99    };
100
101    let dot_kind = variant.dot_color_class();
102
103    rsx! {
104        span {
105            class: "sd-badge {base_override} {variant_class} {pill_class} {radius} {glow_class} {class_modifiers} {class}",
106            if dot {
107                span { class: "sd-badge__dot-container",
108                    span { class: "sd-badge__dot-ping sd-badge__dot-ping--{dot_kind}" }
109                    span { class: "sd-badge__dot sd-badge__dot--{dot_kind}" }
110                }
111            }
112            "{label}"
113        }
114    }
115}