RepostDescription.tsx raw

   1  import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'
   2  import { cn } from '@/lib/utils'
   3  import { Repeat2 } from 'lucide-react'
   4  import { useTranslation } from 'react-i18next'
   5  import UserAvatar from '../UserAvatar'
   6  import Username from '../Username'
   7  
   8  /**
   9   * - reposters.length === 1: show "Alice reposted"
  10   * - reposters.length === 2: show "Alice, Bob reposted"
  11   * - reposters.length === 3: show "Alice, Bob, Charlie reposted"
  12   * - reposters.length > 3: show "Alice, Bob, and x others reposted" (with hover card showing avatars of others)
  13   */
  14  export default function RepostDescription({
  15    reposters,
  16    className
  17  }: {
  18    reposters?: string[]
  19    className?: string
  20  }) {
  21    const { t } = useTranslation()
  22    if (!reposters?.length) return null
  23  
  24    return (
  25      <div className={cn('flex gap-1 text-sm items-center text-muted-foreground mb-1', className)}>
  26        <Repeat2 size={16} className="shrink-0" />
  27        <Username
  28          key={reposters[0]}
  29          userId={reposters[0]}
  30          className={cn('font-semibold truncate', reposters.length > 1 && 'after:content-[","]')}
  31          skeletonClassName="h-3"
  32        />
  33        {reposters.length > 1 && (
  34          <Username
  35            key={reposters[1]}
  36            userId={reposters[1]}
  37            className={cn('font-semibold truncate', reposters.length === 3 && 'after:content-[","]')}
  38            skeletonClassName="h-3"
  39          />
  40        )}
  41        {reposters.length > 3 ? (
  42          <AndXOthers reposters={reposters.slice(2)} />
  43        ) : reposters.length === 3 ? (
  44          <Username
  45            key={reposters[2]}
  46            userId={reposters[2]}
  47            className={cn('font-semibold truncate')}
  48            skeletonClassName="h-3"
  49          />
  50        ) : null}
  51        <div className="shrink-0">{t('reposted')}</div>
  52      </div>
  53    )
  54  }
  55  
  56  function AndXOthers({ reposters }: { reposters: string[] }) {
  57    const { t } = useTranslation()
  58  
  59    return (
  60      <HoverCard>
  61        <HoverCardTrigger asChild>
  62          <span className="shrink-0 hover:underline">
  63            {t('and {{x}} others', { x: reposters.length })}
  64          </span>
  65        </HoverCardTrigger>
  66        <HoverCardContent className="w-fit max-w-60 flex flex-wrap p-2">
  67          {reposters.map((pubkey) => (
  68            <div key={pubkey} className="p-2">
  69              <UserAvatar key={pubkey} userId={pubkey} size="small" />
  70            </div>
  71          ))}
  72        </HoverCardContent>
  73      </HoverCard>
  74    )
  75  }
  76