dify/web/app/components/base/user-avatar-list/index.tsx
Stephen Zhou a84c2d36a3
style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

86 lines
2.7 KiB
TypeScript

import type { AvatarSize } from '@langgenius/dify-ui/avatar'
import type { FC } from 'react'
import { AvatarFallback, AvatarImage, AvatarRoot } from '@langgenius/dify-ui/avatar'
import { useAtomValue } from 'jotai'
import { memo } from 'react'
import { getUserColor } from '@/app/components/workflow/collaboration/utils/user-color'
import { userProfileIdAtom } from '@/context/account-state'
type User = {
id: string
name: string
avatar_url?: string | null
}
type UserAvatarListProps = {
users: User[]
maxVisible?: number
size?: AvatarSize
className?: string
showCount?: boolean
}
const avatarSizeToPx: Record<AvatarSize, number> = {
xxs: 16,
xs: 20,
sm: 24,
md: 32,
lg: 36,
xl: 40,
'2xl': 48,
'3xl': 64,
}
export const UserAvatarList: FC<UserAvatarListProps> = memo(
({ users, maxVisible = 3, size = 'sm', className = '', showCount = true }) => {
const currentUserId = useAtomValue(userProfileIdAtom)
if (!users.length) return null
const shouldShowCount = showCount && users.length > maxVisible
const actualMaxVisible = shouldShowCount ? Math.max(1, maxVisible - 1) : maxVisible
const visibleUsers = users.slice(0, actualMaxVisible)
const remainingCount = users.length - actualMaxVisible
return (
<div className={`flex items-center -space-x-1 ${className}`}>
{visibleUsers.map((user, index) => {
const isCurrentUser = user.id === currentUserId
const userColor = isCurrentUser ? undefined : getUserColor(user.id)
return (
<div
key={`${user.id}-${index}`}
className="relative"
style={{ zIndex: visibleUsers.length - index }}
>
<AvatarRoot size={size} className="ring-2 ring-components-panel-bg">
{user.avatar_url && <AvatarImage src={user.avatar_url} alt={user.name} />}
<AvatarFallback
size={size}
style={userColor ? { backgroundColor: userColor } : undefined}
>
{user.name?.[0]?.toLocaleUpperCase()}
</AvatarFallback>
</AvatarRoot>
</div>
)
})}
{shouldShowCount && remainingCount > 0 && (
<div className="relative shrink-0" style={{ zIndex: 0 }}>
<div
className="inline-flex items-center justify-center rounded-full bg-gray-500 text-[10px] leading-none text-white ring-2 ring-components-panel-bg"
style={{
width: avatarSizeToPx[size],
height: avatarSizeToPx[size],
}}
>
+{remainingCount}
</div>
</div>
)}
</div>
)
},
)
UserAvatarList.displayName = 'UserAvatarList'