OutlineEditor
StableThe plan of a deck before any slide is built: the AI drafts it, the person edits, reorders and approves it.
Also known as outline, deck outline
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Draft, edit and build
Outline
2 slidesAI is draftingSlides appear as they are written. You can edit each one once it is complete.
Overview, drafted by AI
A six-slide quarterly review of Larkspur Outdoor for the board, from your sales sheet, supplier notes and survey summary.
- Q3 sales.xlsx
Drafted by AISales by region
The north grew fastest; the coast was flat.
- Q3 sales.xlsx, sheet 2
Still writing this slide
const [items, setItems] = useState<OutlineItem[]>([]);
const [state, setState] = useState<OutlineState>("drafting");
<OutlineEditor
items={items}
state={state}
pendingId={writingId} // the slide the AI is still writing
overview={<p>A six-slide quarterly review of Larkspur Outdoor for the board…</p>}
onItemsChange={setItems}
onStateChange={setState} // "ready" becomes "edited" on the first edit
onUpdate={() => redraftAround(items)}
onBuild={() => buildSlides(items)}
estimate={`${items.length} slides, about ${items.length * 5} credits`}
maxItems={12}
/>Slides stream in title first, and only the one being written is read-only. Edit any title and the badge changes to Edited by you, with Update outline beside Build slides. Lock a slide to keep it when updating. Build moves to Approved, then Building.
When to use it
Lets a person co-write the plan of a deck with the AI, and decide when it is good enough to build.
Made of: Heading and slide count · State badge · State note or error · AI overview · Slide rows: number, title, description, sources, who wrote it, Move up, Move down, Add after, Lock, Remove · Undo remove bar · Add slide · Build slides, Update outline and the estimate
Use it for
- The step between a brief and a built deck, where the person checks the slide list.
- Any generated document with sections the person may want to reorder, add or remove before the full text is written.
- Redrafting a plan around the person's edits while keeping the slides they locked.
Not for
- A fixed plan of agent steps to approve or send back: use PlanCard.
- Progress while the slides are being built: use GenerationProgress.
- Correcting one value the AI filled in: use InlineEdit.
Do and avoid
Q3 review
3 slidesReady to build- Drafted by AI
- Drafted by AI
- Added by you
Q3 review
3 slidesBuilding slidesBuilding slides from this outline. It can no longer be changed here.
Q3 at a glance
Sales up 9 percent, two new stores.
Drafted by AISales by region
The north grew fastest.
Drafted by AIPlan for Q4
Holiday stock and hiring.
Added by you
Do
- Offer Update outline and Build slides side by side once the person has edited, so they choose whether to redraft.
- Show where each slide's content comes from, and which slides the AI wrote.
- Keep the slides the person edited or locked when the outline is redrafted.
- Show the estimate next to Build, from your own code.
Avoid
- Don't build automatically when drafting finishes; the person approves first.
- Don't colour the person's own slides, the Build button or the whole outline with the AI colour. Only the AI marks and the working edge use it.
- Don't animate each word as it streams in. One calm working edge is enough.
- Don't let an empty title through. Screen-reader users move through a deck by its titles.
On a phone
- One column. The description folds under the title behind a Description button, and opens by itself when the row has an error.
- Move up, Move down, Add after, Lock and Remove are 44px on touch screens. Reorder works with these buttons; there is no drag.
- Build slides and Update outline sit in a bar that sticks to the bottom of the screen, above the safe area, and share the width.
Seen in products
- Gemini in Google Slides shows a plan of slides with sources, and an Update plan action after edits.
- Gamma lets people edit the outline freely before generating cards (third-party review).
- Gemini's help does not list reordering the plan, so not every product offers it.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| itemsrequired | OutlineItem[] | none | The slides, in order. Each has id, title, and optionally description, sources, locked, origin ("ai" or "person") and edited. |
| staterequired | "drafting" | "ready" | "edited" | "updating" | "approved" | "building" | "failed" | none | Where the outline is. Edits are allowed in drafting (finished slides), ready, edited and failed. |
| onItemsChangerequired | (items: OutlineItem[]) => void | none | Called with the new list after every edit, insert, remove, reorder, undo or lock. |
| onBuildrequired | () => void | none | Approve and build. Only called when every slide has a title. |
| onUpdate | () => void | none | Redraft the unlocked slides around the person's edits. Adds Update outline while edited, Try again when failed, and the Lock buttons. |
| onStateChange | (state: OutlineState) => void | none | Told when the first edit turns ready into edited. |
| pendingId | string | none | The slide the AI is still writing. It stays read-only and says so. |
| overview | ReactNode | none | The AI's short summary of the deck, marked as drafted by AI. |
| estimate | ReactNode | none | Slides and cost, worked out by your app, shown beside Build slides. |
| error | ReactNode | none | Why drafting failed, in plain words, shown in the failed state. |
| maxItems | number | none | Most slides allowed. Add turns off at the limit and says why. |
| headingLevel | 2 | 3 | 4 | 5 | 6 | 3 | Level of the part's own heading. |
| labels | Partial<OutlineEditorLabels> | none | heading, build, update, retry, addEnd, titleError and failedNote, for wording or translation. |
| className | string | none | Extra classes on the section. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one OutlineEditor switches all of this from its properties panel, across 7 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Status | state | Drafting, Ready, Edited, Updating, Approved, Building, Failed |
| Estimate | estimate | Any text |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- drafting
- state="drafting": slides stream in; the one in pendingId is read-only and says "Still writing this slide"; a working edge runs.
- empty
- No slides yet: while drafting it says the first slide is coming; otherwise it invites adding one.
- ready
- state="ready": Build slides and the estimate.
- edited
- Any edit in ready, or state="edited": Update outline joins Build slides.
- updating
- state="updating": read-only under a working edge; locked slides are marked.
- approved
- state="approved": read-only with a check and a note.
- building
- state="building": read-only, says slides are being built.
- failed
- state="failed": what was written stays editable, with the error and Try again.
- missing title
- Build with an empty title: field error, focus on it, a summary line, nothing built.
- at limit
- items.length reaches maxItems: Add turns off and says why.
- removed
- After a remove: Undo remove puts the slide back in its place.
Tokens
Change one of these and every part that uses it follows.
--surface--surface-sunken--border--border-strong--fg--fg-muted--danger-fg--lime--on-lime--dur-fast--dur-base--ease-out--safe-bottom--shape-card--shape-control
Built in
- The outline is a section named by its heading. The slides are an ordered list named with the slide count, and each slide is a group named "Slide 3: title".
- Every field and button names its slide, such as "Slide 3 title", "Move slide 3 up" and "Add a slide after slide 3".
- Alt with Up or Down moves the slide while focus is anywhere in its row, including the title field. Focus stays on the same field or button after the move.
- When a move button turns off because the slide reached the end, focus moves to the other move button.
- Remove takes one press and is never final: focus goes to Undo remove, which puts the slide back in its place and returns focus to its title.
- Lock is a toggle button with aria-pressed.
- An empty title gets aria-invalid and a linked error, "Every slide needs a title". Build moves focus to the first one.
- A polite live region says milestones only: "Outline drafted, 6 slides", "Slide 4 moved to 3", "Outline updated, 6 slides", "Slide 2 removed. Undo is available." It never reads streamed words.
- The list is marked busy while the AI drafts or updates. Focus is not moved when the outline appears.
- New rows rise in and moved rows slide quickly; under reduced motion both happen at once with no animation.
What you need to do
- Give the estimate from your own code (slides and credits), never from the model, and update it when the slide count changes.
- Pass pendingId while drafting so the half-written slide is read-only, and move state to ready when drafting ends; screen readers then hear "Outline drafted, 6 slides".
- Write the failed error in plain words and say whether anything was charged.
- Keep the outline in a column no wider than reading width, and do not take focus when it appears.
- If you set a heading label, keep it short; it also names the list.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide