From b4af0d0f9a0397772aa2d201728842b41bfcf1a5 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:16:37 +0800 Subject: [PATCH] refactor: add composable avatar slot wrappers (#34058) --- web/app/components/base/avatar/index.tsx | 72 +++++++++++++++++++----- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/web/app/components/base/avatar/index.tsx b/web/app/components/base/avatar/index.tsx index 461154226d..f53e1f8985 100644 --- a/web/app/components/base/avatar/index.tsx +++ b/web/app/components/base/avatar/index.tsx @@ -1,8 +1,9 @@ import type { ImageLoadingStatus } from '@base-ui/react/avatar' +import type * as React from 'react' import { Avatar as BaseAvatar } from '@base-ui/react/avatar' import { cn } from '@/utils/classnames' -export const avatarSizeClasses = { +const avatarSizeClasses = { 'xxs': { root: 'size-4', text: 'text-[7px]' }, 'xs': { root: 'size-5', text: 'text-[8px]' }, 'sm': { root: 'size-6', text: 'text-[10px]' }, @@ -15,8 +16,6 @@ export const avatarSizeClasses = { export type AvatarSize = keyof typeof avatarSizeClasses -export const getAvatarSizeClassNames = (size: AvatarSize) => avatarSizeClasses[size] - export type AvatarProps = { name: string avatar: string | null @@ -25,13 +24,61 @@ export type AvatarProps = { onLoadingStatusChange?: (status: ImageLoadingStatus) => void } -export const AvatarRoot = BaseAvatar.Root -export const AvatarImage = BaseAvatar.Image -export const AvatarFallback = BaseAvatar.Fallback +export type AvatarRootProps = React.ComponentPropsWithRef & { + size?: AvatarSize +} -const ROOT_CLASS_NAME = 'relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full bg-primary-600' -const IMAGE_CLASS_NAME = 'absolute inset-0 size-full object-cover' -const FALLBACK_CLASS_NAME = 'flex size-full items-center justify-center font-medium text-white' +export function AvatarRoot({ + size = 'md', + className, + ...props +}: AvatarRootProps) { + return ( + + ) +} + +export type AvatarImageProps = React.ComponentPropsWithRef + +export function AvatarImage({ + className, + ...props +}: AvatarImageProps) { + return ( + + ) +} + +export type AvatarFallbackProps = React.ComponentPropsWithRef & { + size?: AvatarSize +} + +export function AvatarFallback({ + size = 'md', + className, + ...props +}: AvatarFallbackProps) { + return ( + + ) +} export const Avatar = ({ name, @@ -40,19 +87,16 @@ export const Avatar = ({ className, onLoadingStatusChange, }: AvatarProps) => { - const sizeClassNames = getAvatarSizeClassNames(size) - return ( - + {avatar && ( )} - + {name?.[0]?.toLocaleUpperCase()}