// // Copyright 2023 DXOS.org // import { getHeight, getSize, mx } from '@dxos/ui-theme'; import { type ComponentFunction, type Size, type Theme } from '@dxos/ui-types'; export type AvatarStyleProps = Partial<{ size: Size; srOnly: boolean; status: 'active' | 'inactive' | 'current' | 'error' | 'warning' | 'internal'; animation: 'pulse' | 'none'; variant: 'circle' | 'square'; inGroup: boolean; }>; const root: ComponentFunction = ({ size = 10, inGroup }, ...etc) => mx( 'relative inline-flex shrink-0', getSize(size), inGroup && (size === 'px' || size <= 3 ? '-mr-1' : '-mr-2'), ...etc, ); const label: ComponentFunction = ({ srOnly }, ...etc) => mx(srOnly && 'sr-only', ...etc); const description: ComponentFunction = ({ srOnly }, ...etc) => mx('text-description', srOnly && 'sr-only', ...etc); const frame: ComponentFunction = ({ variant }, ...etc) => mx('h-full w-full bg-(--surface-bg)', variant === 'circle' ? 'rounded-full' : 'rounded-sm', ...etc); const statusIcon: ComponentFunction = ({ status, size = 3 }, ...etc) => mx( 'absolute bottom-0 end-0', getSize(size), status === 'inactive' ? 'text-amber-400 dark:text-amber-300' : status === 'active' ? 'text-emerald-400 dark:text-emerald-300' : 'text-neutral-400 dark:text-neutral-300', ...etc, ); const ring: ComponentFunction = ({ status, variant, animation }, ...etc) => mx( 'absolute inset-0 border-2', variant === 'circle' ? 'rounded-full' : 'rounded-sm', status === 'current' ? 'border-primary-400 dark:border-primary-500' : status === 'active' ? 'border-emerald-400 dark:border-emerald-400' : status === 'error' ? 'border-rose-400 dark:border-rose-500' : status === 'warning' ? 'border-amber-400 dark:border-amber-500' : status === 'inactive' ? 'border-separator' : status === 'internal' ? 'border-fuchsia-600' : 'border-[color:var(--surface-bg)]', animation === 'pulse' ? 'animate-halo-pulse' : '', ...etc, ); const fallbackText: ComponentFunction = (_props, ...etc) => mx('fill-white', ...etc); const group: ComponentFunction = (_props, ...etc) => mx('inline-flex items-center', ...etc); const groupLabel: ComponentFunction = ({ size, srOnly }, ...etc) => mx( srOnly ? 'sr-only' : 'rounded-full truncate text-sm leading-none py-1 px-2 relative z-[1] flex items-center justify-center', size && getHeight(size), ...etc, ); const groupDescription: ComponentFunction = ({ srOnly }, ...etc) => mx(srOnly ? 'sr-only' : 'text-description', ...etc); export const avatarTheme: Theme = { root, label, description, statusIcon, frame, ring, fallbackText, group, groupLabel, groupDescription, };