チャット入力ChatInputExperimental

メッセージ入力、添付、送信、停止、無効化理由をまとめて扱うチャット用の入力欄です。

プレビュー

状態とバリエーション

標準表示

1つの入力エリア内に、添付プレビュー、枠なしの複数行入力、下段ツールバーをまとめます。

処理中

送信中は停止ボタンに切り替え、入力を一時停止します。

無効化理由

送信できない理由はボタンのツールチップで伝えます。

AI からの選択肢

AI から提示された選択肢は ChatInput ではなく、ChatComposer の prompt として扱います。

どの整理方針で進めますか?

作業コンテキスト付き

現在のブランチ、作業フォルダ、ワークツリー状態などは ChatComposer の context としてまとめます。

#24feature/insights-panel作業状態を選択できます。

使用量とモデル状態

使用量は ChatComposer の footer で独立して表示し、モデル選択は ChatInput 側に残します。

入力ペット付き

補助キャラクターは装飾・状態通知なので、ChatInput の外側に重ねて配置します。

補助キャラクターは装飾・状態通知なので、ChatComposer の accessory として配置します。

プロパティ

表は横にスクロールできます
プロパティ初期値説明
onSend(message: string, files?: File[]) => void-送信時に呼び出されるコールバックです。
onStop() => void-処理中の停止操作で呼び出します。
isProcessingbooleanfalse送信中・生成中の状態を表します。
enableAttachmentsbooleantrue添付ボタンを表示するかを指定します。
modelLabelReact.ReactNode"自動"下段右側のモデル表示です。
optionsContentReact.ReactNode-入力オプションボタンから開くポップオーバー内容です。
modelOptionsChatInputModelOption[]-モデルボタンから選択できる候補です。
toolbarAccessoryReact.ReactNode-モデル選択の右横に置く補助操作です。使用量など、モデルとは別の状態をアイコンで表示できます。
voiceActivebooleanfalse音声認識の録音中状態を外部から制御する場合に指定します。
showOptionsButton / showModelSelector / showVoiceButtonbooleantrue下段ツールバーの補助操作を表示するかを指定します。入力オプションは optionsContent または onOptionsClick がある場合だけ表示されます。
labelsChatInputLabels-ツールチップと無効化理由の文言を指定します。

使い方

import * as React from "react";
import { ChatInput, Switch } from "@gunjo/ui";

export function SupportComposer() {
  const [isProcessing, setIsProcessing] = React.useState(false);
  const [model, setModel] = React.useState("auto");
  const [webSearch, setWebSearch] = React.useState(true);
  const [imageContext, setImageContext] = React.useState(false);

  const modelOptions = [
    { value: "auto", label: "自動", description: "内容に合わせて選択" },
    { value: "fast", label: "高速", description: "短い返答を優先" },
    { value: "deep", label: "推論", description: "複雑な確認向け" },
  ];

  return (
    <ChatInput
      onSend={(message, files) => {
        setIsProcessing(true);
        console.log({ message, files });
      }}
      onStop={() => setIsProcessing(false)}
      isProcessing={isProcessing}
      placeholder="確認したい内容を入力..."
      optionsContent={
        <div className="space-y-3">
          <p className="text-sm font-semibold">入力オプション</p>
          <label className="flex items-center justify-between gap-3 rounded-md border px-3 py-2 text-sm">
            <span>Web を参照</span>
            <Switch checked={webSearch} onCheckedChange={setWebSearch} />
          </label>
          <label className="flex items-center justify-between gap-3 rounded-md border px-3 py-2 text-sm">
            <span>画像を参照</span>
            <Switch checked={imageContext} onCheckedChange={setImageContext} />
          </label>
        </div>
      }
      modelOptions={modelOptions}
      modelValue={model}
      onModelValueChange={setModel}
      labels={{
        attach: "ファイルを添付",
        options: "入力オプション",
        model: "モデルを選択",
        voice: "音声入力",
        voiceActive: "録音を停止",
        send: "送信",
        stop: "停止",
        removeAttachment: "添付を削除",
        emptyMessage: "メッセージを入力すると送信できます。",
      }}
    />
  );
}

設計の判断(UIXHERO)

「いつ・なぜ使うか」の判断は、姉妹サイト UIXHERO の記事で解説しています。