"use client"; import { CornerDownLeftIcon, SquareIcon } from "lucide-react"; import { cn } from "@/lib/utils"; /** * The floating composer blob. Sits on top of the transcript (the parent * overlays it), persists at the bottom while scrolling, content fades out * behind it. * * Corner-radius math (concentric rounding — outer = inner + gap): * blob rounded-2xl (16px) − padding p-1.5 (6px) = button rounded-[10px]. * 10px is 25% of the 40px send button — matches the reference. * * Modes (one text field on screen, always): * chat — normal message composer. * note — a question is pending; text here becomes the answer's note. * No send action (the card's Submit sends); Enter = newline. * answer — a free-text ask is pending; this field IS the answer and the * send button submits it. */ export type ComposerMode = "chat" | "note" | "answer"; const PLACEHOLDERS: Record = { chat: "Ask, answer, or steer the lesson…", note: "Add a note (optional) — anything you're unsure about", answer: "Type your answer…", }; export function Composer({ mode, busy, value, onChange, onSend, onStop, canSend, autoFocus, }: { mode: ComposerMode; busy: boolean; value: string; onChange: (v: string) => void; onSend: () => void; onStop: () => void; canSend: boolean; autoFocus?: boolean; }) { const showSend = mode !== "note"; const handleKeyDown = (e: React.KeyboardEvent) => { // Enter sends (chat/answer); Shift+Enter newline. Note mode: no send. if (e.key === "Enter" && !e.shiftKey && mode !== "note") { e.preventDefault(); if (busy) onStop(); else if (canSend) onSend(); } }; return (
{ e.preventDefault(); if (busy) onStop(); else if (canSend && showSend) onSend(); }} >