import { as, Badge, Box, color, ContainerColor, MainColor, Text, Tooltip, TooltipProvider, toRem, } from 'folds'; import React, { ReactNode } from 'react'; import * as css from './styles.css'; import { Presence, usePresenceLabel } from '../../hooks/useUserPresence'; import { isDndPresence } from '../../utils/busyPresence'; const PresenceToColor: Record = { [Presence.Online]: 'Success', [Presence.Unavailable]: 'Warning', [Presence.Offline]: 'Secondary', [Presence.Busy]: 'Critical', }; type PresenceBadgeProps = { presence: Presence; status?: string; size?: '200' | '300' | '400' | '500'; }; export function PresenceBadge({ presence, status, size }: PresenceBadgeProps) { const label = usePresenceLabel(); // DND is encoded as unavailable + status_msg 'dnd'; render it red/"Do Not // Disturb" to match PresenceRingAvatar and the settings picker (which both // special-case 'dnd' → Critical) — the badge was the lone outlier showing a // yellow "Idle". The 'dnd' sentinel isn't surfaced as a status line. // [Gitea #283] or MSC3026 busy, which keeps a real status line. const isDnd = isDndPresence(presence, status); const legacyDnd = isDnd && status === 'dnd'; const displayLabel = isDnd ? 'Do Not Disturb' : label[presence]; const displayStatus = legacyDnd ? undefined : status; const ariaLabel = displayStatus ? `${displayLabel} — ${displayStatus}` : displayLabel; return ( {displayLabel} {displayStatus && •} {displayStatus && {displayStatus}} } > {(triggerRef) => ( )} ); } type AvatarPresenceProps = { badge: ReactNode; variant?: ContainerColor; }; export const AvatarPresence = as<'div', AvatarPresenceProps>( ({ as: AsAvatarPresence, badge, variant = 'Surface', children, ...props }, ref) => ( {badge && (
{badge}
)} {children}
), );