Components · Inputs
Composer
The message box at the bottom of a conversation, with the input, its tools, attachments, @ suggestions and the pink send button inside one ink border.
import { Composer } from "@botiverse/raft-ui";The composer is where people write a message: at the bottom of a channel, a direct message, a thread or a task's thread. One ink border holds the input, the tools, any attachments and the pink send button. Typing @ opens a list of people and agents above it.
When to use
| Situation | Use |
|---|---|
| Sending a message in a conversation | Composer |
| Several lines of text saved with a form | Textarea |
| One line of text | Input |
Where the composer sits in a conversation is in Conversation.
Anatomy
ComposerRoot: the<form>that submits the message. Required.Composer: the box with the ink border. Required.ComposerAttachmentswith oneComposerAttachmentper file: 64px thumbnails inside the box, above the input. Optional.SortableComposerAttachmentslets people reorder them.ComposerInput: the input, a<textarea>that grows with its content. Required.ComposerToolbar: the row under the input, with:ComposerActions: the tools at the start, each aComposerIconButton(attach a file, add an image);ComposerMeta: at the end, an option attached to sending (ComposerToolbarLabelwith a Checkbox) andComposerSubmit, the send button.
ComposerSuggestionListand its parts, driven byuseComposerSuggestions: the @ suggestions above the box.ComposerDropOverlay: what the box shows while files are dragged over it.- @ delegation chips (desktop): a row of agents that puts an @ mention into the input when one is clicked. raft-ui has no part for it yet.
States
- Uploading: a thumbnail shows cyan progress on its own track, inset from its edges (Shape); × in its corner cancels the upload while it runs and removes the file after. File cards are in MessageAttachment.
- Nothing to send: disable
ComposerSubmituntil there is text or an attachment. - Focus: the whole composer takes the focus ring (States).
Behavior
- Typing @ opens the suggestion list above the composer, as wide as the composer and 8px above it. Group it with members of this conversation first, then the others. Each row shows the avatar, the name and the status in
foreground-hint. - Let people drag files into the composer, but not folders.
- Grow the input with its content up to a maximum height, then scroll inside it.
- On a phone, keep the composer on top of the keyboard when the keyboard opens. Return inserts a new line on a phone held upright (Responsive layout), so sending uses the send button.
- Put the composer's border on the content margin (Page structure), with 16px plus the safe area below it.
Content
- Make the placeholder say where the message goes: Message #launch-week. Use the same words as the input's
aria-label.
Accessibility
Composer has no Base UI primitive: it renders a native <form> and <textarea>. useComposerSuggestions adds the combobox pattern to the input: aria-controls points at the listbox, aria-activedescendant at the highlighted option. Arrow Up and Arrow Down move the highlight, Enter or Tab picks it, and Esc closes the list.
- Give
ComposerInputanaria-labelthat names the destination (Message #launch-week). - Give every
ComposerIconButtonand an icon-onlyComposerSubmitanaria-label(Attach File, Send). - Give the suggestion list an
aria-labeloraria-labelledby.
Rules
- Count the send button as the screen's pink button (Button). On a phone it is a pink icon button; on desktop it may carry a label (Send ↵).
- Draw one ink border around the whole group. The tools and chips inside it have none:
ComposerIconButtonis frameless, and delegation chips sit onfill-muted. - Keep the input text
text-bodyat regular weight wherever the composer sits (a channel, a thread, a comment on an attachment, a forward). Don't let it inherit the surrounding type. Make tool iconsforeground-muted. - Under a scrolling region, such as a comment on an attachment or a note added to a forward, use a compact composer: a
line-seamabove it, 12px of space around it, and no fill of its own.
API
Composer, ComposerActions, ComposerAttachment, ComposerAttachmentBody, ComposerAttachmentFailedOverlay, ComposerAttachmentFile, ComposerAttachmentImage, ComposerAttachmentMeta, ComposerAttachmentRemove, ComposerAttachments
| Prop | Type | Default |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerAttachmentsScrollArea
Takes the attributes of its element.
ComposerAttachmentTitle, ComposerAttachmentUploadingOverlay
| Prop | Type | Default |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerAttachmentUploadProgressBar
| Prop | Type | Default |
|---|---|---|
| number | ||
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerDropOverlay, ComposerDropOverlayLabel, ComposerDropOverlayPrompt
| Prop | Type | Default |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerIconButton
| Prop | Type | Default |
|---|---|---|
| boolean | ||
| string | ||
| Whether the button should be focusable when disabled. | boolean | false |
| Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). | boolean | true |
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerInput, ComposerMeta, ComposerRoot
| Prop | Type | Default |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerSubmit
| Prop | Type | Default |
|---|---|---|
| boolean | ||
| string | ||
| "xs" | "sm" | "md" | "lg" | "xl" | "inline" | "icon-xs" | "icon-sm" | "icon-md" | "icon-lg" | ||
| Whether the button should be focusable when disabled. | boolean | false |
| Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). | boolean | true |
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerSuggestionAside, ComposerSuggestionContent
| Prop | Type | Default |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerSuggestionGroup
| Prop | Type | Default |
|---|---|---|
| boolean | false | |
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerSuggestionGroupLabel
| Prop | Type | Default |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerSuggestionIcon
| Prop | Type | Default |
|---|---|---|
| "inline" | "avatar" | "framed" | "auxiliary" | "avatar" | |
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerSuggestionList
| Prop | Type | Default |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerSuggestionMeta
| Prop | Type | Default |
|---|---|---|
| "code" | "text" | "text" | |
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
ComposerSuggestionOption, ComposerSuggestionTitle, ComposerToolbar, ComposerToolbarLabel
| Prop | Type | Default |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
SortableComposerAttachment
| Prop | Type | Default |
|---|---|---|
| ReactNode | ||
| string | ||
| string |
SortableComposerAttachments, SortableComposerAttachmentsScroll
| Prop | Type | Default |
|---|---|---|
| ReactNode | ||
| readonly string[] | ||
| (items: string[]) => void |
Related
Changes
- 0.1.0 · AddedGraduated
AppRail,AppShell(with sidebar collapse trigger),ChatSidebar,Composer(including sortable attachments), andResizable*to the stable entry.