import { AnimatePresence, motion } from "motion/react"; import { argHint } from "../commands/registry"; import type { SlashCommand } from "../commands/types"; import { cn } from "../lib/cn"; import { useOpenGeniText } from "../messages/runtime"; export type CommandPaletteProps = { open: boolean; items: SlashCommand[]; highlight: number; /** Hover/click selects a row. */ onHighlight: (index: number) => void; /** Click runs the row (same path as Enter). */ onRun: (index: number) => void; /** Footer arg hint shown in arg-hint mode (e.g. ""). */ argHintText: string; /** id used for aria-activedescendant wiring from the textarea. */ listboxId: string; /** Accessible list label. Defaults to "Slash commands". */ label?: string | undefined; /** Badge shown for destructive commands. Defaults to "danger". */ dangerLabel?: string | undefined; }; /** * The slash-command palette: a popover anchored above the textarea, rendered * entirely from the filtered registry. Dark-first, Linear/Vercel-calm, using * the opengeni#46 design tokens. Full keyboard nav lives in useSlashCommands; * this component is presentational + aria. */ export function CommandPalette({ open, items, highlight, onHighlight, onRun, argHintText, listboxId, label: labelProp, dangerLabel = "danger", }: CommandPaletteProps) { const t = useOpenGeniText(); const label = labelProp === undefined ? t("commandPalette.slashCommands") : labelProp; return ( {open ? (
    {items.map((command, index) => { const selected = index === highlight; const hint = argHint(command.args); return (
  • onHighlight(index)} onMouseDown={(event) => { // Keep textarea focus; run on click. event.preventDefault(); onRun(index); }} className={cn( "mx-1 flex cursor-pointer items-center gap-2 rounded-og-md px-2.5 py-1.5", "transition-colors duration-100", selected ? "bg-og-accent/15 text-og-fg" : "text-og-fg-muted hover:bg-og-surface-3", )} > /{command.name} {hint ? ( {hint} ) : null} {command.danger ? ( {dangerLabel} ) : null} {command.description}
  • ); })}
{argHintText ? (
{argHintText}
) : null}
) : null}
); }