Skip to main content

dioxus_element_plug/components/
tag.rs

1use dioxus::prelude::*;
2
3/// Tag type variants
4#[derive(Clone, PartialEq)]
5pub enum TagType {
6    Primary,
7    Success,
8    Info,
9    Warning,
10    Danger,
11}
12
13impl TagType {
14    pub fn as_class(&self) -> &'static str {
15        match self {
16            TagType::Primary => "el-tag--primary",
17            TagType::Success => "el-tag--success",
18            TagType::Info => "el-tag--info",
19            TagType::Warning => "el-tag--warning",
20            TagType::Danger => "el-tag--danger",
21        }
22    }
23}
24
25/// Tag size variants
26#[derive(Clone, PartialEq)]
27pub enum TagSize {
28    Large,
29    Default,
30    Small,
31}
32
33impl TagSize {
34    pub fn as_class(&self) -> &'static str {
35        match self {
36            TagSize::Large => "el-tag--large",
37            TagSize::Default => "",
38            TagSize::Small => "el-tag--small",
39        }
40    }
41}
42
43/// Tag effect variants
44#[derive(Clone, PartialEq)]
45pub enum TagEffect {
46    Dark,
47    Light,
48    Plain,
49}
50
51impl TagEffect {
52    pub fn as_class(&self) -> &'static str {
53        match self {
54            TagEffect::Dark => "el-tag--dark",
55            TagEffect::Light => "el-tag--light",
56            TagEffect::Plain => "el-tag--plain",
57        }
58    }
59}
60
61/// Tag props
62#[derive(Props, Clone, PartialEq)]
63pub struct TagProps {
64    /// Tag content
65    #[props(default)]
66    pub children: Element,
67
68    /// Tag type
69    #[props(default = TagType::Primary)]
70    pub tag_type: TagType,
71
72    /// Tag size
73    #[props(default = TagSize::Default)]
74    pub size: TagSize,
75
76    /// Tag effect
77    #[props(default = TagEffect::Light)]
78    pub effect: TagEffect,
79
80    /// Whether the tag is closable
81    #[props(default = false)]
82    pub closable: bool,
83
84    /// Whether the tag is rounded
85    #[props(default = false)]
86    pub round: bool,
87
88    /// Whether the tag has a highlighted border
89    #[props(default = false)]
90    pub hit: bool,
91
92    /// Custom background color
93    #[props(default)]
94    pub color: Option<String>,
95
96    /// Close event handler
97    #[props(default)]
98    pub on_close: Option<EventHandler<MouseEvent>>,
99
100    /// Click event handler
101    #[props(default)]
102    pub on_click: Option<EventHandler<MouseEvent>>,
103
104    /// Additional CSS classes
105    #[props(default)]
106    pub class: Option<String>,
107
108    /// Inline styles
109    #[props(default)]
110    pub style: Option<String>,
111}
112
113/// Tag component for displaying status, categories or labels
114///
115/// ## Example
116///
117/// ```rust,ignore
118/// rsx! {
119///     Tag { tag_type: TagType::Success, "Success" }
120///     Tag { tag_type: TagType::Warning, closable: true, "Warning" }
121/// }
122/// ```
123#[component]
124pub fn Tag(props: TagProps) -> Element {
125    let mut class_names = vec!["el-tag".to_string()];
126
127    class_names.push(props.tag_type.as_class().to_string());
128    class_names.push(props.effect.as_class().to_string());
129
130    let size_class = props.size.as_class();
131    if !size_class.is_empty() {
132        class_names.push(size_class.to_string());
133    }
134
135    if props.round {
136        class_names.push("is-round".to_string());
137    }
138
139    if props.hit {
140        class_names.push("is-hit".to_string());
141    }
142
143    if let Some(ref custom_class) = props.class {
144        class_names.push(custom_class.clone());
145    }
146
147    let class_string = class_names.join(" ");
148
149    let mut style_string = props.style.clone().unwrap_or_default();
150    if let Some(ref color) = props.color {
151        style_string = format!("background-color: {}; border-color: {}; {}", color, color, style_string);
152    }
153
154    rsx! {
155        span {
156            class: "{class_string}",
157            style: "{style_string}",
158            onclick: move |event| {
159                if let Some(handler) = props.on_click {
160                    handler.call(event);
161                }
162            },
163            {props.children}
164            if props.closable {
165                span {
166                    class: "el-tag__close",
167                    onclick: move |event| {
168                        if let Some(handler) = props.on_close {
169                            handler.call(event);
170                        }
171                    },
172                    "×"
173                }
174            }
175        }
176    }
177}