Styleframe Logo
Layout

Avatar

A user avatar with an image and an automatic initials fallback — circular or square, with an optional status badge — built as a multi-part recipe system.

Overview

The Avatar represents a user or entity with an image, falling back to initials when no image is available or the image fails to load. The useAvatarRecipe() composable creates a fully configured recipe with color, variant, shape, and size options, while useAvatarBadgeRecipe() adds a small status dot for presence indicators. For stacked, overlapping avatars, see the Avatar Group recipe.

The Avatar recipe integrates directly with the default design tokens preset and generates type-safe utility classes at build time with zero runtime CSS.

Why use the Avatar recipe?

The Avatar recipe helps you:

  • Ship faster with sensible defaults: A neutral, soft, circular avatar out of the box from a single composable call.
  • Fail gracefully: The image clips to the avatar shape, and a styled initials fallback covers missing or broken images.
  • Express identity and status: Colored fallbacks plus an optional status badge cover presence states without extra components.
  • Customize without forking: Override base styles, default variants, or filter out options you don't need — all through the options API.
  • Stay type-safe: Full TypeScript support means your editor catches invalid color, variant, shape, or size values at compile time.

Usage

Register the recipes

Add the Avatar recipes to a local Styleframe instance. The global styleframe.config.ts provides design tokens and utilities, while the component-level file registers the recipes themselves:

src/components/avatar.styleframe.ts
import { styleframe } from 'virtual:styleframe';
import { useAvatarRecipe, useAvatarBadgeRecipe } from '@styleframe/theme';

const s = styleframe();

const avatar = useAvatarRecipe(s);
const avatarBadge = useAvatarBadgeRecipe(s);

export default s;

Build the component

Import the avatar runtime function from the virtual module, pass variant props to compute class names, and render an <img> with an initials fallback:

src/components/Avatar.tsx
import { useState } from "react";
import { avatar, type AvatarProps } from "virtual:styleframe";

interface AvatarComponentProps extends AvatarProps {
    src?: string;
    alt?: string;
    label?: string;
}

export function Avatar({ src, alt, label, ...variants }: AvatarComponentProps) {
    const [failed, setFailed] = useState(false);

    return (
        <span className={avatar(variants)}>
            {src && !failed ? (
                <img src={src} alt={alt} onError={() => setFailed(true)} />
            ) : (
                label
            )}
        </span>
    );
}

See it in action

Colors

The Avatar fallback surface supports 4 color options following the Minimal color pattern. The default neutral color renders a muted gray surface that adapts to light and dark mode.

Color Reference

ColorBehaviorUse Case
primaryBrand color, adapts to dark modeHighlighted or "you" avatars
lightAlways light, fixed across modesAvatars on dark backgrounds
darkAlways dark, fixed across modesAvatars on light backgrounds
neutralAdaptive (light ↔ dark)Default, general-purpose fallback
Pro tip: Use neutral for general-purpose initials fallbacks that adapt to both light and dark mode automatically.

Variants

Two fill styles control how the fallback color is applied. solid fills the avatar with the color and uses light text; soft uses a tinted background with darker text.

VariantDescription
solidFilled background with contrasting text
softTinted background with colored text (default)

Shapes

The Avatar can be rendered as a circle (default) or a square with rounded corners. The image clips to the chosen shape automatically.

ShapeBorder Radius
circle@border-radius.full
square@border-radius.md

Sizes

The Avatar comes in 5 sizes that control both the dimensions and the fallback initials font size.

SizeDimensionsFont Size
xs@spacing * 1.5 × @spacing * 1.5@font-size.2xs
sm@spacing * 2 × @spacing * 2@font-size.xs
md@spacing * 2.5 × @spacing * 2.5@font-size.sm
lg@spacing * 3 × @spacing * 3@font-size.md
xl@spacing * 4 × @spacing * 4@font-size.lg

Image and fallback

Place an <img> inside the avatar — the recipe's > img selector sizes it to cover the box and clips it to the avatar shape via border-radius: inherit. Render the initials fallback when no image is set or when the image fails to load.

Good to know: Because the avatar root stays position: relative (rather than overflow: hidden), a status badge can sit at the edge without being clipped — see below.

Status indicator

Add useAvatarBadgeRecipe() to render a small status dot anchored to the bottom-right of an avatar. The badge uses the Full color pattern so it can express presence states.

Status colorTypical meaning
successOnline (default)
warningAway
errorBusy / do not disturb
neutralOffline
src/components/Avatar.vue
<span :class="avatar({ size: 'lg' })">
    AL
    <span :class="avatarBadge({ color: 'success', size: 'lg' })" />
</span>

Accessibility

  • Provide an alt on the image that names the person or entity (e.g. alt="Ada Lovelace"). Use an empty alt="" only when the avatar is purely decorative and the name appears adjacent.
  • The initials fallback is text and is announced by screen readers; keep it meaningful (the person's initials).
  • Communicate status in text, not color alone: pair the status badge with a visible or visually-hidden label (e.g. "Online") so presence isn't conveyed by color only.

Customization

Overriding Defaults

src/components/avatar.styleframe.ts
const avatar = useAvatarRecipe(s, {
    defaultVariants: { color: 'primary', variant: 'solid', size: 'lg', shape: 'square' },
});

Filtering Variants

src/components/avatar.styleframe.ts
const avatar = useAvatarRecipe(s, {
    filter: {
        color: ['neutral', 'primary'],
        shape: ['circle'],
    },
});
Good to know: Filtering also removes compound variants and adjusts default variants that reference filtered-out values, so your recipe stays consistent.

API Reference

useAvatarRecipe(s, options?)

Creates the avatar recipe with color, variant, shape, and size variants. Registers a > img selector that clips the image to the avatar shape.

Parameters:

ParameterTypeDescription
sStyleframeThe Styleframe instance
optionsDeepPartial<RecipeConfig>Optional overrides for the recipe configuration
options.baseVariantDeclarationsBlockCustom base styles
options.variantsVariantsCustom variant definitions
options.defaultVariantsRecord<keyof Variants, string>Default variant values
options.compoundVariantsCompoundVariant[]Custom compound variant definitions
options.filterRecord<string, string[]>Limit which variant values are generated

Variants:

VariantOptionsDefault
colorprimary, light, dark, neutralneutral
variantsolid, softsoft
shapecircle, squarecircle
sizexs, sm, md, lg, xlmd

useAvatarBadgeRecipe(s, options?)

Creates the status badge recipe, positioned absolutely at the bottom-right of an avatar.

Variants:

VariantOptionsDefault
colorprimary, secondary, success, info, warning, error, light, dark, neutralsuccess
sizexs, sm, md, lg, xlmd
positiontop-left, top-right, bottom-left, bottom-rightbottom-right

Learn more about recipes ->

Best Practices

  • Always set alt on avatar images that represent a person or entity.
  • Match the badge size to the avatar size so the status dot scales proportionally.
  • Use neutral + soft for general-purpose initials; reserve primary/solid for emphasis.
  • Keep initials short (1–2 characters) so they stay legible at small sizes.
  • Filter what you don't need: Pass a filter option to reduce generated CSS.

FAQ