Skip to content
PorabuildHeroGPUI component library
v0.14.0 · Apache-2.0

Media

Avatar

Display an image or initials representing a user.

Rust
use herogpui::components::avatar::Avatar;

Avatar on docs.rsSource at v0.14.0

Usage

Showing Usage, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.

Usage

Fallback text uses 14px/20px, 12px/16px for small and 16px/24px for large avatars. Here `radius` sets 8px corners and `sx` squares just the top-left corner on the fallback and loaded image. An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Avatar;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![Avatar::new("avatar-avatar")
        .name("Jane Doe")
        .radius(px(8.))
        .sx(|el| el.rounded_tl(px(0.)))
        .into_any_element()])

Fallback Content

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{ActiveTheme, Avatar, AvatarVariant, Color, icons};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{AnyElement, px};
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Avatar::new("avatar-avatar").name("Jane Doe")
            .into_any_element(),
        Avatar::new("avatar-avatar")
            .into_any_element(),
        // v3's own Fallback Content example drives a
        // deliberately broken URL with
        // `<Avatar.Fallback delayMs={600}>`; an unregistered
        // asset path fails identically here (no network), and
        // the initials replace the box once the delay elapses.
        spec(
            "Broken image",
            Avatar::new("avatar-avatar")
                .name("NA")
                .src("images/avatar-broken.png")
                .delay_ms(600),
            cx,
        ),
        Avatar::new("avatar-avatar")
            .name("HG")
            .fallback(gpui::svg()
                          .size(px(16.))
                          .path(icons::HEART_FILL)
                          .text_color(cx.colors().foreground)
                          .into_any_element())
            .into_any_element(),
        Avatar::new("avatar-color-avatar")
            .name("HG")
            .color(Color::Accent)
            .variant(AvatarVariant::Soft)
            .fallback_color(Color::Warning)
            .into_any_element(),
    ])

Also calls spec (included when you copy).

Sizes

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Avatar, Size};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(Size::ALL
            .iter()
            .enumerate()
            .map(|(i, s)| {
                Avatar::new(("size-avatar", i))
                    .name("Ada Lovelace")
                    .size(*s)
                    .into_any_element()
            }))

Colors

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Avatar, Color};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(Color::ALL
        .iter()
        .enumerate()
        .map(|(i, c)| Avatar::new(("color-avatar", i)).name("HG").color(*c)))

Variants

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Avatar, AvatarVariant, Color};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(AvatarVariant::ALL
            .iter()
            .enumerate()
            .map(|(i, v)| {
                Avatar::new(("variant-avatar", i))
                    .name("HG")
                    .color(Color::Accent)
                    .variant(*v)
                    .into_any_element()
            }))

Custom Image Component

A custom image source composes the same way: the loader below supplies the embedded sample image itself, and `on_load` fires once the image is ready and replaces the fallback. An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Avatar, Toast};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
use std::sync::Arc;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Avatar::new("avatar-loader-avatar")
            .name("JD")
            .src(sample_avatar_source())
            .fallback("JD")
            .on_load(|_, cx| {
                Toast::new("Avatar image loaded")
                    .description("on_load fired once for the custom source.")
                    .push(Some(std::time::Duration::from_secs(3)), cx);
            })
            .into_any_element(),
    ])

Also calls sample_avatar_source (included when you copy).

Helpers used by these examples

Plain functions over the public API, defined once here and copied with each example that calls them.

spec
/// A labelled specimen — the caption HeroUI puts under each variant.
fn spec(label: &str, el: impl IntoElement, cx: &gpui::App) -> AnyElement {
    let muted = cx.colors().muted;
    gpui::div()
        .flex()
        .flex_col()
        .items_center()
        .gap(px(6.))
        .child(el)
        .child(
            gpui::div()
                .text_size(px(11.))
                .text_color(muted)
                .child(label.to_owned()),
        )
        .into_any_element()
}
sample_avatar_source
/// One stable custom image source for the Avatar "Custom Image Component"
/// demo: the loader `Arc` is built once, so the avatar's per-source keyed
/// state and its `on_load` keep their identity across frames.
fn sample_avatar_source() -> gpui::ImageSource {
    type AvatarLoader = std::sync::Arc<
        dyn Fn(
                &mut gpui::Window,
                &mut gpui::App,
            )
                -> Option<Result<std::sync::Arc<gpui::RenderImage>, gpui::ImageCacheError>>
            + Send
            + Sync,
    >;
    static LOADER: std::sync::OnceLock<AvatarLoader> = std::sync::OnceLock::new();
    let loader: &AvatarLoader = LOADER.get_or_init(|| {
        let image = std::sync::Arc::new(gpui::Image::from_bytes(
            gpui::ImageFormat::Png,
            include_bytes!("../../../assets/herogpui/sample.png").to_vec(),
        ));
        std::sync::Arc::new(move |window: &mut gpui::Window, cx: &mut gpui::App| {
            image.clone().use_render_image(window, cx).map(Ok)
        })
    });
    gpui::ImageSource::Custom(loader.clone())
}

Anatomy

Rust types

Avatar

Avatar is assembled from these builders. The API reference lists each one.

Customization

Shared appearance belongs on ThemeBuilder::components and .recipe("name"). Typed builders change how Avatar looks at one call site. Every builder also carries sx for placement, width and flex: it takes GPUI's own styling methods and refines them over the component's root after the theme, so an instance override wins. Behaviour builders live in the API reference below.

Styling

Avatar styling
MethodValuesDescription
size(Size)Size::Sm | Size::Md | Size::LgAvatar size: 32/40/48px edge, with `sm` rounding one step tighter and stepping the fallback text down to 12px, and `lg` stepping it up to 16px. Inside an `AvatarGroup`, an omitted size comes from the group.
color(Color)Color::Default | Color::Accent | Color::Success | Color::Warning | Color::DangerFallback color theme. The base avatar fills `bg-default` for every color — the color recolours the initials via the soft-foreground token.
variant(AvatarVariant)AvatarVariant::Default | AvatarVariant::SoftVisual style variant. `soft` clears the base fill and paints `bg-{role}-soft` with the same soft foreground.
Rust
// The one slot for caller-owned low-level styling: GPUI's
// styling methods, refined over the root element last.
.sx(|el| {
    el.bg(gpui::rgba(0xffa500ff))             // background
        .text_color(gpui::rgba(0x000000ff))   // text
        .w(gpui::px(13.))                     // size
        .h(gpui::px(12.))
})

API reference

Against HeroUI v3.2.6: 8 entries ported, 3 partial, 9 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Avatar builders
BuilderValuesDefaultDescription
size(Size)Size::Sm | Size::Md | Size::LgSize::MdAvatar size: 32/40/48px edge, with `sm` rounding one step tighter and stepping the fallback text down to 12px, and `lg` stepping it up to 16px. Inside an `AvatarGroup`, an omitted size comes from the group.
color(Color)Color::Default | Color::Accent | Color::Success | Color::Warning | Color::DangerColor::DefaultFallback color theme. The base avatar fills `bg-default` for every color — the color recolours the initials via the soft-foreground token.
variant(AvatarVariant)AvatarVariant::Default | AvatarVariant::SoftAvatarVariant::DefaultVisual style variant. `soft` clears the base fill and paints `bg-{role}-soft` with the same soft foreground.
src(ImageSource)string—Image source URL. A plain string or path loads through gpui's asset system (a parseable URI is fetched, anything else is an embedded resource); the gpui `ImageSource::Image` / `Render` / `Custom` variants are the explicit parts for images the app already holds or loads itself.
on_load(handler)PartialFn(event: image event) -> ()—Callback when the image loads successfully and replaces the fallback. Fires once per source, on the first observed success, outside the layout phase; there is no event payload to hand over.
on_error(handler)PartialFn(event: image event) -> ()—Callback when there's an error loading the image; the fallback initials replace the image on that same failure. A decoded image with zero width counts as a failure (Radix Avatar 1.2.6 `naturalWidth > 0`). Fires once per source; no event payload.
delay_ms(u64)number—Delay before showing the fallback, measured from mount so a slow load does not flash the initials behind it. A success inside the window renders before it elapses; a failure inside it waits for the same window rather than restarting it.
fallback_color(Color)Color::Default | Color::Accent | Color::Success | Color::Warning | Color::Danger—Override color from parent. Its own documented prop, not an alias: it overrides the parent `color` for everything the fallback paints, while the parent color still governs the rest.
Not ported9 HeroUI entries not ported
Avatar builders not ported
HeroUI v3Why it is not ported
Avatar.className
Avatar.Image.srcSetThe image `srcset` attribute for responsive images. Browser-only: gpui's asset system resolves one resource per source and never selects between candidates.
Avatar.Image.sizesThe image `sizes` attribute. Browser-only hint for `srcset` selection; there is no viewport-density image pick to hint.
Avatar.Image.altAlternative text for the image. Gpui-pre 0.3.3 has no accessibility tree to carry it.
Avatar.Image.asChildMerges props onto a child element instead of rendering a native `img`. There is no element graph to merge onto; a gpui `ImageSource::Custom` loader is the equivalent seam for a custom image component.
Avatar.Image.crossOriginCORS setting for the image request. Browser fetch metadata with no analogue in gpui's asset system.
Avatar.Image.loadingNative lazy loading attribute. Gpui loads a source when it is first observed; there is no viewport-distance scheduler to defer with.
Avatar.Image.className
Avatar.Fallback.className

Parts

Avatar parts
PartDescription
AvatarRoot container on the `.avatar` BEM class: `relative flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-3xl bg-default`. The name initials come from the port's own `name` builder (has no `name` prop); the load progress and the `delayMs` window key on the image source.
AvatarPartial`absolute inset-0 aspect-square size-full` image with an opacity transition. Draws the loaded image directly inside the root (`img(data).size_full().rounded(radius)`), applying the root radius to keep the image inside the Avatar boundary, and does not animate the swap.
Avatar`flex size-full items-center justify-center bg-default text-sm font-medium` fallback box. The separate fallback container centers initials or custom `fallback` children with 14px/20px medium text (12px/16px for small and 16px/24px for large avatars), painted `text-{role}-soft-foreground`.