'use client'; import type { ReactNode } from 'react'; import { X } from 'lucide-react'; import { cn } from '@djangocfg/ui-core/lib'; /** One action button in the banner. */ export interface ComposerBannerAction { /** Stable key. */ id: string; label: ReactNode; onClick: () => void; /** `primary` — filled accent; `outline` — bordered neutral. Default `outline`. */ variant?: 'primary' | 'outline'; } export interface ComposerBannerProps { /** Leading icon (Lucide element). */ icon?: ReactNode; /** Bold headline. */ title: ReactNode; /** Secondary line under the title. */ description?: ReactNode; /** Up to two trailing action buttons. */ actions?: ComposerBannerAction[]; /** Accent tint: `info` neutral, `warning` destructive, `upgrade` primary. */ variant?: 'info' | 'warning' | 'upgrade'; /** Show a dismiss `×` in the top-right corner. */ onDismiss?: () => void; className?: string; } /** Icon-tint per variant — keeps the surface neutral, accents the icon only. */ const ICON_TINT: Record, string> = { info: 'text-muted-foreground', warning: 'text-destructive', upgrade: 'text-primary', }; const ACTION_VARIANT: Record< NonNullable, string > = { primary: 'bg-primary text-primary-foreground hover:bg-primary/90', outline: 'border border-border bg-background text-foreground hover:bg-accent hover:text-accent-foreground', }; /** * A standalone notice bubble that sits above the composer — its own * rounded surface, separated by a gap (drop it into * `composerSlots.blockStart`). Mirrors ChatGPT's "free limit reached" * banner: leading icon, title + description, trailing action buttons. */ export function ComposerBanner({ icon, title, description, actions, variant = 'info', onDismiss, className, }: ComposerBannerProps) { return (
{icon ? ( {icon} ) : null}

{title}

{description ? (

{description}

) : null}
{actions && actions.length > 0 ? (
{actions.map((action) => ( ))}
) : null} {onDismiss ? ( ) : null}
); }