SuggestionBar
StableA bar under an AI draft. Nothing changes in your document until you choose.
Also known as inline suggestion, accept reject bar
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Try each button
Draft ready. Nothing is added until you choose.
Choose what to do.
const [status, setStatus] = useState<SuggestionBarStatus>("ready");
<SuggestionBar status={status} retryCost="Uses 1 AI response"
onKeep={() => setStatus("committed")} onInsertBelow={() => setStatus("committed")}
onDiscard={() => setStatus("discarded")}
onRegenerate={() => setStatus("generating")}
onRefine={(text) => setStatus("generating")}>
Our quarterly numbers beat the forecast, driven by steady renewals and two large new accounts.
</SuggestionBar>Try each button. Regenerate and Fine-tune show a short wait. Keep and Discard finish it.
When to use it
Sits under an AI draft that has not been added yet. Nothing changes in the document until the person chooses, and Regenerate and Fine-tune are kept clearly apart.
Made of: Draft preview · Main button · Insert below · Regenerate · Cost of trying again · Discard · Fine-tune box · Spoken update
Use it for
- A draft paragraph the AI wrote for a document.
- Replacing selected text with a rewrite, with Replace as the main button.
- Showing what another try costs when tries count against a limit.
Not for
- One small edit with a before and after: use SuggestionCard.
- An action the assistant wants to take that needs a yes: use ApprovalPrompt.
- A suggested ending to the line being typed: use GhostText.
Do and avoid
Draft ready. Nothing is added until you choose.
Draft ready. Nothing is added until you choose.
Do
- Keep the draft out of the document until the person chooses Keep, Replace or Insert below.
- Show what another try costs when tries count against a limit.
- Call the box Fine-tune this and the button Regenerate, so they are not confused.
- Return the cursor to the document after Keep or Discard.
Avoid
- Do not add the draft just because time passed or the person clicked away.
- Do not call a request for a change Regenerate.
- Do not hide Discard. Closing the bar should never be the only way out.
On a phone
- The buttons wrap onto new rows, and Discard moves to the right edge of its row.
- The Fine-tune field is 16px on touch screens, so the page does not zoom when it takes focus, The field grows to 44px tall, and the Send button keeps its size and has a 44px tap area.
- The long placeholder is cut off in a narrow field. The bar does not move above the on-screen keyboard, so place it where the keyboard will not cover it.
Seen in products
- Notion offers accept, discard, insert below, or try again. Each Try again counts as another AI response against the free limit.
- Google Docs offers Replace, Insert (below), or Close, which discards.
- Word Copilot offers Keep it, Regenerate and Discard, plus a compose box for Fine tune this draft.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| status | "generating" | "ready" | "committed" | "discarded" | "ready" | Where the staged output is. The consumer owns this state. |
| children | ReactNode | none | Optional preview of the staged output. |
| primaryLabel | string | "Keep" | Label of the primary action. Use Replace over a selection. |
| onKeep / onInsertBelow / onDiscard | () => void | none | Commit, commit as a new block below, or drop the draft. |
| onRegenerate | () => void | none | Ask for a fresh sample of the same request. |
| onRefine | (instruction: string) => void | none | Send a follow-up instruction typed in the Fine-tune field. |
| retryCost | ReactNode | none | Cost of a retry, shown next to Regenerate. |
| labels | Partial<Record<string, string>> | none | Overrides for every piece of copy, including the status messages. |
| className | string | none | Extra classes on the container. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one SuggestionBar switches all of this from its properties panel, across 4 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Status | status | Generating, Ready, Committed, Discarded |
| Text | children | Any text |
| RetryCost | retryCost | Any text |
Tokens
Change one of these and every part that uses it follows.
--surface--surface-sunken--border--lime--on-lime--fg-subtle--radius-field--radius-card
Built in
- Status changes, such as "Added to the document", are announced to screen readers separately from the draft.
- While the draft is being written, the spinner is named "Writing a draft" for screen readers. The draft text itself is not read out as it changes.
- The Fine-tune box has a name, and its send button is turned off while the box is empty.
- Every action is a real button, in reading order.
- Keyboard focus follows the buttons as they change: to Discard while a new draft is written, to the main action when it is ready, and back to the document after Keep, Replace, Insert below or Discard (the nearest text box or editor, else the bar itself). Pass focusAfter to choose the place.
What you need to do
- Set status to generating while a new draft is written and back to ready when it is done, so screen readers hear the right update.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide