You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 1.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. 'use client'
  2. import { useState } from 'react'
  3. import cn from '@/utils/classnames'
  4. export type AvatarProps = {
  5. name: string
  6. avatar: string | null
  7. size?: number
  8. className?: string
  9. textClassName?: string
  10. onError?: (x: boolean) => void
  11. }
  12. const Avatar = ({
  13. name,
  14. avatar,
  15. size = 30,
  16. className,
  17. textClassName,
  18. onError,
  19. }: AvatarProps) => {
  20. const avatarClassName = 'shrink-0 flex items-center rounded-full bg-primary-600'
  21. const style = { width: `${size}px`, height: `${size}px`, fontSize: `${size}px`, lineHeight: `${size}px` }
  22. const [imgError, setImgError] = useState(false)
  23. const handleError = () => {
  24. setImgError(true)
  25. onError?.(true)
  26. }
  27. if (avatar && !imgError) {
  28. return (
  29. <img
  30. className={cn(avatarClassName, className)}
  31. style={style}
  32. alt={name}
  33. src={avatar}
  34. onError={handleError}
  35. onLoad={() => onError?.(false)}
  36. />
  37. )
  38. }
  39. return (
  40. <div
  41. className={cn(avatarClassName, className)}
  42. style={style}
  43. >
  44. <div
  45. className={cn(textClassName, 'scale-[0.4] text-center text-white')}
  46. style={style}
  47. >
  48. {name && name[0].toLocaleUpperCase()}
  49. </div>
  50. </div>
  51. )
  52. }
  53. export default Avatar