Prompt Input
Ein Chat-Composer, der als ruhige einzelne Zeile beginnt, beim Schreiben zu einer Karte wächst und nach unten wandert, sobald die Unterhaltung beginnt. Enter sendet, sicher bei japanischer und chinesischer Eingabe. Dateien per Einfügen, Ablegen oder Auswählen hinzufügen, mit Vorschau, Fortschritt und Wiederholen. @ fügt Dateien hinzu und / führt Befehle aus einem Menü an der Einfügemarke aus. Ein Modellwähler mit Zifferntasten, ein Effort-Slider, der bei Max lebendig wird, ein Kontextring, Diktat mit Live-Wellenform, Tool-Chips, eine Warteschlange für Nachrichten, die während einer streamenden Antwort getippt werden, und Entwürfe, die einen Reload überstehen.
Der Composer ist der Teil eines Chats, den Leute am meisten berühren, deshalb muss sich jeder Tastenanschlag richtig anfühlen. Prompt Input beginnt als ruhige einzelne Zeile mit dem + links und Senden rechts, wächst zu einer Karte, sobald der Text umbricht oder Dateien hinzukommen, und setzt sich zurück, wenn er geleert wird.
Enter sendet und Shift+Enter fügt eine Zeile hinzu, und Eingabemethoden für Japanisch, Chinesisch und Koreanisch werden nie unterbrochen. Auf Touchscreens fügt Enter eine Zeile hinzu, da die Tastatur kein Shift hat. Einfügungen laufen über den eigenen Undo-Stack des Browsers, sodass ⌘Z immer funktioniert, und lange eingefügte Texte werden zu einem Anhang, den du in der Vorschau ansehen oder wieder inline einsetzen kannst.
Alles ist aus Parts zusammengesetzt, die einen Kontext teilen. Nutze nur das Feld und den Senden-Button, oder füge Datei-Uploads mit Fortschritt und Wiederholen, @- und /-Menüs an der Einfügemarke, einen Modellwähler, einen Effort-Slider, einen Kontextring, Diktat, Tool-Chips, eine Warteschlange für Nachrichten, die während einer streamenden Antwort gesendet werden, und Entwürfe, die einen Reload überstehen, hinzu.
Prompt Input ist kostenlos. Installiere es ohne Konto oder Token und nutze es unter der Pro-Lizenz in beliebig vielen Projekten.
pnpm dlx shadcn@latest add https://hextaui.com/r/pro/prompt-input.jsonMit dem AI SDK
Übergib status und stop von useChat. Dateien kommen als FileUIPart mit einer Data-URL an, und eine Nachricht, die während einer streamenden Antwort getippt wird, wird in die Warteschlange gestellt und gesendet, wenn die Antwort fertig ist.
Modell, Effort und Diktat
Setze Modellwähler, Effort-Slider und Kontextring mit PromptInputMeta unter den Composer. Aktiviere Tools über das +-Menü und zeige sie als Chips. Übergib transcribe, um Aufnahmen an dein eigenes Sprachmodell zu schicken, und autoSend, um zu senden, sobald der Text da ist.
Erwähnungen und Befehle
Füge pro Auslösezeichen ein Menü hinzu. @ macht aus einer Auswahl einen Chip über dem Text, und / fügt den Befehl ein. Pfeiltasten bewegen, Enter oder Tab wählt und Escape schließt, alles ohne den Text zu verlassen.
Dateien hochladen
Gib upload eine Funktion, die den Fortschritt meldet und das Abbruchsignal beachtet. Wirf UploadError mit retryable: false bei Fehlern, die ein erneuter Versuch nicht behebt, etwa einer Datei, die für den Server zu groß ist.
Agent-Harness
Umschließe den Body mit PromptInputInset und füge ein PromptInputFooter hinzu. Nutze PromptInputSelect für den Modus, den Ausführungsort und den Ordner, in dem gearbeitet wird.
Aufbau
Die Teile, die du zusammensetzt, von außen nach innen.
| Part | Beschreibung |
|---|---|
PromptInput | Das Formular und der gemeinsame State: Text, Dateien, Erwähnungen, Warteschlange und Status. |
PromptInputBody | Die abgerundete Fläche, die zwischen kompakt und erweitert wechselt. |
PromptInputTextarea | Das Feld. Die gesamte Tastaturbehandlung liegt hier. |
PromptInputTools | Linke Seite: das +-Menü und Tool-Chips. |
PromptInputActions | Rechte Seite: Diktat und Senden. |
PromptInputSubmit | Senden, Stopp oder Warteschlange, je nach Status und Text. |
PromptInputAttachments | Datei- und Erwähnungs-Chips über dem Text. |
PromptInputMenu | Ein Menü an der Einfügemarke für ein Auslösezeichen. |
PromptInputMeta | Die Zeile unter dem Composer für die Steuerelemente von Modell, Effort und Kontext. |
PromptInputModel | Ein Steuerelement für Modell und Effort, mit dem Thinking-Switch. |
PromptInputInset | Eine gedämpfte Hülle um den Body, die eine Fußzeile enthält, für Agent-Harnesses. |
PromptInputFooter | Die Zeile innerhalb der eingelassenen Hülle für Ort-, Ordner- und Sitzungs-Steuerelemente. |
PromptInputSelect | Ein kompakter Picker für Modi, Ausführungsort, Ordner oder Repositories. |
PromptInputQueue, PromptInputSuggestions, PromptInputMeter | Nachrichten in der Warteschlange, Starter-Prompts und ein Zeichenzähler nahe maxLength. |
PromptInput
Akzeptiert auch alle form-Props außer onSubmit und defaultValue.
| Prop | Typ | Standard |
|---|---|---|
onSubmitErhält { text, files, mentions }. Gib ein Promise zurück, um den Text zu behalten, bis es aufgelöst ist. | (message: PromptMessage) => void | Promise<unknown> | – |
statusÜbergib status von useChat. Solange beschäftigt, wird Senden zu Stopp oder Warteschlange. | "ready" | "submitted" | "streaming" | "error" | "ready" |
onStopWird vom Stopp-Button oder Escape aufgerufen. | () => void | – |
onEditLastGib die letzte Nachricht zurück, um sie mit ↑ in einem leeren Feld zu laden. | () => string | void | – |
valueKontrollierter Text. | string | – |
defaultValueAnfangstext. | string | "" |
onValueChangeWird aufgerufen, wenn sich der Text ändert. | (value: string) => void | – |
submitOnWelche Taste sendet. ⌘↵ sendet immer. | "enter" | "mod+enter" | "enter" |
pasteLimitZeichen, ab denen ein Einfügen zu einem Anhang wird. | number | false | 5000 |
maxLengthHartes Limit, von PromptInputMeter angezeigt. | number | – |
draftKeySpeichert ungesendeten Text unter diesem Schlüssel im Local Storage. | string | – |
globalDropAkzeptiert Dateien, die irgendwo auf der Seite abgelegt werden. | boolean | false |
focusOnTypeTippen, solange nichts anderes den Fokus hat, beginnt hier zu schreiben. | boolean | false |
layoutErzwingt ein Layout, statt umzuschalten. | "auto" | "compact" | "expanded" | "auto" |
acceptAkzeptierte Dateitypen, wie das input-Attribut. | string | – |
maxFilesHöchstzahl gleichzeitiger Dateien. | number | – |
maxFileSizeGrößte Datei in Bytes. | number | – |
uploadLädt jede Datei hoch. Wirf UploadError mit retryable: false bei dauerhaften Fehlern. | (file, { signal, onProgress }) => Promise<unknown> | – |
onRejectWird für Dateien über einem Limit oder vom falschen Typ aufgerufen. | (file: File, reason: string) => void | – |
disabledDeaktiviert den gesamten Composer. | boolean | false |
| Prop | Typ | Standard |
|---|---|---|
triggerDas Zeichen, das es öffnet, etwa @ oder /. | string | – |
items{ value, label, description?, icon?, hint?, keywords?, insert? } | PromptMenuItem[] | – |
modeErwähnungen fügen einen Chip hinzu; Text fügt insert ?? label ein. | "mention" | "text" | – |
labelAbschnittslabel oben im Menü. | string | – |
limitHöchstzahl angezeigter Zeilen. | number | – |
onSelectWird nach einer Auswahl aufgerufen. | (item: PromptMenuItem) => void | – |
PromptInputModel
Modellwähler und Effort-Slider in einem Steuerelement. Nimmt auch alle PromptInputEffort-Props außer value und onValueChange.
| Prop | Typ | Standard |
|---|---|---|
modelsDie ersten neun erhalten die Kürzel 1–9. | { value, label }[] | – |
modelGewähltes Modell. | string | – |
onModelChangeWird bei der Auswahl aufgerufen. | (value: string) => void | – |
levelsEffort-Stufen, von der niedrigsten zur höchsten. | { value, label }[] | – |
effortGewählter Effort. | string | – |
onEffortChangeWird aufgerufen, während sich der Slider bewegt. | (value: string) => void | – |
| Prop | Typ | Standard |
|---|---|---|
modelsDie ersten neun erhalten die Kürzel 1–9. | { value, label }[] | – |
valueGewähltes Modell. | string | – |
onValueChangeWird bei der Auswahl aufgerufen. | (value: string) => void | – |
| Prop | Typ | Standard |
|---|---|---|
levelsVon der niedrigsten zur höchsten. | { value, label }[] | – |
valueGewählte Stufe. | string | – |
onValueChangeWird aufgerufen, während sich der Slider bewegt. | (value: string) => void | – |
recommendedMarkiert eine Stufe als empfohlen. | string | – |
thinkingZeigt den Switch für Extended Thinking, wenn gesetzt. | boolean | – |
onThinkingChangeWird vom Switch aufgerufen. | (thinking: boolean) => void | – |
thinkingLabelSwitch-Label. | string | – |
descriptionHilfetext im Tooltip. | string | – |
| Prop | Typ | Standard |
|---|---|---|
usedVerbrauchte Tokens. | number | – |
limitGröße des Kontextfensters. | number | – |
limitsZusätzliche Zeilen, etwa Planverbrauch. | { label, used, detail? }[] | – |
limitsLabelÜberschrift für diese Zeilen. | string | – |
| Prop | Typ | Standard |
|---|---|---|
transcribeSendet die Aufnahme an dein Sprachmodell. Ohne dies wird die Spracherkennung des Browsers verwendet. | (audio: Blob) => Promise<string> | – |
shortcutStartet und beendet eine Aufnahme von überall. | string | false | "ctrl+shift+d" |
autoSendSendet, sobald das Transkript da ist. | boolean | false |
| Prop | Typ | Standard |
|---|---|---|
iconWird im Chip angezeigt und beim Hover durch × ersetzt. | ReactNode | – |
childrenTool-Name. | string | – |
toneChip-Farbe. | "blue" | "green" | "amber" | "violet" | "pink" | "blue" |
onRemoveWird aufgerufen, wenn auf den Chip geklickt wird. | () => void | – |
| Prop | Typ | Standard |
|---|---|---|
optionsDie Auswahlmöglichkeiten. Beschreibungen erscheinen unter jedem Label. | { value, label, icon?, description? }[] | – |
valueGewählte Option. Lass es ungesetzt, um den Platzhalter zu zeigen. | string | – |
onValueChangeWird bei der Auswahl aufgerufen. | (value: string) => void | – |
labelZugänglicher Name und Tooltip, etwa Mode oder Run on. | string | – |
placeholderWird angezeigt, wenn nichts gewählt ist. | string | – |
iconWird angezeigt, wenn die gewählte Option kein Icon hat. | ReactNode | – |
headingLabel oben im Menü. | string | – |
shortcutSchaltet von überall durch die Optionen, etwa mit alt+m. | string | – |
childrenZusätzliche Menüpunkte unter den Optionen, etwa Open folder. | ReactNode | – |
| Taste | Aktion |
|---|---|
| Enter | Sendet. Auf Touchscreens fügt es stattdessen eine Zeile hinzu. |
| ShiftEnter | Fügt eine Zeile hinzu. |
| ⌘Enter | Sendet immer, auch wenn submitOn mod+enter ist. |
| Esc | Stoppt eine streamende Antwort, schließt ein Menü oder bricht eine Aufnahme ab. |
| ↑ | Holt in einem leeren Feld deine letzte Nachricht zurück, wenn onEditLast gesetzt ist. |
| ↑↓ | Wechselt durch ein geöffnetes @- oder /-Menü. |
| EnterTab | Wählt die hervorgehobene Menüzeile. |
| 1–9 | Wählt ein Modell, solange das Modellmenü geöffnet ist. |
| ←→ | Bewegt den Effort-Slider. Pos1 und Ende springen zu den Enden. |
| CtrlShiftD | Startet das Diktat und fügt das Transkript ein, wenn erneut gedrückt. |
| AltM | Schaltet ein PromptInputSelect durch, das shortcut="alt+m" hat, etwa den Agent-Modus. |
- Das Feld hat einen sichtbaren Platzhalter und einen zugänglichen Namen, und jeder Icon-Button hat ein Label und einen Tooltip mit seinem Tastenkürzel.
- Das Menü an der Einfügemarke ist eine Combobox mit aria-activedescendant, sodass der Fokus beim Navigieren nie den Text verlässt.
- Uploads, Ablehnungen, Änderungen an der Warteschlange und Diktat werden über eine höfliche Live-Region angesagt.
- Das Effort-Steuerelement ist ein Slider mit Werttext und funktioniert weiterhin mit Pfeiltasten sowie Pos1 und Ende.
- Inputs haben auf Touchscreens mindestens 16 px, damit iOS beim Fokus nie hineinzoomt.
- Bei reduzierter Bewegung setzen sich Höhenänderungen, die Wellenform und die Effort-Füllung ohne Animation.
Gebaut mit
Die kostenlosen HextaUI-Komponenten, aus denen Prompt Input besteht. Jede lässt sich einzeln installieren.
Code
10 Dateien, hinzugefügt zu components/blocks/prompt-input.