Website
Conversation
Conversation threads, answers, citations, composers and floating chat surfaces.
Usage
When to reach for it
Ships from@misoto22/design/website
import { ConversationLayout } from '@misoto22/design/website'Notes
A reading-width conversation with a separate, sticky evidence rail.
Best practices
Do
- Supply localized labels, descriptive links and meaningful image alternatives.
Don’t
- Do not put service credentials, routing logic or backend models inside presentation components.
Examples
a local conversation
The host owns the questions and rendered answer nodes while the composition owns their reading order. This local example records questions without calling an assistant service.
Explore the library
Try a question to preview the conversation layout.
Start with
Parts
Composed at the call site rather than configured through props, so a layout this component did not anticipate is still expressible.
ConversationFacts
| Prop | Type | Default | Description |
|---|---|---|---|
| itemsrequired | DescriptionListItem[] | — |
Also accepts everything in HTMLAttributes<HTMLDListElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationSuggestions
| Prop | Type | Default | Description |
|---|---|---|---|
| itemsrequired | ConversationSuggestion[] | — | |
| labelrequired | string | — |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationThread
Host owns turns and folding; this composition owns their hierarchy and controls.
| Prop | Type | Default | Description |
|---|---|---|---|
| composerrequired | ReactNode | — | |
| hasTurnsrequired | boolean | — | |
| labelrequired | string | — | |
| controls | ConversationControl[] | [] | — |
| intro | { title: ReactNode; description: ReactNode; suggestionsLabel: string; suggestions: ConversationSuggestion[] } | — | |
| proposal | ReactNode | — | |
| summary | ReactNode | — |
Also accepts everything in HTMLAttributes<HTMLElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationLog
| Prop | Type | Default | Description |
|---|---|---|---|
| compact | boolean | — |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
QuestionComposer
A controlled, labelled composer. Request limits and sending remain host concerns.
| Prop | Type | Default | Description |
|---|---|---|---|
| idrequired | string | — | |
| labelrequired | string | — | |
| onSubmitrequired | () => void | — | |
| onValueChangerequired | (value: string) => void | — | |
| submitLabelrequired | string | — | |
| valuerequired | string | — | |
| actions | ReactNode | — | |
| compact | boolean | — | |
| counter | ReactNode | — | |
| disabled | boolean | — | |
| hideHint | boolean | — | |
| hideLabel | boolean | — | |
| hint | ReactNode | — | |
| inputRef | Ref<HTMLInputElement> | — | |
| maxLength | number | — | |
| pending | boolean | — | |
| placeholder | string | — | |
| submitDisabled | boolean | — |
Also accepts everything in Omit<HTMLAttributes<HTMLFormElement>, 'onSubmit'>. Those are forwarded to the underlying element and are not listed row by row.
ConversationTurn
| Prop | Type | Default | Description |
|---|---|---|---|
| bodyIdrequired | string | — | |
| expandedrequired | boolean | — | |
| onTogglerequired | () => void | — | |
| titlerequired | ReactNode | — | |
| metadata | ReactNode | — | |
| preview | ReactNode | — |
Also accepts everything in Omit<HTMLAttributes<HTMLElement>, 'title'>. Those are forwarded to the underlying element and are not listed row by row.
ConversationQuote
| Prop | Type | Default | Description |
|---|---|---|---|
| labelrequired | string | — | |
| compact | boolean | — |
Also accepts everything in HTMLAttributes<HTMLElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationAnswer
| Prop | Type | Default | Description |
|---|---|---|---|
| questionrequired | ReactNode | — | |
| questionLabelrequired | string | — | |
| quote | ReactNode | — |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationProse
Trusted React nodes from the host's sanitized answer parser, never raw model HTML.
Takes no props of its own.
ConversationAnswerHeading
Model-generated headings are prose labels, so they do not alter the page outline.
Takes no props of its own.
StreamingCaret
Takes no props of its own.
ConversationSources
| Prop | Type | Default | Description |
|---|---|---|---|
| countrequired | ReactNode | — | |
| itemsrequired | ConversationSource[] | — | |
| labelrequired | string | — |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
ActionProposal
| Prop | Type | Default | Description |
|---|---|---|---|
| approveLabelrequired | string | — | |
| destinationrequired | ReactNode | — | |
| dismissLabelrequired | string | — | |
| labelrequired | string | — | |
| onApproverequired | () => void | — | |
| onDismissrequired | () => void | — | |
| approvalAttributes | Record<`data-${string}`, string> | — | |
| detail | ReactNode | — |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationLauncher
| Prop | Type | Default | Description |
|---|---|---|---|
| visiblerequired | boolean | — | |
| buttonRef | Ref<HTMLButtonElement> | — |
Also accepts everything in ButtonHTMLAttributes<HTMLButtonElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationDock
The host supplies placement, dismissal and stream state; the dock draws them.
| Prop | Type | Default | Description |
|---|---|---|---|
| cardrequired | boolean | — | |
| closeLabelrequired | string | — | |
| composerrequired | ReactNode | — | |
| cornerrequired | ConversationDockCorner | — | |
| labelrequired | string | — | |
| onCloserequired | () => void | — | |
| openrequired | boolean | — | |
| roomLinkrequired | ReactElement | — | |
| dragging | boolean | — | |
| handles | ReactNode | — | |
| logRef | Ref<HTMLDivElement> | — | |
| moving | boolean | — | |
| notice | ReactNode | — | |
| onHeaderPointerDown | (event: PointerEvent<HTMLElement>) => void | — | |
| panelRef | Ref<HTMLElement> | — | |
| proposal | ReactNode | — |
Also accepts everything in HTMLAttributes<HTMLElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationDockWelcome
| Prop | Type | Default | Description |
|---|---|---|---|
| leadrequired | ReactNode | — | |
| suggestionsrequired | ConversationSuggestion[] | — | |
| suggestionsLabelrequired | string | — |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationResizeHandle
Keyboard equivalents for the host's pointer resize controller.
| Prop | Type | Default | Description |
|---|---|---|---|
| axisrequired | 'size-vertical' | 'size-horizontal' | — | |
| draggingrequired | boolean | — | |
| labelrequired | string | — | |
| onNudgerequired | (axis: 'size-vertical' | 'size-horizontal', delta: number) => void | — | |
| onStartrequired | (axis: 'size-vertical' | 'size-horizontal', event: PointerEvent<HTMLElement>) => void | — | |
| siderequired | 'top' | 'bottom' | 'left' | 'right' | — |
SelectionToolbar
Selection actions with a real toolbar's single tab stop and arrow navigation.
| Prop | Type | Default | Description |
|---|---|---|---|
| actionsrequired | SelectionToolbarAction[] | — | |
| floatingrequired | boolean | — | |
| labelrequired | string | — | |
| style | CSSProperties | — | |
| toolbarRef | Ref<HTMLDivElement> | — |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
ConversationRoomLink
A router link keeps its own destination and behavior inside a standard action.
Takes no props of its own.
Types
export type ConversationDockCorner = 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'