Avatar Circle

Animated circular progress ring for avatars, profile pictures or any circular content.

Preview

Browse the example variants of AvatarCircle component below and also you can see code of each previews in the below 'Examples' section.

AP

1. Wrapping initials (no image at all)

Installation

1. Run the following command in your terminal:
npx shadcn@latest add https://refinery.abhii.me/r/avatar-circle.json

API Reference

Component props
NameTypeDescription
childrenReactNodeContent to be wrapped by the avatar circle (e.g., an image or initials div). Anything circular works.
size"xs" | "sm" | "md" | "lg" | "xl"Drives the wrapper dimensions and SVG ring geometry. Override with `className` + explicit w-/h- if you need a custom size.
strokeColorstringAccepts any CSS color string to set the color of the animated ring.
strokeWidthnumberWidth of the animated ring in pixels.
durationnumberDuration of a full draw/erase cycle in seconds.
easeEasing | Easing[]Easing function(s) for the animation. Can be a single easing or an array for keyframe easing.
showTrackbooleanWhether to show a faint ghost track behind the ring (the full circle at low opacity).
lineCap"butt" | "round" | "square"Stroke-linecap for the animated ring. 'round' (default) gives a tapered tip, 'butt' gives a hard edge, and 'square' extends the line slightly beyond the endpoint.
classNamestringAdditional CSS classes to apply to the wrapper for custom styling.

Examples

Below are usage code examples of different variant usecases shown above in the preview section.

1

Wrapping Initials -

A simple variant wrapping text initials. No image needed at all - works just as well with initials or an icon.

default-initials.tsx
import { AvatarCircle } from "@/components/avatar-circle";

export default function AvatarCircleExample1() {
  return (
    <AvatarCircle
      size="sm"
      strokeColor="currentColor"
      className="text-neutral-600 dark:text-neutral-400"
    >
      <div className="flex size-full items-center justify-center rounded-full bg-neutral-200 text-sm font-medium text-neutral-700 dark:bg-neutral-700 dark:text-neutral-200">
        AP
      </div>
    </AvatarCircle>
  );
}
2

Image Avatar -

Convenience AvatarCircleImage component that handles the img element and fallback logic for you.

default-img.tsx
import { AvatarCircleImage } from "@/components/avatar-circle";

export default function AvatarCircleExample2() {
  return (
    <AvatarCircleImage
      src="https://res.cloudinary.com/dbglon4f7/image/upload/v1772550894/sample.jpg"
      alt="Jordan"
      size="lg"
      showTrack={false}
      duration={0.5}
    />
  );
}
3

Custom Colors and Size. -

Dark background, white ring, no ghost track, smaller size & use of a fallback initials string when image fails to load.

fallback-initials.tsx
import { AvatarCircleImage } from "@/components/avatar-circle";

export default function AvatarCircleExample3() {
  return (
    <AvatarCircleImage
      src="https://res.cloudinary.com/dbglon4f7/image/upload/v1772550894/sample.jpg"
      alt="Alex Chen"
      fallback="AC"
      size="md"
    />
  );
}
4

Custom Easing -

Slow, dramatic draw with custom easing [0.16, 1, 0.3, 1] and 'butt' line cap for a hard edge, instead of the default tapered tip

custom-easing.tsx
import { AvatarCircleImage } from "@/components/avatar-circle";

export default function AvatarCircleExample4() {
  return (
    <AvatarCircleImage
      src="https://res.cloudinary.com/dbglon4f7/image/upload/v1772550894/sample.jpg"
      alt="Profile"
      size="xl"
      strokeColor="currentColor"
      strokeWidth={1}
      duration={1.2}
      ease={[0.16, 1, 0.3, 1]}
      lineCap="butt"
    />
  );
}
Design Notes

I used an SVG circle for the ring and animate strokeDashoffset to create the looping draw-and-erase effect. The component calculates the radius and circumference from the chosen size and stroke width, so the ring stays aligned around the content. You can turn on showTrack for a faint background circle, adjust duration and easing, or change the stroke color, width, and line cap to match your avatar treatment.