Yugen UI

PromptInput

PromptInput is a complete prompt composer for AI assistants: auto-grows, attaches via button / drag and drop / pasted images, validates files inline, and Send turns into Stop while the model responds.

Files show as chips with a type icon (or a thumbnail for images, created with URL.createObjectURL and revoked on removal or unmount) and the file size. accept, maxFiles and maxSize are checked before a file is added, and errors show inline (role=alert). Enter sends, Shift+Enter adds a new line, and nothing is sent while an input method is still composing (Telex, IME). onSubmit receives { text, files }; return false to keep the content. For text-only chat, ChatComposer is the simpler choice.
Yugen Labs · experimentalThis component is outside SemVer: its API can change in a minor release, and What's new says so. Versioning policy

Import

Install from npm, copy the source into your project with @yugen-ui/cli or the shadcn CLI, or import directly when working in this repo.

TSX
// npm install yugen-uiimport { PromptInput, validateFiles, formatFileSize } from "yugen-ui";

Variants

Each tile is a standalone example: hover to copy, or press Code to see the source.

Text only, with key hint

Disabled

Usage

Do
  • Set accept / maxSize to the server's limits so errors show early.
  • Put the model and tool pickers in toolbar, close to the Send button.
  • Allow stopping (onStop) when answers are long.
Don't
  • Don't clear the content when sending fails. Return false from onSubmit.
  • Don't send when Enter is only confirming text in an input method.
  • Don't hide why a file was rejected.

Props

Prop · TypeDefaultDescription
onSubmit({ text, files }) => void | booleanDefault: —Sends; returning false keeps the content.
value / defaultValue / onValueChangestringDefault: —Text (controlled / uncontrolled).
files / defaultFiles / onFilesChangeFile[]Default: —Attached files.
accept / maxFiles / maxSizestring / number / number (byte)Default: —File checks; onFilesRejected receives the reasons.
streaming / onStopboolean / () => voidDefault: —Blocks sending; Stop button.
toolbarReactNodeDefault: —Slot after the attach button.
allowAttachmentsbooleanDefault: trueAttach button, drag and drop, pasting files.
maxRows / showHint / disablednumber / boolean / booleanDefault: 8 / false / falseMaximum rows before scrolling, key hint, disabled.
placeholder / label / sendLabel / stopLabelstringDefault: —Visible text and accessible labels.

Messages

Text built into the component: labels, aria-labels, screen reader announcements.

English by default. Change it with the messages prop of YugenProvider, by the namespace below; messagesVi has the Vietnamese set. See Interface language.

messages.promptInput

Key · TypeDefault (English)messagesVi
placeholderstringDefault (English)"Ask anything…"messagesVi"Hỏi bất cứ điều gì…"
labelstring

Nhãn truy cập cho ô soạn.

Default (English)"Enter a prompt"messagesVi"Nhập yêu cầu"
sendstring

Tên nút gửi / dừng.

Default (English)"Send"messagesVi"Gửi"
stopstringDefault (English)"Stop responding"messagesVi"Dừng phản hồi"
attachstring

Tên nút đính kèm.

Default (English)"Attach files"messagesVi"Đính kèm tệp"
attachmentsstring

Tên danh sách tệp đã đính kèm.

Default (English)"Attachments"messagesVi"Tệp đính kèm"
remove(fileName: string) => string

Tên nút gỡ một tệp.

Default (English)(fileName) => `Remove ${fileName}`messagesVi(fileName) => `Gỡ ${fileName}`
hintstring

Gợi ý phím (showHint).

Default (English)"Enter to send · Shift+Enter for a new line"messagesVi"Enter để gửi · Shift+Enter xuống dòng"
dropzonestring

Lớp phủ khi kéo tệp vào.

Default (English)"Drop files to attach"messagesVi"Thả tệp để đính kèm"
attachedOne(fileName: string) => string

Đọc qua live region sau khi đính kèm / gỡ tệp.

Default (English)(fileName) => `Attached ${fileName}`messagesVi(fileName) => `Đã đính kèm ${fileName}`
attachedMany(count: number) => stringDefault (English)(count) => (count === 1 ? "Attached 1 file" : `Attached ${count} files`)messagesVi(count) => `Đã đính kèm ${count} tệp`
removed(fileName: string) => stringDefault (English)(fileName) => `Removed ${fileName}`messagesVi(fileName) => `Đã gỡ ${fileName}`
duplicate(fileName: string) => string

Lỗi kiểm tra tệp (validateFiles). maxSize đã định dạng sẵn (vd. "5 MB").

Default (English)(fileName) => `“${fileName}” is already attached.`messagesVi(fileName) => `“${fileName}” đã được đính kèm.`
invalidType(fileName: string) => stringDefault (English)(fileName) => `“${fileName}” isn't an allowed file type.`messagesVi(fileName) => `“${fileName}” không đúng định dạng cho phép.`
tooLarge(fileName: string, maxSize: string) => stringDefault (English)(fileName, maxSize) => `“${fileName}” is larger than ${maxSize}.`messagesVi(fileName, maxSize) => `“${fileName}” vượt quá ${maxSize}.`
tooMany(maxFiles: number) => stringDefault (English)(maxFiles) => (maxFiles === 1 ? "You can attach only 1 file." : `You can attach up to ${maxFiles} files.`)messagesVi(maxFiles) => `Chỉ đính kèm tối đa ${maxFiles} tệp.`