88 lines
2.0 KiB
Plaintext
88 lines
2.0 KiB
Plaintext
---
|
|
import { tv, type VariantProps } from 'tailwind-variants'
|
|
|
|
import { getSizePxFromTailwindClasses } from '../lib/tailwind'
|
|
|
|
import MyPicture from './MyPicture.astro'
|
|
|
|
import type { Prisma } from '@prisma/client'
|
|
import type { HTMLAttributes } from 'astro/types'
|
|
import type { O } from 'ts-toolbelt'
|
|
|
|
const userBadge = tv({
|
|
slots: {
|
|
base: 'group/user-badge font-title inline-flex max-w-full items-center gap-1 overflow-hidden font-medium',
|
|
image: 'inline-block rounded-full object-cover',
|
|
text: 'truncate',
|
|
},
|
|
variants: {
|
|
size: {
|
|
sm: {
|
|
base: 'gap-1 text-xs',
|
|
image: 'size-4',
|
|
},
|
|
md: {
|
|
base: 'gap-2 text-sm',
|
|
image: 'size-5',
|
|
},
|
|
lg: {
|
|
base: 'gap-2 text-base',
|
|
image: 'size-6',
|
|
},
|
|
},
|
|
noLink: {
|
|
true: {
|
|
text: 'cursor-default',
|
|
},
|
|
false: {
|
|
base: 'cursor-pointer',
|
|
text: 'group-hover/user-badge:underline',
|
|
},
|
|
},
|
|
},
|
|
defaultVariants: {
|
|
size: 'sm',
|
|
noLink: false,
|
|
},
|
|
})
|
|
|
|
type Props = O.Optional<HTMLAttributes<'a'>, 'href'> &
|
|
VariantProps<typeof userBadge> & {
|
|
user: Prisma.UserGetPayload<{
|
|
select: {
|
|
name: true
|
|
displayName: true
|
|
picture: true
|
|
}
|
|
}>
|
|
classNames?: {
|
|
image?: string
|
|
text?: string
|
|
}
|
|
children?: never
|
|
}
|
|
|
|
const { user, href, class: className, size = 'sm', classNames, noLink = false, ...htmlProps } = Astro.props
|
|
const { base, image, text } = userBadge({ size, noLink })
|
|
|
|
const imageClassName = image({ class: classNames?.image })
|
|
const imageSizePx = getSizePxFromTailwindClasses(imageClassName, 16)
|
|
|
|
const Tag = noLink ? 'span' : 'a'
|
|
---
|
|
|
|
<Tag
|
|
href={Tag === 'a' ? (href ?? `/u/${user.name}`) : undefined}
|
|
class={base({ class: className })}
|
|
{...htmlProps}
|
|
>
|
|
{
|
|
!!user.picture && (
|
|
<MyPicture src={user.picture} height={imageSizePx} width={imageSizePx} class={imageClassName} alt="" />
|
|
)
|
|
}
|
|
<span class={text({ class: classNames?.text })}>
|
|
{user.displayName ?? user.name}
|
|
</span>
|
|
</Tag>
|