Email draftPro
A draft email the assistant writes and you finish in the thread, sent with a few seconds to undo.
On this page
Installation
Usage
import { EmailDraft } from "@/components/ui/chatcn/pro/email-draft"
<EmailDraft
value={draft}
onValueChange={setDraft}
status={streaming ? "drafting" : "ready"}
from="ines@tavares.pt"
onSend={(draft) => sendMail(draft)}
/>The value holds to, cc, subject and body. While status is drafting the body can stream in and every field is read only; the header shows the only shimmer the kit allows. Once it settles, that version is kept as the original: any edit shows Edited in the header with Revert to draft, so the assistant's wording is one click away. Pass original to set it yourself.
Recipients are chips. Enter, comma, Tab or leaving the field turns text into chips, a pasted list splits into several, and Backspace on an empty field takes the last chip back for editing. An address that is not one stays as a red chip with the fix in words, and Send waits until it is fixed or removed.
Send starts an undo window (undoSeconds, default 5): a hairline of accent drains across the footer and Undo takes the place of Send. Then onSend runs; a rejection keeps the draft and says what to do. Open in mail app is a mailto link with every field, or your own handler with onOpenInClient. Render it inside the card your host draws for a widget answer. It fills the width it is given, so a comfortable max width (around 28 rem) comes from the card, and it follows the host theme through the kit tokens. Pass onExpand where the host can go full screen.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
value, defaultValue, onValueChange | { to, cc, subject, body } | Recipients are { email, name? } |
original | EmailDraftValue | For Edited and Revert. Defaults to the settled draft |
status | "drafting" | "ready" | "sent" | Default ready |
onSend | (draft) => unknown | Promise | Runs after the undo window |
undoSeconds | number | Default 5; 0 sends at once |
onOpenInClient | (draft) => void | Replaces the mailto link |
from, attachments, sentAt | attachments are { name, size? } | |
bodyLines | number | Lines before a long body folds. Default 10 |
locale, disabled | ||
labels | Partial<…Labels> | Every string the widget writes, for translation |
Labels
labels covers the header (titleTo(names)), field names and placeholders, chip removal (remove(who)), the address error (invalid(email)), drafting, Edited and Revert, the fold, Send, the undo countdown (sendingIn(seconds)), sent and failed lines and join for name lists.
Keyboard
| Key | Action |
|---|---|
| Enter, comma or Tab in To or Cc | Turn the text into a chip |
| Backspace in an empty To or Cc | Take the last chip back to edit it |
| Tab | To, Cc, subject, body, then Open in mail app and Send |
| Enter or Space on Undo | Cancel the send while the hairline drains |
Accessibility
- Every field has a visible label. A bad address sets
aria-invalidon its field and the error is linked to it. - Chips name the person and, for screen readers, the address; each has a labelled remove button.
- The undo countdown is a polite live region. Sent is a status message.
- The IME guard keeps Enter from committing a chip mid composition.
Motion
The drain is a linear scale over the undo window, because it is a timer. The sent line enters with a 220 ms fade from 0.96. Reduced motion keeps the countdown text and drops the drain.