buster/web/src/components/ui/avatar/Avatar.tsx

82 lines
2.4 KiB
TypeScript
Raw Normal View History

2025-02-27 05:06:23 +08:00
import React from 'react';
import { Avatar as AvatarBase, AvatarFallback, AvatarImage } from './AvatarBase';
import { getFirstTwoCapitalizedLetters } from '@/lib/text';
import { Tooltip } from '../tooltip/Tooltip';
import { BusterLogo } from '@/assets/svg/BusterLogo';
import { cn } from '@/lib/utils';
2025-02-27 14:25:53 +08:00
export interface AvatarProps {
2025-04-10 04:34:36 +08:00
image?: string | null;
2025-02-27 05:06:23 +08:00
name?: string | null;
className?: string;
2025-03-12 05:55:55 +08:00
fallbackClassName?: string;
2025-02-27 05:06:23 +08:00
useToolTip?: boolean;
2025-02-27 14:25:53 +08:00
size?: number;
2025-02-27 05:06:23 +08:00
}
2025-02-27 14:25:53 +08:00
export const Avatar: React.FC<AvatarProps> = React.memo(
2025-03-12 05:55:55 +08:00
({ image, name, className, useToolTip, size, fallbackClassName }) => {
2025-02-27 05:06:23 +08:00
const hasName = !!name;
2025-03-15 01:23:32 +08:00
const nameLetters = createNameLetters(name);
2025-03-15 01:31:43 +08:00
const hasImage = !!image;
2025-02-27 05:06:23 +08:00
return (
2025-03-15 01:31:43 +08:00
<Tooltip delayDuration={300} title={useToolTip ? name || '' : ''}>
2025-02-27 14:25:53 +08:00
<AvatarBase
className={className}
style={{
width: size,
height: size
}}>
2025-02-27 05:06:23 +08:00
{image && <AvatarImage src={image} />}
2025-03-15 01:23:32 +08:00
{hasName ? (
2025-03-15 01:31:43 +08:00
<NameLettersFallback
fallbackClassName={fallbackClassName}
nameLetters={nameLetters}
hasImage={hasImage}
/>
2025-03-15 01:23:32 +08:00
) : (
<BusterAvatarFallback fallbackClassName={fallbackClassName} />
)}
2025-02-27 05:06:23 +08:00
</AvatarBase>
</Tooltip>
);
}
);
Avatar.displayName = 'Avatar';
2025-03-15 01:31:43 +08:00
const NameLettersFallback: React.FC<{
fallbackClassName?: string;
nameLetters: string;
hasImage: boolean;
}> = ({ fallbackClassName, hasImage, nameLetters }) => {
return (
<AvatarFallback className={cn(fallbackClassName)} delayMs={hasImage ? 300 : 0}>
{nameLetters}
</AvatarFallback>
);
2025-03-15 01:23:32 +08:00
};
const BusterAvatarFallback: React.FC<{ fallbackClassName?: string }> = ({ fallbackClassName }) => {
2025-02-27 05:06:23 +08:00
return (
2025-03-15 01:31:43 +08:00
<AvatarFallback className={cn('border bg-white', fallbackClassName)} delayMs={0}>
2025-03-15 01:23:32 +08:00
<div className="text-foreground flex h-full w-full items-center justify-center">
<BusterLogo className="h-full w-full translate-x-[1px] p-1" />
</div>
</AvatarFallback>
2025-02-27 05:06:23 +08:00
);
};
2025-03-15 01:23:32 +08:00
const createNameLetters = (name?: string | null) => {
if (name) {
2025-02-27 05:06:23 +08:00
const firstTwoLetters = getFirstTwoCapitalizedLetters(name);
if (firstTwoLetters.length == 2) return firstTwoLetters;
const _name = name.split(' ') as [string, string];
const returnName = `${_name[0][0]}`.toUpperCase().replace('@', '');
return returnName;
}
return '';
};