RoadieRoadie
  • Home
  • Foundations
  • Tokens
  • Components
  • Charts
  • Widgets
  • Appearance
HomeFoundationsComponents
Appearance

Components

  • Navigation

    • Breadcrumb
    • Navigator
    • Steps
    • Tabs
  • Layout

    • Pane
    • ScrollArea
    • Separator
  • Actions

    • Button
    • IconButton
    • Toggle
    • Toggle group
  • Forms

    • Forms overview
    • Autocomplete
    • Checkbox
    • Combobox
    • Field
    • Fieldset
    • Input
    • Label
    • Number field
    • OTP field
    • Radio group
    • Select
    • Slider
    • Switch
    • Textarea
  • Overlays

    • Dialog
    • Drawer
    • Menu
    • Popover
    • Toast
    • Tooltip
  • Collections

    • Accordion
    • Card
    • Carousel
    • Collapsible
    • DataTable
    • List
    • Marquee
    • Table
  • Status

    • Badge
    • Callout
    • Countdown
    • Empty state
    • Meter
    • Progress
    • Skeleton
    • Sparkline
    • StatTile
  • Media & brand

    • Avatar
    • Icon Tile
    • Image
    • Logo
    • QR code
    • SpotIllustration
  • Text

    • CalendarTile
    • Code
    • DateTime
    • Duration
    • Highlight
    • Mark
    • Prose

Avatar

A person's photo, with their initials or an icon when there is no photo.

Import

import { Avatar } from '@oztix/roadie-components/avatar'

Examples

Default

Pass src and name. The initials from name show until the photo loads, and stay if it never does.

<Avatar
  src='/roadie-logo.png'
  name='Mia Tran'
/>

Sizes

Sizes run xs to xl and match IconTile, so the two line up in a row. Initials and the icon scale with the box, so a custom size-* class works too.

<div className='flex flex-wrap items-center gap-3'>
  <Avatar size='xs' name='Mia Tran' />
  <Avatar size='sm' name='Mia Tran' />
  <Avatar size='md' name='Mia Tran' />
  <Avatar size='lg' name='Mia Tran' />
  <Avatar size='xl' name='Mia Tran' />
</div>

Shape

Avatars are circles by default. Use shape='square' for an organisation or a team rather than a person. The corner radius grows with the size.

<div className='flex flex-wrap items-center gap-3'>
  <Avatar shape='square' size='sm' name='Harbour Sound' />
  <Avatar shape='square' size='md' name='Harbour Sound' />
  <Avatar shape='square' size='lg' name='Harbour Sound' />
  <Avatar shape='square' size='xl' name='Harbour Sound' />
</div>

Intents

The fallback uses the subtle emphasis of the surrounding intent. Set intent to colour one avatar.

<div className='flex flex-wrap items-center gap-3'>
  <Avatar name='Mia Tran' />
  <Avatar name='Mia Tran' intent='accent' />
  <Avatar name='Mia Tran' intent='brand' />
  <Avatar name='Mia Tran' intent='success' />
  <Avatar name='Mia Tran' intent='warning' />
</div>

Fallback

Without a photo, the avatar shows initials from the first and last words of name. Without a name, it shows a user icon. A photo that fails to load is hidden, so the fallback shows instead of a broken image.

<div className='flex flex-wrap items-end gap-6'>
  <div className='grid justify-items-center gap-2'>
    <Avatar name='Leo van der Park' />
    <p className='text-sm text-subtle'>Initials</p>
  </div>
  <div className='grid justify-items-center gap-2'>
    <Avatar />
    <p className='text-sm text-subtle'>No name</p>
  </div>
  <div className='grid justify-items-center gap-2'>
    <Avatar src='/missing-avatar.png' name='Ada Nguyen' />
    <p className='text-sm text-subtle'>Photo failed</p>
  </div>
</div>

Composition

Compose Avatar.Fallback and Avatar.Image yourself for custom fallback content. Put the fallback first so the photo paints over it. Give the fallback role='img' and an aria-label so it names the person until the photo loads.

<Avatar size='lg'>
  <Avatar.Fallback role='img' aria-label='Mia Tran'>
    MT
  </Avatar.Fallback>
  <Avatar.Image
    src='/roadie-logo.png'
    alt='Mia Tran'
  />
</Avatar>

With Image

Avatar.Image stays mounted while it loads, so loading='lazy' works and it can render through Roadie's Image. Oztix CDN photos then get a resized srcSet.

<Avatar>
<Avatar.Fallback role='img' aria-label='Mia Tran'>
MT
</Avatar.Fallback>
<Avatar.Image render={<Image src={photoUrl} alt='Mia Tran' width={40} />} />
</Avatar>

Group

Avatar.Group overlaps its avatars and rings each one in the page colour. It sets the size and shape for every avatar inside it. End the row with Avatar.GroupCount for the people you don't show. Give the group an aria-label.

<div className='flex items-center gap-3'>
  <Avatar.Group size='sm' aria-label='Going'>
    <Avatar
      src='/roadie-logo.png'
      name='Sam Okafor'
    />
    <Avatar name='Priya Shah' />
    <Avatar name='Leo Park' />
    <Avatar.GroupCount count={12} />
  </Avatar.Group>
  <p className='text-sm text-subtle'>15 friends are going</p>
</div>

On a surface other than the page, set --avatar-ring to that surface so the rings still read as gaps.

<div className='grid emphasis-raised rounded-xl p-4'>
  <Avatar.Group aria-label='Crew' className='[--avatar-ring:var(--intent-bg-raised)]'>
    <Avatar name='Sam Okafor' />
    <Avatar name='Priya Shah' />
    <Avatar name='Leo Park' />
    <Avatar.GroupCount count={4} />
  </Avatar.Group>
</div>

User account

Show who is signed in. The name is written beside the avatar, so pass alt='' to keep screen readers from reading it twice.

<div className='flex items-center gap-3'>
  <Avatar
    size='lg'
    src='/roadie-logo.png'
    name='Mia Tran'
    alt=''
  />
  <div className='grid flex-1 gap-0.5'>
    <p className='font-semibold text-strong'>Mia Tran</p>
    <p className='text-sm text-subtle'>mia.tran@example.com</p>
  </div>
  <Button size='sm'>Manage account</Button>
</div>

Team members

Avatars fit a List row's leading slot. The row title names the person, so the avatar is decorative.

<List contained>
  <List.Item
    title='Mia Tran'
    description='Owner'
    leading={
      <Avatar
        src='/roadie-logo.png'
        name='Mia Tran'
        alt=''
      />
    }
  />
  <List.Item
    title='Sam Okafor'
    description='Box office'
    leading={
      <Avatar name='Sam Okafor' alt='' />
    }
  />
  <List.Item
    title='Leo van der Park'
    description='Invite sent'
    leading={<Avatar name='Leo van der Park' alt='' />}
    trailing={<Badge size='sm'>Pending</Badge>}
  />
</List>

Guidelines

Always pass a name

<Avatar src={user.photo} name={user.name} />

Do

Pass name even with a photo. It gives the fallback its initials and the avatar its accessible name.

<Avatar src={user.photo} />

Don’t

Don't rely on the photo alone. If it fails, everyone gets the same icon.

Use Avatar for people, IconTile for things

Do

Use an avatar for a person, or a square one for an organisation with a logo or initials.

Don’t

Don't use an avatar to frame an icon for a setting or a category. Use IconTile.

Accessibility

  • With name or alt, the avatar is announced as an image with that name, whether it shows the photo or the initials.
  • Pass alt='' when the name is already visible beside the avatar. The avatar is then hidden from screen readers.
  • Avatar.GroupCount is announced as "12 more". Pass aria-label to say more, for example "12 more people going".
  • An avatar isn't interactive. To make one a link or a button, wrap it in one and give that the name.

API reference

Avatar

Base UI
classNamestring | ((state: AvatarRootState) => string)

CSS class applied to the element, or a function that returns a class based on the component's state.

size"xs" | "sm" | "md" | "lg" | "xl"

Inherits from `Avatar.Group`, else `md`.

shape"circle" | "square"

Inherits from `Avatar.Group`, else `circle`.

intent"neutral" | "brand" | "brand-secondary" | "accent" | "danger" | "success" | "warning" | "info"

Colours the fallback; inherits from context when unset.

srcstring

Image URL. Used when there are no children.

namestring

Person's name. Gives the fallback its initials and the avatar its name.

altstring

Accessible name, over `name`. Pass `''` when the name is already beside it.

Avatar.Fallback

Base UI
classNamestring | ((state: AvatarFallbackState) => string)

CSS class applied to the element, or a function that returns a class based on the component's state.

Inherited from AvatarFallbackProps

delaynumber

How long to wait before showing the fallback. Specified in milliseconds.

Defaults to 0.

Avatar.Group

Set `--avatar-ring` to the surface behind the group when it isn't the page.

size"xs" | "sm" | "md" | "lg" | "xl"

Size of every avatar in the group.

Defaults to md.

shape"circle" | "square"

Shape of every avatar in the group.

Defaults to 'circle'.

Avatar.GroupCount

The last item in an `Avatar.Group`. Announced as "N more" unless `aria-label` says otherwise.

countnumber
Required

How many people the group doesn't show. Renders as `+N`.

size"xs" | "sm" | "md" | "lg" | "xl"

Inherits from `Avatar.Group`, else `md`.

shape"circle" | "square"

Inherits from `Avatar.Group`, else `circle`.

intent"neutral" | "brand" | "brand-secondary" | "accent" | "danger" | "success" | "warning" | "info"

Avatar.Image

Base UI

Stays mounted so the image is in server HTML and `loading='lazy'` works; it stays hidden over the fallback until it loads.

classNamestring | ((state: AvatarImageState) => string)

CSS class applied to the element, or a function that returns a class based on the component's state.

Inherited from AvatarImageProps

onLoadingStatusChange((status: ImageLoadingStatus) => void)

Callback fired when the loading status changes.

keepMountedboolean

Whether the image element stays mounted and loads in place instead of being preloaded. Supports `loading="lazy"` and optimized image components such as `next/image`.

Defaults to true.

Previous page← SkeletonNext pageIcon Tile →