use dioxus::prelude::*;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum IndicatorPosition {
#[default]
TopEnd,
TopStart,
BottomEnd,
BottomStart,
}
impl IndicatorPosition {
#[must_use]
pub fn class_name(&self) -> &'static str {
match self {
Self::TopEnd => "sd-indicator-badge--top-end",
Self::TopStart => "sd-indicator-badge--top-start",
Self::BottomEnd => "sd-indicator-badge--bottom-end",
Self::BottomStart => "sd-indicator-badge--bottom-start",
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum IndicatorColor {
#[default]
Violet,
Emerald,
Rose,
Amber,
Cyan,
}
impl IndicatorColor {
#[must_use]
pub fn class_name(&self) -> &'static str {
match self {
Self::Violet => "sd-indicator-badge--violet",
Self::Emerald => "sd-indicator-badge--emerald",
Self::Rose => "sd-indicator-badge--rose",
Self::Amber => "sd-indicator-badge--amber",
Self::Cyan => "sd-indicator-badge--cyan",
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum IndicatorSize {
Sm,
#[default]
Md,
Lg,
}
impl IndicatorSize {
#[must_use]
pub fn class_name(&self) -> &'static str {
match self {
Self::Sm => "sd-indicator-badge--sm",
Self::Md => "sd-indicator-badge--md",
Self::Lg => "sd-indicator-badge--lg",
}
}
}
#[component]
pub fn Indicator(
#[props(default)]
position: IndicatorPosition,
#[props(default)]
color: IndicatorColor,
#[props(default)]
size: IndicatorSize,
#[props(default)]
label: Option<String>,
#[props(default = false)]
processing: bool,
#[props(default = false)]
disabled: bool,
#[props(default)]
offset: Option<i32>,
#[props(default)]
class: String,
children: Element,
) -> Element {
let pos_class = position.class_name();
let col_class = color.class_name();
let sz_class = size.class_name();
let with_label_class = if label.is_some() { "sd-indicator-badge--with-label" } else { "" };
let processing_class = if processing { "sd-indicator-badge--processing" } else { "" };
let offset_style = if let Some(off) = offset {
match position {
IndicatorPosition::TopEnd => format!("top: {off}px; right: {off}px;"),
IndicatorPosition::TopStart => format!("top: {off}px; left: {off}px;"),
IndicatorPosition::BottomEnd => format!("bottom: {off}px; right: {off}px;"),
IndicatorPosition::BottomStart => format!("bottom: {off}px; left: {off}px;"),
}
} else {
String::new()
};
rsx! {
div { class: "sd-indicator {class}",
{children}
if !disabled {
div {
class: "sd-indicator-badge {pos_class} {col_class} {sz_class} {with_label_class} {processing_class}",
style: "{offset_style}",
if let Some(ref l) = label {
span { class: "sd-indicator-text", "{l}" }
}
if processing {
span { class: "sd-indicator-pulse" }
}
}
}
}
}
}