ttolbel UI

Component

AI chat box

A rounded composer with multiline input and a bottom toolbar: attach, mode pill, model selector, voice, and send. Type / to add capability pills inline in the input (modes, agents, tools). Pick the model from the model dropdown, not slash. Backspace removes the last pill.

Standalone

0/500
ai chat box.tsx
<NativeAIChatBox
  modes={[
    { id: "search", label: "Search", group: "Modes", icon: <MagnifyingGlass size={14} /> },
    { id: "research", label: "Research", group: "Agents" },
  ]}
  models={[{ id: "gpt-4o", label: "GPT-4o" }, { id: "fast", label: "Fast" }]}
  slashCommands={[
    { id: "search", label: "Search", group: "Modes" },
    { id: "research", label: "Research", group: "Agents" },
    { id: "web", label: "Web search", group: "Tools" },
  ]}
  placeholder="Type / for search modes"
  onSend={async (text, files, { modeId, modelId, commands }) => {
    await sendToBackend({ text, files, modeId, modelId, commands });
  }}
  onStop={cancelStream}
/>

Example

Docked beneath a support thread. Slash pills sit in the input; mode and model are chosen from the toolbar.

0/280
ai-chat-box-example.tsx
<SupportThread messages={messages} onReplyTo={setReplyTo} />
<NativeAIChatBox
  modes={modes}
  models={models}
  slashCommands={slashCommands}
  replyTo={replyTo}
  onClearReply={() => setReplyTo(null)}
  isTyping={assistantTyping}
  isStreaming={streamOpen}
  onSend={onSendMessage}
  onStop={cancelStream}
/>

Capabilities

PropTypeDescription
onSendrequired(text: string, files: File[], meta?: NativeAIChatSendMeta) => Promise<void>-
onStop() => void-
onDraftChange(text: string) => void-
onSlashSelect(command: NativeAIChatSlashCommand) => void-
onVoicePress() => void-
onModeChange(modeId: string) => void-
onModelChange(modelId: string) => void-
placeholderstring-
disabledboolean-
classNamestring-
modesNativeAIChatMode[]-
modelsNativeAIChatModel[]-
slashCommandsNativeAIChatSlashCommand[]-
activeModeIdstring-
activeModelIdstring-
replyToNativeAIChatReplyContext | null-
onClearReply() => void-
isTypingboolean-
isStreamingboolean-
maxCharactersnumber-
maxAttachmentsnumber-
footerTextstring-
showFooterboolean-
showAttachmentsboolean-
showVoiceboolean-
initialTextstring-