Prompt Input
最初は静かな1行で、入力に合わせてカードへ広がり、会話が始まると下へ移動するチャット入力欄です。Enterで送信でき、日本語や中国語の入力でも安全です。ファイルは貼り付け、ドロップ、選択でき、プレビュー、進捗、再試行に対応します。@でファイルを追加し、/でコマンドをカーソル位置のメニューから実行できます。数字キーで選べるモデルピッカー、Maxで動き出す推論量スライダー、コンテキストリング、リアルタイム波形つきの音声入力、ツールチップ、返信のストリーミング中に入力したメッセージのキュー、再読み込みしても残る下書きを備えています。
コンポーザーは、チャットの中でもっとも頻繁に触れられる部分なので、すべてのキー入力の感触が正しくなければなりません。Prompt Inputは、左に+、右に送信を備えた静かな1行で始まり、テキストが折り返されるかファイルが追加されるとカードへ広がり、クリアすると元に戻ります。
Enterで送信、Shift+Enterで改行となり、日本語、中国語、韓国語の入力メソッドが中断されることはありません。タッチ画面ではキーボードにShiftがないため、Enterは改行になります。挿入はブラウザー自身のundoスタックを通るため、⌘Zが常に動作し、長い貼り付けはプレビューしたりインラインに戻したりできる添付ファイルになります。
すべては、1つのコンテキストを共有するパーツから組み立てられます。フィールドと送信ボタンだけを使うことも、進捗と再試行つきのファイルアップロード、キャレット位置の@と/のメニュー、モデルピッカー、推論量スライダー、コンテキストリング、音声入力、ツールチップ、返信のストリーミング中に送ったメッセージのキュー、再読み込みしても残る下書きを追加することもできます。
Prompt Inputは無料です。アカウントやトークンなしでインストールでき、Proライセンスのもと、好きなだけのプロジェクトで使えます。
pnpm dlx shadcn@latest add https://hextaui.com/r/pro/prompt-input.jsonAI SDKと使う
useChatのstatusとstopを渡します。ファイルはデータURLを持つFileUIPartとして届き、返信のストリーミング中に入力されたメッセージはキューに入り、完了したときに送信されます。
モデル、推論量、音声入力
PromptInputMetaを使って、モデルピッカー、推論量スライダー、コンテキストリングをコンポーザーの下に置きます。+メニューからツールをオンにして、チップとして表示します。録音を独自の音声モデルに送るにはtranscribeを、テキストが入力された時点ですぐに送信するにはautoSendを渡します。
メンションとコマンド
トリガーごとにメニューを追加します。@は選択をテキストの上のチップにし、/はコマンドを挿入します。矢印キーで移動し、EnterまたはTabで選択し、Escapeで閉じます。すべてテキストから離れずに操作できます。
ファイルのアップロード
進捗を報告し、中断シグナルに従う関数をuploadに渡してください。サーバーに対して大きすぎるファイルなど、再試行では直せないエラーには、retryable: falseでUploadErrorを投げます。
エージェントハーネス
本体をPromptInputInsetで包み、PromptInputFooterを追加します。モード、実行場所、作業するフォルダーにはPromptInputSelectを使います。
構造
外側から内側へ組み合わせるパーツ。
| パーツ | 説明 |
|---|---|
PromptInput | フォームと共有される状態。テキスト、ファイル、メンション、キュー、ステータス。 |
PromptInputBody | コンパクトと展開の間で変化する、角丸のサーフェス。 |
PromptInputTextarea | フィールド。すべてのキーボード操作はここで処理されます。 |
PromptInputTools | 左側。+メニューとツールチップ。 |
PromptInputActions | 右側。音声入力と送信。 |
PromptInputSubmit | statusとテキストに応じて、送信、停止、またはキュー追加を行います。 |
PromptInputAttachments | テキストの上に表示されるファイルとメンションのチップ。 |
PromptInputMenu | 1つのトリガー文字に対する、キャレット位置のメニュー。 |
PromptInputMeta | モデル、推論量、コンテキストのコントロールのための、コンポーザーの下の行。 |
PromptInputModel | モデルと推論量をまとめた1つのコントロールで、シンキングのスイッチ付きです。 |
PromptInputInset | エージェントハーネス向けに、フッター行を保持する、本体を囲む控えめなシェル。 |
PromptInputFooter | 場所、フォルダー、セッションのコントロールのための、インセットシェル内の行。 |
PromptInputSelect | モード、実行場所、フォルダー、リポジトリ用のコンパクトなピッカー。 |
PromptInputQueue, PromptInputSuggestions, PromptInputMeter | キューに入ったメッセージ、スタータープロンプト、maxLength付近での文字数メーター。 |
PromptInput
onSubmitとdefaultValueを除くすべてのformプロップも受け付けます。
| プロパティ | 型 | デフォルト |
|---|---|---|
onSubmit{ text, files, mentions } を受け取ります。Promiseを返すと、resolveされるまでテキストが保持されます。 | (message: PromptMessage) => void | Promise<unknown> | – |
statususeChatのstatusを渡します。ビジー中は、送信が停止またはキューに変わります。 | "ready" | "submitted" | "streaming" | "error" | "ready" |
onStop停止ボタンまたはEscapeから呼ばれます。 | () => void | – |
onEditLast空のフィールドで↑を押したときに読み込めるよう、最後のメッセージを返します。 | () => string | void | – |
value制御されたテキスト。 | string | – |
defaultValue初期テキスト。 | string | "" |
onValueChangeテキストが変わるたびに呼ばれます。 | (value: string) => void | – |
submitOn送信に使うキー。⌘↵は常に送信します。 | "enter" | "mod+enter" | "enter" |
pasteLimit貼り付けが添付ファイルになるまでの文字数。 | number | false | 5000 |
maxLength厳密な上限。PromptInputMeterに表示されます。 | number | – |
draftKey未送信のテキストを、このキーでローカルストレージに保存します。 | string | – |
globalDropページ上のどこにドロップされたファイルも受け付けます。 | boolean | false |
focusOnType他の要素にフォーカスがない状態で入力すると、ここへの入力が始まります。 | boolean | false |
layout切り替えずに、レイアウトを固定します。 | "auto" | "compact" | "expanded" | "auto" |
accept受け付けるファイルの種類。input属性と同様です。 | string | – |
maxFiles一度に扱える最大のファイル数。 | number | – |
maxFileSizeバイト単位での最大ファイルサイズ。 | number | – |
upload各ファイルをアップロードします。恒久的な失敗には、retryable: falseでUploadErrorを投げます。 | (file, { signal, onProgress }) => Promise<unknown> | – |
onReject上限を超えたファイル、または種類が違うファイルに対して呼ばれます。 | (file: File, reason: string) => void | – |
disabledコンポーザー全体を無効にします。 | boolean | false |
| プロパティ | 型 | デフォルト |
|---|---|---|
trigger開くための文字。@や/など。 | string | – |
items{ value, label, description?, icon?, hint?, keywords?, insert? } | PromptMenuItem[] | – |
modeメンションはチップを追加し、テキストは「insert ?? label」を挿入します。 | "mention" | "text" | – |
labelメニューの上部にあるセクションのラベル。 | string | – |
limit一度に表示できる最大の行数。 | number | – |
onSelect選択後に呼ばれます。 | (item: PromptMenuItem) => void | – |
PromptInputModel
モデルピッカーと推論量スライダーを1つにまとめたコントロール。valueとonValueChangeを除く、PromptInputEffortのすべてのプロップも受け付けます。
| プロパティ | 型 | デフォルト |
|---|---|---|
models最初の9個には、1から9のショートカットが割り当てられます。 | { value, label }[] | – |
model選択されたモデル。 | string | – |
onModelChange選択時に呼ばれます。 | (value: string) => void | – |
levels推論量のレベル。低いものから高いものの順です。 | { value, label }[] | – |
effort選択された推論量。 | string | – |
onEffortChangeスライダーの移動に合わせて呼ばれます。 | (value: string) => void | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
models最初の9個には、1から9のショートカットが割り当てられます。 | { value, label }[] | – |
value選択されたモデル。 | string | – |
onValueChange選択時に呼ばれます。 | (value: string) => void | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
levels低いものから高いものの順。 | { value, label }[] | – |
value選択されたレベル。 | string | – |
onValueChangeスライダーの移動に合わせて呼ばれます。 | (value: string) => void | – |
recommended1つのレベルを推奨としてマークします。 | string | – |
thinking設定すると、拡張シンキングのスイッチを表示します。 | boolean | – |
onThinkingChangeスイッチから呼ばれます。 | (thinking: boolean) => void | – |
thinkingLabelスイッチのラベル。 | string | – |
descriptionツールチップ内のヘルプテキスト。 | string | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
used使用したトークン数。 | number | – |
limitコンテキストウィンドウのサイズ。 | number | – |
limitsプランの使用状況などの追加の行。 | { label, used, detail? }[] | – |
limitsLabelそれらの行の見出し。 | string | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
transcribe録音を独自の音声モデルに送ります。指定しない場合は、ブラウザーの音声認識が使われます。 | (audio: Blob) => Promise<string> | – |
shortcutどこからでも録音を開始・終了します。 | string | false | "ctrl+shift+d" |
autoSend文字起こしが入力された時点ですぐに送信します。 | boolean | false |
| プロパティ | 型 | デフォルト |
|---|---|---|
iconチップ内に表示され、ホバー時には×に置き換わります。 | ReactNode | – |
childrenツール名。 | string | – |
toneチップの色。 | "blue" | "green" | "amber" | "violet" | "pink" | "blue" |
onRemoveチップがクリックされたときに呼ばれます。 | () => void | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
options選択肢。説明は各ラベルの下に表示されます。 | { value, label, icon?, description? }[] | – |
value選択されたオプション。プレースホルダーを表示するには、未設定のままにします。 | string | – |
onValueChange選択時に呼ばれます。 | (value: string) => void | – |
labelアクセシブルな名前とツールチップ。ModeやRun onなど。 | string | – |
placeholder何も選択されていないときに表示されます。 | string | – |
icon選択されたオプションにアイコンがないときに表示されます。 | ReactNode | – |
headingメニューの上部のラベル。 | string | – |
shortcutalt+mのように、どこからでもオプションを順に切り替えます。 | string | – |
childrenオプションの下に表示される、Open folderなどの追加のメニュー項目。 | ReactNode | – |
| キー | アクション |
|---|---|
| Enter | 送信します。タッチ画面では、代わりに改行します。 |
| ShiftEnter | 行を追加します。 |
| ⌘Enter | submitOnがmod+enterの場合でも、常に送信します。 |
| Esc | ストリーミング中の返信を停止するか、メニューを閉じるか、録音をキャンセルします。 |
| ↑ | 空のフィールドで、onEditLastが設定されていると、直前のメッセージを呼び戻します。 |
| ↑↓ | 開いている@または/のメニュー内を移動します。 |
| EnterTab | ハイライトされたメニューの行を選択します。 |
| 1–9 | モデルメニューが開いているとき、モデルを選択します。 |
| ←→ | 推論量スライダーを動かします。HomeとEndで両端にジャンプします。 |
| CtrlShiftD | 音声入力を開始し、もう一度押すと文字起こしを挿入します。 |
| AltM | エージェントモードのように、shortcut="alt+m" を持つPromptInputSelectを順に切り替えます。 |
- フィールドには見えるプレースホルダーとアクセシブルな名前があり、すべてのアイコンボタンにはラベルと、ショートカットを示すツールチップがあります。
- キャレット位置のメニューはaria-activedescendantを持つコンボボックスなので、移動中もフォーカスがテキストから離れることはありません。
- アップロード、拒否、キューの変更、音声入力は、politeなライブリージョンで読み上げられます。
- 推論量のコントロールは値のテキストを持つスライダーで、矢印キーとHome、Endでも引き続き操作できます。
- タッチ画面では入力欄が16px以上になるため、フォーカス時にiOSがズームすることはありません。
- モーション軽減時は、高さの変化、波形、推論量の塗りは、アニメーションせずに落ち着きます。
使用技術
Prompt Input を構成する無料のHextaUIコンポーネントです。それぞれ単独でインストールできます。
コード
10 個のファイルを components/blocks/prompt-input に追加しました。