Getting Started
Components
- Accordion
- Advanced Toast
- AlertMessage
- ArrowButton
- Arrows
- Avatar
- Backdrop
- Basic Toast
- Breadcrumb
- Button
- CardBackground
- Card
- Carousel
- Chapters
- ChatBody
- ChatButton
- ChatHeader
- ChatInput
- ChatMessageActions
- ChatMessageEditor
- ChatMessage
- ChatTypingIndicator
- ChatWindowCsatPrompt
- ChatWindowQuote
- ChatWindow
- CheckboxSelect
- Checkbox
- Checkboxes
- Chip
- ChoiceExpander
- Clickable
- ContentReview
- Countdown
- CriteriaDates
- CriteriaParticipants
- CriteriaTransports
- Date Field
- Datepicker
- Dropdown
- ElasticHeight
- ExpandableCard
- ExpandableText
- Filter
- FloatingLabelTextField
- Form Control
- Form Label
- Frame
- HamburgerIcon
- Heading
- Image
- JourneyCard
- LayerHeader
- Layer
- Link
- Loader
- Number Field
- PageNavigation
- Pagination
- Paragraph
- Password
- Phone Field
- Popin
- Portal
- ProductThumbnail
- Promises
- Prose
- Radio Group
- RadioSelect
- Radio
- Range
- Scrollbar
- Select
- SidebarLayout
- SliderFrame
- SparkleWrapper
- Spinner
- Switch
- Table
- Tabs
- Tag
- TextField
- Toggle
- Tooltip
- ValidationMessage
'use client';
import { useState } from 'react';
import { ChatInput } from '@/ui/ChatInput';
export function ChatInputDemo() {
const [value, setValue] = useState('');
return (
<div className="w-[380px]">
<ChatInput
aria-label="Chat message input"
value={value}
onValueChange={setValue}
onSubmit={() => setValue('')}
onAudioClick={() => {}}
/>
</div>
);
}
Installation
npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/chat-input.json
Usage
import { ChatInput } from '@/ui/ChatInput';
import { useState } from 'react';
export function Component() {
const [value, setValue] = useState('');
return (
<ChatInput
value={value}
onValueChange={setValue}
onSubmit={() => {
console.log('Submitted:', value);
setValue('');
}}
onAudioClick={() => console.log('Audio clicked')}
/>
);
}Stop while an answer is generated
While isStreaming is true, submitting is disabled and the send button becomes a stop button
that calls onStop. Set it when you start generating the answer, and reset it when the answer is
complete or stopped.
'use client';
import { useRef, useState } from 'react';
import { ChatInput } from '@/ui/ChatInput';
export function ChatInputStreamingDemo() {
const [value, setValue] = useState('');
const [isStreaming, setIsStreaming] = useState(false);
const timer = useRef<ReturnType<typeof setTimeout>>(undefined);
function send() {
setValue('');
setIsStreaming(true);
// Simulates an answer being generated for 4 seconds
timer.current = setTimeout(() => setIsStreaming(false), 4000);
}
function stop() {
clearTimeout(timer.current);
setIsStreaming(false);
}
return (
<div className="w-[380px]">
<ChatInput
aria-label="Chat message input"
value={value}
onValueChange={setValue}
onSubmit={send}
isStreaming={isStreaming}
onStop={stop}
/>
</div>
);
}
Submit with Enter
By default Ctrl/Cmd + Enter submits and Enter adds a
line break. Set submitKey="enter" for the usual chat behavior: Enter submits and
Shift + Enter adds a line break (Ctrl/Cmd + Enter
still submits).
'use client';
import { useState } from 'react';
import { ChatInput } from '@/ui/ChatInput';
export function ChatInputSubmitOnEnterDemo() {
const [value, setValue] = useState('');
return (
<div className="w-[380px]">
<ChatInput
aria-label="Chat message input"
value={value}
onValueChange={setValue}
onSubmit={() => setValue('')}
submitKey="enter"
/>
</div>
);
}
submitKey | Enter | Shift + Enter | Ctrl/Cmd + Enter |
|---|---|---|---|
"mod+enter" (default) | line break | line break | submits |
"enter" | submits | line break | submits |
The Enter that validates a text being composed with an IME (Japanese, Chinese…) never submits.
API Reference
ChatInput
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Required. Controlled input value |
onValueChange | (value: string) => void | — | Required. Called on every keystroke |
onSubmit | () => void | — | Required. Called when the form is submitted |
placeholder | string | "Ask a question?" | Input placeholder text (also used as aria-label) |
submitKey | "mod+enter" | "enter" | "mod+enter" | Keyboard shortcut that submits the message, see Submit with Enter |
isStreaming | boolean | false | While true, submitting is disabled and the send button becomes a stop button |
onStop | () => void | undefined | Called when the stop button, shown while isStreaming, is clicked |
onAudioClick | () => void | undefined | Enables the microphone button. The browser speech recognition is used when available, this is the fallback otherwise |
className | string | undefined | Additional CSS classes on the <form> element |
Inherits all HTMLFormElement attributes.
Notes
- The send button is disabled when the input is empty or whitespace only.
- The microphone button, and the browser speech recognition behind it, are only enabled when
onAudioClickis provided. - While
isStreamingistrue, neither the send button nor the keyboard shortcut submits. - The component is fully controlled — manage state externally.
- Used as the bottom bar inside
ChatWindow.