'use client'; /** * CodePanelHeader — a slim, persistent header bar for the code panel * (PrettyCode), GitHub / ChatGPT style: the detected language on the left, * a copy button on the right. In flow (not an absolute hover overlay), so * the copy button never floats over the code. * * Code panels are usually DARK (like the map basemap is always light), so * the header defaults to FIXED on-dark colors — theme tokens * (`text-foreground`, `border-border`) would render dark-on-dark / an * over-bright divider on the dark panel. Pass `dark={false}` for a * light-surfaced panel, which switches to muted semantic tokens. */ import { useCallback, useState, type ReactNode } from 'react'; import { cn } from '@djangocfg/ui-core/lib'; import { Check, Copy, Maximize2 } from 'lucide-react'; export interface CodePanelHeaderProps { /** Display label on the left (e.g. "typescript", "json", "bash"). */ language?: ReactNode; /** Text copied when the copy button is pressed. Omit to hide copy. */ copyValue?: string; /** a11y label for the copy button. */ copyLabel?: string; /** When set, an expand (⤢) button is shown that calls this — used to open * the panel full-screen when it's height-capped. */ onExpand?: () => void; /** a11y / tooltip label for the expand button. */ expandLabel?: string; /** Extra trailing actions, rendered left of the copy button. */ actions?: ReactNode; /** Dark panel (default). `false` → light-surface muted tokens. */ dark?: boolean; className?: string; } export function CodePanelHeader({ language, copyValue, copyLabel = 'Copy', onExpand, expandLabel = 'Expand', actions, dark = true, className, }: CodePanelHeaderProps) { const [copied, setCopied] = useState(false); const onCopy = useCallback(() => { if (copyValue == null) return; void navigator.clipboard?.writeText(copyValue).then(() => { setCopied(true); setTimeout(() => setCopied(false), 1400); }); }, [copyValue]); // Fixed on-dark vs semantic light. The hairline is faint so it never // reads as a heavy rule across the panel. const dividerCls = dark ? 'border-white/[0.06]' : 'border-border/60'; const labelCls = dark ? 'text-white/40' : 'text-muted-foreground'; const btnCls = dark ? 'text-white/45 hover:bg-white/10 hover:text-white/80 focus-visible:ring-white/40' : 'text-muted-foreground hover:bg-foreground/10 hover:text-foreground focus-visible:ring-ring'; return (