import * as React from 'react'; import { cn } from '../../shared/utils'; type NotificationBadgeVariant = | 'default' | 'secondary' | 'destructive' | 'outline' | 'success' | 'info' | 'warning'; interface NotificationBadgeProps extends React.HTMLAttributes { count?: number; max?: number; showZero?: boolean; dot?: boolean; variant?: NotificationBadgeVariant; } const variantStyles: Record = { default: 'bg-primary text-primary-foreground', secondary: 'bg-secondary text-secondary-foreground', destructive: 'bg-destructive text-destructive-foreground', outline: 'border-2 border-primary bg-background text-primary', success: 'bg-success text-success-foreground', info: 'bg-info text-info-foreground', warning: 'bg-warning text-warning-foreground', }; /** * Floating notification count or dot indicator overlay. * * @description * Renders a small floating badge in the top-right corner of its child element * to indicate unread counts or alert dots. Supports number display with overflow * capping (e.g., `99+`) or a simple dot via `dot={true}`. * * @ai-rules * 1. Use `count` for numeric badges or `dot={true}` for a simple presence indicator. * 2. Wrap the target element as a child — the badge positions relative to it automatically. * 3. For standalone status labels (not overlays), use `` instead. * 4. Available variants: `default`, `secondary`, `destructive`, `outline`, `success`, `info`, `warning`. */ const NotificationBadge = React.forwardRef( ( { className, count = 0, max = 99, showZero = false, dot = false, variant = 'destructive', children, ...props }, ref ) => { const displayCount = count > max ? `${max}+` : count; const shouldShow = count > 0 || showZero; if (!shouldShow && !dot) { return (
{children}
); } return (
{children} {!dot && shouldShow && ( {displayCount} )}
); } ); NotificationBadge.displayName = 'NotificationBadge'; export { NotificationBadge }; export type { NotificationBadgeProps, NotificationBadgeVariant };