{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "avatar", "type": "registry:ui", "title": "Avatar", "description": "An avatar component that can be used to display user profile pictures.", "files": [ { "path": "registry/tra-kit/components/avatar.tsx", "content": "import { cva } from 'class-variance-authority';\r\nimport React, { useState } from 'react';\r\nimport { UserIcon, XIcon } from '@phosphor-icons/react';\r\nimport { cn } from '@/lib/utils';\r\n\r\nconst avatarVariants = cva(\r\n 'bg-primary-15 text-primary relative flex w-fit items-center justify-center transition',\r\n {\r\n variants: {\r\n variant: {\r\n circular: 'rounded-full',\r\n rounded: 'rounded-lg',\r\n },\r\n size: {\r\n sm: 'aspect-square size-12 text-lg',\r\n default: 'aspect-square size-20 min-h-20 min-w-20 text-3xl',\r\n lg: 'aspect-square size-52 min-h-52 min-w-52 text-6xl',\r\n },\r\n },\r\n defaultVariants: {\r\n variant: 'circular',\r\n size: 'default',\r\n },\r\n },\r\n);\r\n\r\nconst avatarIconVariants = cva('', {\r\n variants: {\r\n size: {\r\n sm: 'size-5',\r\n default: 'size-9',\r\n lg: 'size-20',\r\n },\r\n },\r\n defaultVariants: {\r\n size: 'default',\r\n },\r\n});\r\nconst imageVariants = cva('h-max-full w-full object-fill', {\r\n variants: {\r\n variant: {\r\n circular: 'rounded-full',\r\n rounded: 'rounded-lg',\r\n },\r\n },\r\n defaultVariants: {\r\n variant: 'circular',\r\n },\r\n});\r\n\r\nconst badgeVariants = cva('absolute', {\r\n variants: {\r\n badgePosition: {\r\n 'top-left': 'left-0 top-0',\r\n 'top-right': 'right-0 top-0',\r\n 'bottom-left': 'bottom-0 left-0',\r\n 'bottom-right': 'bottom-0 right-0',\r\n },\r\n variant: {\r\n circular: '',\r\n rounded: '',\r\n },\r\n size: {\r\n sm: '',\r\n lg: '',\r\n },\r\n },\r\n defaultVariants: {\r\n badgePosition: 'top-right',\r\n variant: 'circular',\r\n size: 'lg',\r\n },\r\n compoundVariants: [\r\n {\r\n badgePosition: 'top-left',\r\n variant: 'circular',\r\n size: 'lg',\r\n className: 'left-8 top-8 -translate-x-full -translate-y-1/2 transform',\r\n },\r\n {\r\n badgePosition: 'top-right',\r\n variant: 'circular',\r\n size: 'lg',\r\n className: 'right-8 top-8 -translate-y-1/2 translate-x-full transform',\r\n },\r\n {\r\n badgePosition: 'bottom-left',\r\n variant: 'circular',\r\n size: 'lg',\r\n className: 'bottom-8 left-8 -translate-x-full translate-y-1/2 transform',\r\n },\r\n {\r\n badgePosition: 'bottom-right',\r\n variant: 'circular',\r\n size: 'lg',\r\n className: 'bottom-8 right-8 translate-x-full translate-y-1/2 transform',\r\n },\r\n {\r\n badgePosition: 'top-left',\r\n variant: 'rounded',\r\n size: 'lg',\r\n className: '-left-2 -top-2',\r\n },\r\n {\r\n badgePosition: 'top-right',\r\n variant: 'rounded',\r\n size: 'lg',\r\n className: '-right-2 -top-2',\r\n },\r\n {\r\n badgePosition: 'bottom-left',\r\n variant: 'rounded',\r\n size: 'lg',\r\n className: '-bottom-2 -left-2',\r\n },\r\n {\r\n badgePosition: 'bottom-right',\r\n variant: 'rounded',\r\n size: 'lg',\r\n className: '-bottom-2 -right-2',\r\n },\r\n {\r\n badgePosition: 'top-left',\r\n variant: 'rounded',\r\n size: 'sm',\r\n className: '-left-1 -top-1',\r\n },\r\n {\r\n badgePosition: 'top-right',\r\n variant: 'rounded',\r\n size: 'sm',\r\n className: '-right-1 -top-1',\r\n },\r\n {\r\n badgePosition: 'bottom-left',\r\n variant: 'rounded',\r\n size: 'sm',\r\n className: '-bottom-1 -left-1',\r\n },\r\n {\r\n badgePosition: 'bottom-right',\r\n variant: 'rounded',\r\n size: 'sm',\r\n className: '-bottom-1 -right-1',\r\n },\r\n ],\r\n});\r\n\r\ninterface IAvatar {\r\n asChild?: React.ElementType;\r\n badgeClassName?: string;\r\n badgeContent?: React.ReactNode;\r\n badgePosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\r\n className?: string;\r\n href?: string;\r\n icon?: React.ReactNode;\r\n imageClassName?: string;\r\n onClick?: () => void;\r\n size?: 'sm' | 'lg';\r\n src?: string;\r\n title?: string;\r\n variant?: 'circular' | 'rounded';\r\n}\r\n\r\ntype PolymorphicAvatarProps = IAvatar & {\r\n asChild?: C;\r\n} & Omit, keyof IAvatar>;\r\n\r\ninterface IMultipleAvatarContainer {\r\n children: React.ReactNode[];\r\n lastElementSize?: 'sm' | 'lg';\r\n showLessAvatarClassName?: string;\r\n showMoreAvatarClassName?: string;\r\n childrenClassName?: string;\r\n}\r\n\r\nconst Avatar = React.forwardRef(function (\r\n props: PolymorphicAvatarProps,\r\n ref: React.Ref,\r\n) {\r\n const {\r\n asChild,\r\n badgeClassName,\r\n badgeContent,\r\n badgePosition = 'top-right',\r\n className,\r\n href,\r\n icon,\r\n imageClassName,\r\n onClick,\r\n size,\r\n src,\r\n title,\r\n variant,\r\n ...otherProps\r\n } = props as PolymorphicAvatarProps;\r\n\r\n const Comp = (asChild ?? 'div') as React.ElementType;\r\n return (\r\n \r\n {src ? (\r\n \r\n ) : !src && title && !icon ? (\r\n

\r\n {title\r\n .split(' ')\r\n .map((item) => item[0])\r\n .join('')}\r\n

\r\n ) : !src && !title && icon ? (\r\n {icon}\r\n ) : (\r\n \r\n )}\r\n {badgeContent && (\r\n
\r\n {badgeContent}\r\n
\r\n )}\r\n \r\n );\r\n}) as unknown as (\r\n props: PolymorphicAvatarProps & { ref?: React.Ref },\r\n) => React.ReactElement;\r\n\r\nconst showMoreAvatarVariants = cva('border-neutral-black relative');\r\n\r\nconst showLessAvatarVariants = cva('bg-primary/50 text-white hover:brightness-125');\r\n\r\nconst MultipleAvatarContainer: React.FC = ({\r\n children,\r\n lastElementSize = 'sm',\r\n showLessAvatarClassName,\r\n showMoreAvatarClassName,\r\n childrenClassName,\r\n}) => {\r\n const [showAllAvatars, setShowAllAvatars] = useState(false);\r\n const maxVisibleAvatars = 4;\r\n const remainingAvatars = React.Children.count(children) - maxVisibleAvatars;\r\n\r\n const handleShowAllAvatars = () => {\r\n setShowAllAvatars(true);\r\n };\r\n\r\n const handleHideAllAvatars = () => {\r\n setShowAllAvatars(false);\r\n };\r\n\r\n const enhanceChild = (child: React.ReactNode, extraClass?: string) => {\r\n if (!extraClass) return child;\r\n if (React.isValidElement(child)) {\r\n const existing = (child.props && (child.props as { className?: string }).className) || '';\r\n return React.cloneElement(child, {\r\n className: cn(existing, extraClass, childrenClassName),\r\n } as Partial);\r\n }\r\n return child;\r\n };\r\n\r\n return (\r\n
\r\n {React.Children.toArray(children)\r\n .slice(0, showAllAvatars ? undefined : maxVisibleAvatars)\r\n .map((child, index) => {\r\n const enhanced = enhanceChild(child, 'border border-2 border-neutral-black/75');\r\n return (\r\n \r\n {enhanced}\r\n
\r\n );\r\n })}\r\n {!showAllAvatars && remainingAvatars > 0 && (\r\n \r\n \r\n \r\n )}\r\n {showAllAvatars && (\r\n \r\n }\r\n />\r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nexport { Avatar, MultipleAvatarContainer };\r\n", "type": "registry:ui" } ] }