On this page
Import
import { Composer } from '@envsemble/envui';
Usage
A Composer is a native textarea with no visible label, so name it with aria-label or aria-labelledby. Enter or the send button passes the text to onSend; blank text never sends, and neither does a disabled, running or pending composer.
- Leave it uncontrolled, with
defaultValue, and it clears after each send and when its form resets. - Or control it with
valueandonValueChange, and clear it yourself.
import { useEffect, useRef, useState } from 'react';
import { Composer, Column, Text } from '@envsemble/envui';
export default function AskAnything() {
const [draft, setDraft] = useState('');
const [sent, setSent] = useState('');
const [running, setRunning] = useState(false);
const timer = useRef<number>(undefined);
useEffect(() => () => window.clearTimeout(timer.current), []);
const send = (text: string) => {
setSent(text);
setDraft('');
setRunning(true);
// Stands in for a reply that streams for a few seconds.
timer.current = window.setTimeout(() => setRunning(false), 4000);
};
const stop = () => {
window.clearTimeout(timer.current);
setRunning(false);
};
return (
// As wide as a conversation column.
<Column gap={3} style={{ inlineSize: 'min(100%, 32rem)' }}>
<Composer
aria-label="Message"
placeholder="Ask anything"
value={draft}
onValueChange={setDraft}
onSend={send}
running={running}
onStop={stop}
/>
<Text variant="caption" emphasis="muted" role="status">
{running ? 'Replying…' : sent ? `Sent: ${sent}` : ''}
</Text>
</Column>
);
}Pending and running
pending marks a send in progress: the send button shows a spinner and sending is unavailable, while the field stays editable and keeps focus, so use it rather than disabled. running marks a reply on its way: the send button becomes a stop button, which calls onStop and stays available when the field is disabled, and Enter doesn't send.
<Composer aria-label="Reply to Priya Shah" pending={sending} onSend={send} />
<Composer aria-label="Message" running={replying} onSend={send} onStop={stop} />
Sent by its form
Without onSend, Enter and the send button submit the composer's form, which sends the text under its name.
<form onSubmit={submit}>
<Composer name="note" aria-label="Note" placeholder="Add a note to the plan" />
</form>
Rows, start and description
The field shows minRows lines while empty, 1 by default, and grows to maxRows, 8 by default, before it scrolls. start holds content at the start of the action row, such as an attach button or the name of a model, and description supporting text below the composer, which describes the field. sendLabel and stopLabel name the button.
<Composer
aria-label="Comment"
minRows={2}
maxRows={6}
start={<IconButton variant="text" icon={<IconAttachFile />} aria-label="Attach files" />}
description="Files up to 10 MB."
onSend={addComment}
/>
Composition
Place the composer below the MessageList it adds to.
Customize
The composer, env-composer, is on the raised popup surface, env-composer-surface, which holds the input, env-composer-input, the start content, env-composer-start, and the send button, env-composer-action; the footer, env-composer-footer, sits below it.
Accessibility
You provide
- An
aria-labelthat names the field. - An announcement of the reply, or of a message that couldn't be sent.
sendLabelandstopLabelin the application's language.
envUI provides
- A native
textareadescribed by the footer. - A send button named Send or Stop, which stays focusable as it changes.
- Focus back in the field after a send.
- Enter that leaves input method composition alone.
Props
Composer
The message field of a conversation: a multiline field on a raised surface that grows with its text up to maxRows, with a send button at the end that becomes a stop button while running. Enter submits, Shift+Enter starts a new line and an input method's composition never submits. Without onSend, Enter and the send button submit the field's form.
| Prop | Type | Description |
|---|---|---|
value | string | The message text of a controlled composer. |
defaultValueDefault '' | string | The starting text of an uncontrolled composer; it clears after each send through onSend and when its form resets. |
onValueChange | ( | Receives the text as it changes, and an empty string when an uncontrolled composer clears. |
onSend | ( | Enter or the send button submits the text as typed, and an uncontrolled composer clears. Blank text never submits, and neither does a disabled, running or pending composer. Without onSend, they submit the field's form instead and the text stays until the form resets. Without onSend or a form there is nothing to send: the button is unavailable and Enter starts a new line. |
pendingDefault false | boolean | A send is in progress, such as a request the application makes: the send button shows a spinner and sending is unavailable, while the field keeps its text, stays editable and keeps focus. The pending action of an enclosing form counts too; set pending for a form the field joins through its form attribute, or for a request of the application's own. |
runningDefault false | boolean | A reply is on its way: the send button becomes a stop button and Enter does not submit. |
onStop | ( | Called by the stop button while running; it stays available when the field is disabled. |
sendLabelDefault 'Send', or EnvUIProvider's messages.composer.send | string | Accessible name of the send button. |
stopLabelDefault 'Stop', or EnvUIProvider's messages.composer.stop | string | Accessible name of the stop button. |
minRowsDefault 1 | number | Lines the field shows while empty; 1 by default. |
maxRowsDefault 8 | number | Lines the field grows to before it scrolls; 8 by default. |
start | ReactNode | Content at the start of the action row, such as an attach button or the name of a model. |
description | ReactNode | Supporting text below the composer, such as a note on attachments; it describes the field. |
aria-label | string | Required when aria-labelledby is not set. Names the field, which has no visible label, such as "Message"; this or aria-labelledby. |
aria-labelledby | string | Required when aria-label is not set. The id of visible text that names the field; this or aria-label. |
Also accepts the native props of <textarea>, such as ref, className and aria-* attributes.
Part names
Each part's class and state attributes are public and versioned, for an application's CSS to style.
env-composer- The message composer.
env-composer-action- The send or stop button.
env-composer-footer- The row of actions under the input.
env-composer-input- The text input.
env-composer-start- The actions at the start of the footer.
env-composer-surface- The surface around the input and the footer.
data-disabled- Present
data-running- Present
data-start- Present
Strings
EnvUIProvider's messages overrides each, and a component's own label prop wins over it.
messages.composer.send"Send"The send button's name.messages.composer.stop"Stop"The stop button's name while a reply is generated.
Changelog
- 1.0.0
footerisdescription, as on a field, since it describes the field.onSubmitisonSend, which pairs withsendLabeland leaves the native submit event's name alone. The send and stop labels come from EnvUIProvider'smessages, unlesssendLabelandstopLabelset them.