/** * A header button that parks an explanation behind one click. The AI * Visibility page used to open with full-width blocks of prose above the * report - the merchant scrolled past a screen of documentation before * reaching a single number. The copy is unchanged, it just waits to be asked * for. */ import React, { ReactNode, useState } from 'react'; import Modal from './Modal'; interface InfoDialogButtonProps { /** Short label on the trigger. */ label: string; /** Icon rendered before the label. */ icon: ReactNode; /** Heading inside the dialog. */ title: string; /** One line under the title, for context the body assumes. */ subtitle?: string; /** ``warning`` paints the trigger amber, matching the banner it replaced. */ tone?: 'default' | 'warning'; /** * Drop the label and render just the icon, so the header bar stays on a * single row; the label survives as the tooltip and accessible name. */ compact?: boolean; /** The explanation itself. */ children: ReactNode; } /** Trigger surface per tone, matching the header's other secondary buttons. */ const TONE_CLASSES: Record<'default' | 'warning', string> = { default: 'border-border bg-card text-foreground hover:bg-muted hover:text-foreground', warning: 'border-amber-500/30 bg-amber-500/10 text-amber-800 dark:text-amber-200 hover:bg-amber-500/15 hover:text-amber-900', }; /** * The trigger plus its dialog. * * @param {InfoDialogButtonProps} props - Label, icon, tone and body. * @returns {JSX.Element} Button and dialog. */ const InfoDialogButton = ({ label, icon, title, subtitle, tone = 'default', compact = false, children, }: InfoDialogButtonProps): JSX.Element => { const [open, setOpen] = useState(false); return ( <> setOpen(false)} title={title}> {subtitle && (

{subtitle}

)}
{children}
); }; export default InfoDialogButton;