Skip to main content

dioxus_element_plug/components/
avatar.rs

1use dioxus::prelude::*;
2
3/// Avatar size variants
4#[derive(Clone, PartialEq)]
5pub enum AvatarSize {
6    Large,
7    Default,
8    Small,
9}
10
11impl AvatarSize {
12    pub fn as_class(&self) -> &'static str {
13        match self {
14            AvatarSize::Large => "el-avatar--large",
15            AvatarSize::Default => "",
16            AvatarSize::Small => "el-avatar--small",
17        }
18    }
19}
20
21/// Avatar shape variants
22#[derive(Clone, PartialEq)]
23pub enum AvatarShape {
24    Circle,
25    Square,
26}
27
28impl AvatarShape {
29    pub fn as_class(&self) -> &'static str {
30        match self {
31            AvatarShape::Circle => "el-avatar--circle",
32            AvatarShape::Square => "el-avatar--square",
33        }
34    }
35}
36
37/// Avatar fit type
38#[derive(Clone, PartialEq)]
39pub enum AvatarFit {
40    Fill,
41    Contain,
42    Cover,
43    None,
44    ScaleDown,
45}
46
47impl AvatarFit {
48    pub fn as_str(&self) -> &'static str {
49        match self {
50            AvatarFit::Fill => "fill",
51            AvatarFit::Contain => "contain",
52            AvatarFit::Cover => "cover",
53            AvatarFit::None => "none",
54            AvatarFit::ScaleDown => "scale-down",
55        }
56    }
57}
58
59/// Avatar props
60#[derive(Props, Clone, PartialEq)]
61pub struct AvatarProps {
62    /// Avatar content (text or icon)
63    #[props(default)]
64    pub children: Option<Element>,
65
66    /// Image source URL
67    #[props(default)]
68    pub src: Option<String>,
69
70    /// Icon CSS class
71    #[props(default)]
72    pub icon: Option<String>,
73
74    /// Avatar size
75    #[props(default = AvatarSize::Default)]
76    pub size: AvatarSize,
77
78    /// Avatar shape
79    #[props(default = AvatarShape::Circle)]
80    pub shape: AvatarShape,
81
82    /// Image fit type
83    #[props(default = AvatarFit::Cover)]
84    pub fit: AvatarFit,
85
86    /// Additional CSS classes
87    #[props(default)]
88    pub class: Option<String>,
89
90    /// Inline styles
91    #[props(default)]
92    pub style: Option<String>,
93}
94
95/// Avatar component for displaying user profiles or icons
96///
97/// ## Example
98///
99/// ```rust,ignore
100/// rsx! {
101///     Avatar { src: Some("user.jpg".to_string()), size: AvatarSize::Large }
102///     Avatar { "U" }
103/// }
104/// ```
105#[component]
106pub fn Avatar(props: AvatarProps) -> Element {
107    let mut class_names = vec!["el-avatar".to_string()];
108    class_names.push(props.shape.as_class().to_string());
109
110    let size_class = props.size.as_class();
111    if !size_class.is_empty() {
112        class_names.push(size_class.to_string());
113    }
114
115    if let Some(ref custom_class) = props.class {
116        class_names.push(custom_class.clone());
117    }
118
119    let class_string = class_names.join(" ");
120    let style_string = props.style.clone().unwrap_or_default();
121    let fit_str = props.fit.as_str();
122
123    rsx! {
124        span {
125            class: "{class_string}",
126            style: "{style_string}",
127            if let Some(ref src) = props.src {
128                img {
129                    class: "el-avatar__img",
130                    src: "{src}",
131                    style: "object-fit: {fit_str};",
132                }
133            } else if let Some(ref icon) = props.icon {
134                i {
135                    class: "{icon}"
136                }
137            } else {
138                {props.children}
139            }
140        }
141    }
142}