Avatar Circle
refinery/avatar-circleFreeComponent
Animated circular progress ring for avatars, profile pictures or any circular content.
Live preview
live · rendered by the registry
Rendered by refinery on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://refinery.abhii.me/r/avatar-circle.jsonSource
1"use client";23import { motion, type Easing } from "motion/react";4import { useState } from "react";5import { cn } from "@/lib/utils";67type AvatarSize = "xs" | "sm" | "md" | "lg" | "xl";89export interface AvatarCircleProps {10 children?: React.ReactNode;11 size?: AvatarSize;12 strokeColor?: string;13 strokeWidth?: number;14 duration?: number;15 ease?: Easing | Easing[];16 showTrack?: boolean;17 lineCap?: "butt" | "round" | "square";18 className?: string;19}2021const sizeMap: Record<AvatarSize, { wrapper: string; px: number }> = {22 xs: { wrapper: "size-8", px: 32 },23 sm: { wrapper: "size-12", px: 48 },24 md: { wrapper: "size-16", px: 64 },25 lg: { wrapper: "size-24", px: 96 },26 xl: { wrapper: "size-32", px: 128 },27};2829// Ring sits slightly outside the avatar's edge for visual breathing room30const RING_OFFSET = 2;3132export function AvatarCircle({33 children,34 size = "md",35 strokeColor = "currentColor",36 strokeWidth = 1.5,37 duration = 0.6,38 ease = "easeInOut",39 showTrack = true,40 lineCap = "round",41 className,42}: AvatarCircleProps) {43 const { px } = sizeMap[size];4445 const half = px / 2;46 const radius = half - strokeWidth / 2 + RING_OFFSET;47 const circumference = 2 * Math.PI * radius;4849 return (50 <motion.div51 tabIndex={0}52 className={cn(53 "relative inline-flex cursor-pointer items-center justify-center rounded-full focus:outline-none",54 sizeMap[size].wrapper,55 className56 )}57 initial="rest"58 whileHover="active"59 whileFocus="active"60 >61 <div className="relative z-10 size-full overflow-hidden rounded-full">62 {children}63 </div>6465 <svg66 className="pointer-events-none absolute inset-0 z-50 size-full"67 viewBox={`0 0 ${px} ${px}`}68 aria-hidden="true"69 style={{ overflow: "visible" }}70 >71 {showTrack && (72 <circle73 cx={half}74 cy={half}75 r={radius}76 fill="none"77 stroke={strokeColor}78 strokeWidth={strokeWidth}79 opacity={0.12}80 transform={`rotate(-90 ${half} ${half})`}81 />82 )}8384 {/* Animated ring - draws clockwise on hover or keyboard focus */}85 <motion.circle86 cx={half}87 cy={half}88 r={radius}89 fill="none"90 stroke={strokeColor}91 strokeWidth={strokeWidth}92 strokeLinecap={lineCap}93 strokeDasharray={circumference}94 variants={{95// … truncated
What it pulls in
npm packages
Files it writes
More from refinery
All 16 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Analog Clock Screensaveranalog-clock-screensaver | refinery | Components | Free | 1 dep | |
| DVD Screensaverdvd-screensaver | refinery | Components | Free | 1 dep | |
| Floating Cardfloating-card | refinery | Components | Free | 1 dep | |
| Floating Navfloating-nav | refinery | Components | Free | 1 dep | |
| Glowy Buttonglowy-button | refinery | Components | Free | 1 dep | |
| Move To Topmove-to-top-button | refinery | Components | Free | 1 dep | |
| Notification Badgenotification-badge | refinery | Components | Free | 1 dep | |
| Sleeping Cat Screensaversleeping-cat-screensaver | refinery | Components | Free | 2 deps |
