'use client'; import { forwardRef } from 'react'; import type { ButtonHTMLAttributes, ReactNode } from 'react'; import { Tooltip, TooltipContent, TooltipTrigger, } from '@djangocfg/ui-core/components'; import { cn } from '@djangocfg/ui-core/lib'; export interface ChatHeaderActionButtonProps extends Omit, 'children'> { /** Icon (required). */ icon: ReactNode; /** Accessible label — also drives the hover/focus tooltip. */ ariaLabel: string; /** * Tooltip copy. Defaults to `ariaLabel`. Pass to show a friendlier * label than the (sometimes terse) aria string. Set `false` to opt * out of the floating tooltip entirely. */ tooltip?: ReactNode | false; /** Optional unread / status badge — small number on top-right. */ badge?: number; /** Mark as destructive — uses destructive hover tokens. */ destructive?: boolean; /** Optional visual loading state (e.g. while reset is in flight). */ loading?: boolean; } /** * Compact icon button for the chat header actions slot. * * Standard chrome: 28×28 ghost button, hover bg-accent, focus ring, optional * destructive variant, optional numeric badge for unread / pending. * * Shows a floating tooltip (ui-core ``) on hover *and* keyboard * focus; falls back to the native `title` attribute as well. * * @example * ```tsx * * } * ariaLabel="Clear context" * onClick={handleReset} * loading={isResetting} * /> * } * ariaLabel="Settings" * onClick={openSettings} * /> * * } * /> * ``` */ export const ChatHeaderActionButton = forwardRef( function ChatHeaderActionButton( { icon, ariaLabel, tooltip, badge, destructive, loading, disabled, className, ...rest }, ref, ) { const button = ( ); // Opted out — render the button without any tooltip. if (tooltip === false) return button; // Floating tooltip on hover *and* keyboard focus. // Host app mounts (which includes TooltipProvider). const tooltipLabel = tooltip ?? ariaLabel; return ( {button} {/* Tooltip portals to in ui-core's anchored-overlay tier, already above the dock — no z-index override needed. */} {tooltipLabel} ); }, );