Avatar
A circular identity mark for a person, account, or brand, with resilient image fallbacks.
Implementation previewEvery example. In one place.
Explore every named example, including states, compositions, and theme variants.
Example source
packages/design-system/src/components/primitives/Avatar/Avatar.stories.tsxExport PlaygroundImplementation preview Local Storybook build 0.2.0-preview.1. Source specification status does not approve this runtime.
Stories + source JSON ↗Local specification source status: preview. Implementation preview pending sign-off.
A circular identity mark for a person, account, or brand, with resilient image fallbacks.
Implementation API 1 entry point · source-derived preview
Read the actual callable API and preserve its composition constraints. Each union branch is a complete alternative; props marked forbidden cannot be supplied.
import { Avatar } from '@cloakedinc/design-system';AvatarAvatarProps
packages/design-system/src/components/primitives/Avatar/Avatar.tsx:69
| Prop | Type | Presence | Notes |
|---|---|---|---|
type | AvatarType | Required | Which avatar is rendered. `brand` insets the mark and contains it inside the circle; `image` crops to fill. `icon` and `initials` take `icon`/`initial` instead of `src`. |
size | AvatarSize | Required | Named size, mapped to the sizing token scale. |
icon | React.ReactNode | Optional | Rendered as-is for `type='icon'`. The avatar sets no size on it, so size the node yourself. |
initial | string | undefined | Optional | Initials text for `type='initials'`, and what a `brand`/`image` avatar renders once no source can be shown — omit it and those render nothing. Uppercased by CSS. |
color | string | undefined | Optional | Background color for initials avatars. |
initialTextColor | string | undefined | Optional | Initials text color. Defaults to `--cds-text-on-bold`. |
brandFrame | AvatarBrandFrame | undefined | Optional | Edge treatment for `brand` avatars. Use `none` only for a mark you ship and have looked at;
a runtime-resolved mark has an unknowable silhouette, so it keeps the ring.Source default: 'ring' |
src | string | undefined | Optional | Image source for `brand` and `image` avatars. |
fallbackSrc | string | undefined | Optional | Secondary image tried before initials when the primary source is unavailable. |
minImageNaturalWidth | number | undefined | Optional | Minimum loaded image dimension before falling back to initials. |
fallbackMinImageNaturalWidth | number | undefined | Optional | Minimum loaded fallback image dimension before falling back to initials. |
maxImageAspectRatio | number | undefined | Optional | Maximum loaded image aspect ratio (longer / shorter side) before falling back; rejects wide wordmarks. |
fallbackMaxImageAspectRatio | number | undefined | Optional | Maximum loaded fallback image aspect ratio before falling back to initials. |
alt | string | undefined | Optional | Accessible image description. |
ariaLabel | string | undefined | Optional | Accessible label for non-image avatars. |
className | string | undefined | Optional | Class hook for composite styling. Applied to the avatar root for every type. |
imageClassName | string | undefined | Optional | Class applied only to the `<img>` of `brand`/`image` avatars (never the initials fallback). |
style | React.CSSProperties | undefined | Optional | |
testId | string | undefined | Optional | Optional test selector. Applied to the avatar root, including a standing-in initials element. |
Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source.
Overview
A single identity mark for one person, account, or brand, rendered as an icon, initials,
a brand logo, or a photo. For several identities together use AvatarGroup.
Use when
Pick type for what the mark represents. brand/image fall back to initial when the
source fails or is rejected as too small or too wide (a wordmark).
size maps to the token scale: sm 24, md 40, lg 56, xl 80. Reach for IconTile
instead when the circle is a category affordance whose color carries meaning.
Loading
Brand and image sources shimmer, then fade in once resolved.
Usage by variant
| Choice | Use when | Avoid when |
|---|---|---|
Type: brand | A contained, padded, aspect-preserving company or service logo. The common case, resolved from brand assets. | A person — use initials or image. |
Type: initials | A monogram, used as the fallback when no logo or photo is available. color sets the circle background. | When a real logo or photo exists — show it. |
Type: icon | A glyph identity mark, for accounts represented by an icon rather than a logo. | A category tile whose tone carries meaning — use IconTile. |
Type: image | An edge-to-edge cover photo for a person. (No current app consumers.) | A logo — use brand, which pads and preserves aspect ratio. |
Component specification
$schema
../../../specs/component-spec.schema.jsonParts
- Id
- container
- Label
- Container
- Description
- Owns the circular crop, background role, and selected size.
- Id
- identity
- Label
- Identity content
- Description
- Shows an icon, initials, contained brand mark, or edge-to-edge image.
- Id
- placeholder
- Label
- Loading placeholder
- Description
- Shimmers while a brand or image source is loading.
Allowed Design Choices
- Variants
- Icon
- Label
- Icon
- Initials
- Label
- Initials
- Brand
- Label
- Brand
- Image
- Label
- Image
- Sizes
- Sm
- Label
- Small
- Md
- Label
- Medium
- Lg
- Label
- Large
- Xl
- Label
- Extra large
- Brand Frame
- Ring
- Label
- Ring
- Description
- Default. Hairline edge for a mark whose silhouette is unknown at author time.
- None
- Label
- None
- Description
- No edge, for a bundled mark whose own shape has been checked.
Variants
- Id
- icon
- Label
- Icon
- Description
- Centers a glyph when an account is represented by an icon rather than a logo.
- Platforms
- ios
- android
- web
- Id
- initials
- Label
- Initials
- Description
- Shows an uppercase monogram and serves as the final image fallback.
- Platforms
- ios
- android
- web
- Id
- brand
- Label
- Brand
- Description
- Contains a brand mark without cropping its aspect ratio.
- Platforms
- ios
- android
- web
- Id
- image
- Label
- Image
- Description
- Crops a person image edge to edge with cover behavior.
- Platforms
- ios
- android
- web
Sizes
- Id
- sm
- Label
- Small
- Description
- 24-unit compact identity mark.
- Id
- md
- Label
- Medium
- Description
- 40-unit default identity mark.
- Id
- lg
- Label
- Large
- Description
- 56-unit prominent identity mark.
- Id
- xl
- Label
- Extra large
- Description
- 80-unit hero identity mark.
Measurements
- Id
- sm-diameter
- Label
- Small diameter
- Kind
- exact
- Token
- --cds-size-24
- Value
- 24
- Unit
- px
- Applies To
- container
- sm
- Id
- md-diameter
- Label
- Medium diameter
- Kind
- exact
- Token
- --cds-size-40
- Value
- 40
- Unit
- px
- Applies To
- container
- md
- Id
- lg-diameter
- Label
- Large diameter
- Kind
- exact
- Token
- --cds-size-56
- Value
- 56
- Unit
- px
- Applies To
- container
- lg
- Id
- xl-diameter
- Label
- Extra-large diameter
- Kind
- exact
- Token
- --cds-size-80
- Value
- 80
- Unit
- px
- Applies To
- container
- xl
- Id
- brand-mark-inset
- Label
- Brand mark inset
- Kind
- exact
- Value
- 12
- Unit
- %
- Applies To
- identity
- brand
- Notes
- Proportional padding so the brand mark stays inside the circular clip. Empirically fit to live favicon-service/brandfetch assets, which carry some internal transparent margin: the measured LinkedIn/YouTube/Reddit marks lose up to ~12.2% of opaque pixels to the crop at 0% inset, and 12% takes all three to zero. It is not a geometric guarantee — a true edge-to-edge square with hard corners needs ~14.65%, since its corners sit 0.537x the diameter from center against a 0.5x radius.
- Id
- brand-ring-width
- Label
- Brand chip ring width
- Kind
- exact
- Token
- --cds-border-width-default
- Value
- 1
- Unit
- px
- Applies To
- container
- brand
- Notes
- Inset hairline ring on the brand chip, painted as
box-shadow: insetrather thanborderso it doesn't perturb the box model the avatar's fixed size and the brand mark's 12% inset both depend on. Brand marks arrive as a circular badge, a wide rounded rect, and a square with no shared silhouette; the ring gives every shape one consistent edge. Present by default and suppressed bybrandFrame='none', which is reserved for a bundled mark whose silhouette the author has checked — a runtime-resolved mark keeps the ring because its shape cannot be known.
Layout
- Alignment
- Identity content is centered. Person/cover images fill the circular crop edge to edge; brand marks are inset and contained, so they never reach the crop.
- Flow
- The avatar is an inline, non-shrinking circle.
- Notes
- Brand images use contain behavior with a 12% inset while person images use cover behavior edge to edge.
- The brand chip carries an inset hairline ring unless
brandFrame='none'; the image chip never does. - Initials scale with the selected diameter.
Typography And Color
- Typography
- Label
- Initials foundation
- Description
- Initials begin from the body-small ramp before scaling with the avatar diameter.
- Token
- --cds-type-body-small-size
- Colors
- Label
- Default initials container
- Description
- Uses the theme-aware bold fill unless a consumer supplies an identity color.
- Token
- --cds-bg-bold
- Label
- Default initials text
- Description
- Maintains contrast on the bold fill.
- Token
- --cds-text-on-bold
- Label
- Image surface
- Description
- Backs brand and image content while it loads.
- Token
- --cds-bg-surface
- Label
- Brand chip ring
- Description
- Hairline ring around the brand chip so mixed brand-mark silhouettes read as one consistent shape. Suppressed by
brandFrame='none'. - Token
- --cds-divider
States
- Id
- ready
- Label
- Ready
- Description
- Shows the chosen icon, initials, or loaded image.
- Id
- loading
- Label
- Loading
- Description
- Shows a circular shimmer while an image source resolves.
- Id
- fallback-image
- Label
- Fallback image
- Description
- Tries the secondary source when the primary source fails validation or loading.
- Id
- fallback-initials
- Label
- Fallback initials
- Description
- Shows initials when no acceptable image source remains.
Behavior
- Label
- Image validation
- Description
- Reject images that fall below configured natural-width or aspect-ratio limits.
- Label
- Fallback order
- Description
- Try the primary image, then fallback image, then initials when supplied.
Accessibility
- Label
- Images
- Description
- Use alt text for meaningful images and an empty alt value for decorative identity marks.
- Label
- Non-image marks
- Description
- Give icon avatars an accessible label; initials fall back to the visible monogram.
Content Adaptation
- Label
- Initials
- Description
- Keep monograms short enough to remain legible at the selected size.
- Label
- Brand assets
- Description
- Prefer compact marks over wide wordmarks; aspect-ratio validation may reject a wide source.
Motion Haptics
- Motion
- Label
- Image arrival
- Description
- Fade a loaded bitmap over the placeholder; remove the fade for reduced motion. Reveal a bitmap that was already decoded at mount outright — no placeholder, no fade — so a list of cached avatars does not animate content that was never absent. An image whose source was decoded earlier in the session still shows its placeholder until its own bitmap arrives, then skips the fade.
- Haptics
- Label
- No feedback
- Description
- Avatar is not interactive and does not request haptic feedback.