Component
avatar
dx components add avatarAn avatar component for displaying user profile images or initials.
Basic Usage
Rounded
Loading
Error State
Large Size
Installation
Use the CLI command for the common path, or copy the component files manually.
Manual installation files
Copy the component source and CSS into your app. Import the shared theme CSS once near your app root.
use dioxus::prelude::*;
use dioxus_primitives::dioxus_attributes::attributes;
use dioxus_primitives::avatar::{self, AvatarState};
use dioxus_primitives::merge_attributes;
#[derive(Clone, Copy, PartialEq, Default)]
pub enum AvatarImageSize {
#[default]
Small,
Medium,
Large,
}
impl AvatarImageSize {
fn to_class(self) -> &'static str {
match self {
AvatarImageSize::Small => "dx-avatar-sm",
AvatarImageSize::Medium => "dx-avatar-md",
AvatarImageSize::Large => "dx-avatar-lg",
}
}
}
#[derive(Clone, Copy, PartialEq, Default)]
pub enum AvatarShape {
#[default]
Circle,
Rounded,
}
impl AvatarShape {
fn to_class(self) -> &'static str {
match self {
AvatarShape::Circle => "dx-avatar-circle",
AvatarShape::Rounded => "dx-avatar-rounded",
}
}
}
/// The props for the [`Avatar`] root component.
#[derive(Props, Clone, PartialEq)]
pub struct AvatarProps {
/// Callback when image loads successfully.
#[props(default)]
pub on_load: Option<EventHandler<()>>,
/// Callback when image fails to load.
#[props(default)]
pub on_error: Option<EventHandler<()>>,
/// Callback when the avatar state changes.
#[props(default)]
pub on_state_change: Option<EventHandler<AvatarState>>,
#[props(default)]
pub size: AvatarImageSize,
#[props(default)]
pub shape: AvatarShape,
/// Additional attributes for the avatar element.
#[props(extends = GlobalAttributes)]
pub attributes: Vec<Attribute>,
/// The fallback content shown while the image is loading or if it fails to load.
pub children: Element,
}
#[component]
pub fn Avatar(props: AvatarProps) -> Element {
let class = format!(
"{} {} {}",
"dx-avatar",
props.size.to_class(),
props.shape.to_class()
);
let base = attributes!(span {
class
});
let merged = merge_attributes(vec![base, props.attributes]);
rsx! {
document::Link { rel: "stylesheet", href: asset!("/src/components/avatar/style.css") }
avatar::Avatar {
on_load: props.on_load,
on_error: props.on_error,
on_state_change: props.on_state_change,
attributes: merged,
{props.children}
}
}
}
#[derive(Props, Clone, PartialEq)]
pub struct AvatarImageProps {
#[props(default)]
pub id: ReadSignal<Option<String>>,
pub src: String,
#[props(default)]
pub alt: String,
#[props(extends = GlobalAttributes)]
pub attributes: Vec<Attribute>,
}
#[component]
pub fn AvatarImage(props: AvatarImageProps) -> Element {
let base = attributes!(img {
class: "dx-avatar-image",
draggable: "false",
});
let merged = merge_attributes(vec![base, props.attributes]);
rsx! {
document::Link { rel: "stylesheet", href: asset!("/src/components/avatar/style.css") }
avatar::AvatarImage {
id: props.id,
src: props.src,
alt: props.alt,
attributes: merged,
}
}
}
#[derive(Props, Clone, PartialEq)]
pub struct AvatarFallbackProps {
#[props(extends = GlobalAttributes)]
pub attributes: Vec<Attribute>,
pub children: Element,
}
#[component]
pub fn AvatarFallback(props: AvatarFallbackProps) -> Element {
let base = attributes!(span {
class: "dx-avatar-fallback",
});
let merged = merge_attributes(vec![base, props.attributes]);
rsx! {
document::Link { rel: "stylesheet", href: asset!("/src/components/avatar/style.css") }
avatar::AvatarFallback {
attributes: merged,
{props.children}
}
}
}
/// The props for the [`ImageAvatar`] convenience component.
#[derive(Props, Clone, PartialEq)]
pub struct ImageAvatarProps {
/// The image source URL.
pub src: String,
/// The image alt text.
#[props(default)]
pub alt: String,
/// Callback when image loads successfully.
#[props(default)]
pub on_load: Option<EventHandler<()>>,
/// Callback when image fails to load.
#[props(default)]
pub on_error: Option<EventHandler<()>>,
/// Callback when the avatar state changes.
#[props(default)]
pub on_state_change: Option<EventHandler<AvatarState>>,
#[props(default)]
pub size: AvatarImageSize,
#[props(default)]
pub shape: AvatarShape,
/// Additional attributes for the avatar element.
#[props(extends = GlobalAttributes)]
pub attributes: Vec<Attribute>,
/// The fallback content shown while the image is loading or if it fails to load.
pub children: Element,
}
#[component]
pub fn ImageAvatar(props: ImageAvatarProps) -> Element {
// axe `role-img-alt` (docs/backlog.md row 34's own round): the root
// `Avatar` renders `role="img"` (`avatar.rs`) and gets its accessible
// name from a caller-supplied `aria_label`, same as this crate's own
// doc example -- this convenience wrapper forwarded `alt` only to the
// inner `<img>` (via `AvatarImage`), never to the outer `role="img"`
// span, so every caller that used `alt` instead of separately also
// setting `aria_label` (every dashboard email-client avatar; the
// sidebar's user avatar) rendered an unnamed `role="img"`. Default the
// root's `aria_label` from `alt` -- merged caller-wins, so an explicit
// `aria_label` in `props.attributes` still overrides it. Contributed
// only when `alt` is non-empty: an `aria-label=""` is still an empty
// accessible name (no better than omitting it), and would additionally
// shadow any real name the caller supplies some other way.
let base: Vec<Attribute> = if props.alt.is_empty() {
Vec::new()
} else {
attributes!(span { aria_label: "{props.alt}" })
};
let attributes = merge_attributes(vec![base, props.attributes]);
rsx! {
document::Link { rel: "stylesheet", href: asset!("/src/components/avatar/style.css") }
Avatar {
on_load: props.on_load,
on_error: props.on_error,
on_state_change: props.on_state_change,
size: props.size,
shape: props.shape,
attributes,
AvatarImage {
src: props.src,
alt: props.alt,
}
AvatarFallback {
{props.children}
}
}
}
}Usage notes
The Avatar components display a user's profile picture or fallback initials. Use the composable Avatar, AvatarImage, and AvatarFallback primitives when you need full control, or ImageAvatar for the common image-with-fallback case.
Component Structure
Avatar {
aria_label: "Jane Doe",
AvatarImage {
src: "https://example.com/avatar.png",
alt: "Jane Doe",
}
AvatarFallback { "JD" }
}ImageAvatar {
src: "https://example.com/avatar.png",
alt: "Jane Doe",
on_state_change: |state: AvatarState| { /* image is loading/loaded/failed */ },
"JD"
}