Skip to content

ChatInput Component ​

The composer: a text area, file attachments (pick, drop, paste), and the send / stop button. Chat uses it; use it directly with useChat for your own layout.

New in 0.4.0

Drag and drop, paste, image thumbnails, per-file progress with retry, files without text, state (one value for every reason the composer may be closed), and a refused message that gives its text back.

An attached picture shown as a thumbnail chip with its size, a remove button and the file counter

Import ​

tsx
import { ChatInput } from "@cognipeer/chat-ui";

Usage ​

tsx
const chat = useChat({ baseUrl: "/api/agents", agentId: "assistant" });

<ChatInput
  onSend={chat.sendMessage}
  onStop={chat.stop}
  isLoading={chat.isStreaming}
  isUploading={chat.isUploading}
  pendingFiles={chat.pendingFiles}
  onFilesAdd={chat.addFiles}
  onFileRemove={chat.removeFile}
  onFileRetry={chat.retryFile}
  state={chat.composerState}
/>

Props ​

PropTypeDefaultDescription
onSend(message: string) => void | boolean | Promise<void | boolean>requiredCalled with the trimmed text. The composer clears at once; if this returns (or resolves to) false the message was refused and the typed text comes back unless something new was typed meanwhile. The text is empty when only files are attached
onStop() => void-Stop callback; shows a stop button while isLoading
onFilesAdd(files: File[]) => void-Files were picked, dropped or pasted. Without it there is no paperclip and no drop zone
onFileRemove(fileId: string) => void-A pending file was removed (while it is going up, that stops the upload)
onFileRetry(fileId: string) => void-A file that failed to upload is tried again; its chip then has a retry button
pendingFilesFileAttachment[][]Files attached to the next message
isLoadingbooleanfalseA reply is streaming: sending waits, attaching does not
isUploadingbooleanfalseThe files of a message are being read or uploaded: the paperclip, drop and sending wait, and the chips show a spinner. Files that carry their own status (stored as they were picked) show a progress bar instead, and only hold the send back
enableFileUploadbooleantrueShow the paperclip and take drops and pastes
allowedFileTypesstring[]anyPassed to the file picker's accept
maxFilesnumber10The paperclip is off once this many files are attached (plus filesHeld)
filesHeldnumber0Files the conversation already holds; they count against maxFiles
fileCounterbooleanfalseShow "3 of 10 files in this chat" next to the chips
retentionDaysnumber-Show "Files are kept for 30 days" in the helper line
imagesIgnoredbooleanfalseThe agent does not read images: an attached image gets a warning chip and message
stateComposerState"open"What the composer is doing; see below. useChat returns it as composerState
pendingMode"blocked" | "cancel" | "answer"-The older form of state for the first three values; state wins
placeholderstringlocalizedInput placeholder
disabledbooleanfalseDisable input
autoFocusbooleanfalseFocus on mount
classNamestring-Container class name
footerReactNode-Content under the helper text; Chat puts the row of legal links here
renderSendButton({ onClick, disabled }) => ReactNode-Custom send button
renderStopButton({ onClick }) => ReactNode-Custom stop button

The component also takes a ref (ChatInputHandle) with focus() and setValue(text, { focus? }), which puts text in the composer (replacing what is there), grows the box to fit and, unless focus: false, focuses it with the caret at the end. The text area grows with its content up to 200 px, then scrolls.

States ​

stateTextareaPaperclipSendNotice above the box
openopenonon
blockedclosedoffoff"The assistant is waiting for your response above"
cancelopenononsending cancels the request
answeropenonthe text answers the question (files alone are not an answer)"Your reply will answer the question above"
followingclosedoffoff (Stop stays)"This conversation is answering in another window. You can stop it here."
budget_pausedclosedoffoffnone: the usage limit banner explains
readonlyclosedoffoff"This conversation is read-only"

The placeholder says the same. In every state, the stop button shows while isLoading and onStop is set.

Files ​

  • Paperclip: opens the file picker. It is off while the composer is blocked, while files are uploading, and at the file limit.
  • Drag and drop: dropping files on the composer attaches them; a hint shows while a drag is over it. A drop the composer cannot take (blocked, uploading) is refused without letting the browser open the file.
  • Paste: a pasted screenshot or copied file is attached; pasted text stays text, also when the clipboard carries an image next to it (a copied spreadsheet cell). A browser's generic image.png gets its own name.
  • Files without text: a message with only files can be sent. Chat / useChat then send attachmentsOnlyMessage.
  • Chips: name and size, a thumbnail for an image (from FileAttachment.previewUrl) and a remove button labelled with the file name. A chip whose file has a status shows it: uploading a progress bar (role="progressbar") and a percentage, ready a check mark, failed a red border with the reason on hover, a retry and a remove button. A file whose conversionStatus is failed / skipped is tinted "no readable text".
  • Send is held back while any chip is queued or uploading, and while any failed: the notice "Some files could not be uploaded. Try again or remove them to send." says so.

Limits and refusals (size, count, type, empty) are checked by useChat.addFiles; see File Uploads.

Keyboard ​

  • Enter - Send message
  • Shift+Enter - New line

Styling ​

Colours come from the theme variables (--chat-bg-tertiary, --chat-border-primary, --chat-accent-primary, ...) and the status colours (--chat-warning for the image warning). See Theming.

Accessibility ​

  • The text area is labelled "Message" (chat.input.label); send, stop, attach and remove buttons have accessible names (the remove button names its file).
  • The notice for the composer's state, the image warning, the failed-files notice and a chip's upload spinner are role="status"; the progress of an upload is a progressbar with a name and a value.
  • The pending files are a labelled list.

Studio · Pulse · Console · Agent SDK and more — the Cognipeer documentation hub