Components
Avatar

Avatar

A graphical representation of the user, often used in profile sections.

Usage

JD
import { Avatar, type AvatarProps } from '~/components/ui/avatar'

export const Demo = (props: AvatarProps) => {
  return <Avatar src="https://i.pravatar.cc/300" name="John Doe" {...props} />
}

Examples

Name Only

When only a name is supplied, the initials are displayed.

CS
<Avatar name="Christian Schröter" />

No User Data

Displays a default avatar in the absence of user data.

User Icon
<Avatar />

Installation

1

Add Component

Insert code snippet into your project. Update import paths as needed.

import { Avatar as ArkAvatar, type AvatarRootProps } from '@ark-ui/react/avatar'
import { forwardRef } from 'react'
import { css, cx } from 'styled-system/css'
import { splitCssProps } from 'styled-system/jsx'
import { avatar, type AvatarVariantProps } from 'styled-system/recipes'
import type { Assign, JsxStyleProps } from 'styled-system/types'

export interface AvatarProps extends Assign<JsxStyleProps, AvatarRootProps>, AvatarVariantProps {
  name?: string
  src?: string
}

export const Avatar = forwardRef<HTMLDivElement, AvatarProps>((props, ref) => {
  const [variantProps, avatarProps] = avatar.splitVariantProps(props)
  const [cssProps, localProps] = splitCssProps(avatarProps)
  const { name, src, className, ...rootProps } = localProps
  const styles = avatar(variantProps)

  return (
    <ArkAvatar.Root ref={ref} className={cx(styles.root, css(cssProps), className)} {...rootProps}>
      <ArkAvatar.Fallback className={styles.fallback}>
        {getInitials(name) || <UserIcon />}
      </ArkAvatar.Fallback>
      <ArkAvatar.Image className={styles.image} src={src} alt={name} />
    </ArkAvatar.Root>
  )
})

Avatar.displayName = 'Avatar'

const UserIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <title>User Icon</title>
    <path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" />
    <circle cx="12" cy="7" r="4" />
  </svg>
)

const getInitials = (name = '') =>
  name
    .split(' ')
    .map((part) => part[0])
    .splice(0, 2)
    .join('')
    .toUpperCase()
2

Add Recipe

This step is necessary only if you do not use any of the Park UI plugins.

import { avatarAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'

export const avatar = defineSlotRecipe({
  className: 'avatar',
  slots: avatarAnatomy.keys(),
  base: {
    root: {
      borderRadius: 'full',
      flexShrink: 0,
    },
    fallback: {
      alignItems: 'center',
      background: 'bg.subtle',
      borderRadius: 'full',
      borderWidth: '1px',
      color: 'fg.default',
      display: 'flex',
      fontWeight: 'semibold',
      height: 'inherit',
      justifyContent: 'center',
      _hidden: {
        display: 'none',
      },
    },
    image: {
      objectFit: 'cover',
    },
  },
  defaultVariants: {
    size: 'md',
  },
  variants: {
    size: {
      xs: {
        root: {
          height: '8',
          width: '8',
        },
        image: {
          height: '8',
          width: '8',
        },
        fallback: {
          textStyle: 'xs',
          '& svg': {
            width: '4',
            height: '4',
          },
        },
      },
      sm: {
        root: {
          height: '9',
          width: '9',
        },
        image: {
          height: '9',
          width: '9',
        },
        fallback: {
          textStyle: 'sm',
          '& svg': {
            width: '4',
            height: '4',
          },
        },
      },
      md: {
        root: {
          height: '10',
          width: '10',
        },
        image: {
          height: '10',
          width: '10',
        },
        fallback: {
          textStyle: 'md',
          '& svg': {
            width: '5',
            height: '5',
          },
        },
      },
      lg: {
        root: {
          height: '11',
          width: '11',
        },
        image: {
          height: '11',
          width: '11',
        },
        fallback: {
          textStyle: 'lg',
          '& svg': {
            width: '6',
            height: '6',
          },
        },
      },
      xl: {
        root: {
          height: '12',
          width: '12',
        },
        image: {
          height: '12',
          width: '12',
        },
        fallback: {
          textStyle: 'xl',
          '& svg': {
            width: '7',
            height: '7',
          },
        },
      },
      '2xl': {
        root: {
          height: '16',
          width: '16',
        },
        image: {
          height: '16',
          width: '16',
        },
        fallback: {
          textStyle: '2xl',
          '& svg': {
            width: '8',
            height: '8',
          },
        },
      },
    },
  },
})

Previous

Alert

Next

Badge