PlanCard
StableShows what the assistant plans to do before it starts, so you can approve or ask for changes.
Also known as plan, agent plan, proposed plan
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Awaiting approval
Plan the party seating
Awaiting approvalLook at the guest list
See who has replied so far.
Add a seat for each guest
Group friends and family together.
Check the table plan
Make sure nobody is left out.
<PlanCard
title="Plan the party seating"
estimate="About 6 minutes"
steps={[
{ id: "1", title: "Look at the guest list", description: "See who has replied so far." },
{ id: "2", title: "Add a seat for each guest", description: "Group friends and family together." },
{ id: "3", title: "Check the table plan", description: "Make sure nobody is left out." },
]}
/>The starting state. Approve and Revise work, and the "nothing has changed" label shows.
When to use it
Shows the steps the assistant intends to take before anything changes, so a person can agree to the approach or ask for another. It does not take your place on the page when it appears, because a plan can wait.
Made of: Title · State label · "Nothing has changed" label · Estimate · Numbered steps (title, note, Edit, Remove) · Buttons (Approve, Revise) or a note on the result · Spoken update
Use it for
- Before a task that edits, sends or deletes things, so the person agrees first.
- Letting people edit or remove steps before they approve.
- Showing a time or cost estimate next to the steps.
Not for
- A yes or no on one single action: use ApprovalPrompt.
- Showing progress through steps that are already running: use StepTimeline.
- A to-do list people tick off themselves: use Checklist.
Do and avoid
Book the hotel
Awaiting approvalCheck the hotel dates
Match them to your flights.
Book the room
Pick the cheapest refundable one.
Do
- Show the plan before anything changes, and say so.
- Keep each step's note to one short sentence.
- Give an estimate when you can, in time or cost.
- Let people edit or remove a step while the plan can still change.
Avoid
- Don't show a plan that has already run as if it were still waiting.
- Don't use amber on the card. A plan is not urgent.
- Don't pack a long list of tasks into one step.
On a phone
- The card has 20px padding, and each step keeps its Edit button and remove icon on the same row as its text, so step text gets narrower when edit tools are on.
- The remove icon and buttons keep their size and have a 44px tap area on a touch screen.
- Approve and Revise wrap under each other if they do not fit on one row.
Seen in products
- Replit Agent Plan mode lets the user brainstorm before Agent changes code, and produces task proposals with Accept tasks and Revise plan actions.
- Claude Code plan mode is read-only, and the user approves the plan before edits.
- Windsurf Cascade keeps a long-term plan and generates a todo list.
- Gemini Deep Research shows a research plan with an Edit plan button before starting.
- Perplexity asks clarifying questions up front for broad queries (secondary).
- Vercel AI Elements ships Plan, Task and Queue components, and Shape of AI Governors list Action plan.
- Anthropic's Building effective agents advises surfacing plans, showing ground truth at each step, and including human checkpoints and stop conditions.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| titlerequired | string | none | Plan title, shown as the heading. |
| stepsrequired | PlanStep[] | none | Ordered steps. Each has id, title and an optional description. |
| estimate | ReactNode | none | Time or cost estimate shown under the title. |
| state | "draft" | "awaiting" | "approved" | "revised" | none | State, for controlled use. |
| defaultState | PlanState | "awaiting" | Initial state when uncontrolled. |
| onStateChange | (state: PlanState) => void | none | Called when Approve or Revise changes the state. |
| onApprove | () => void | none | Called by Approve. |
| onRevise | () => void | none | Called by Revise. |
| onEditStep | (id: string) => void | none | Adds an Edit button to each step while the plan is draft or awaiting. |
| onRemoveStep | (id: string) => void | none | Adds a Remove button to each step while the plan is draft or awaiting. |
| readOnlyLabel | string | null | "Nothing has changed yet" | Read-only badge text. Null hides it. It is hidden once approved. |
| labels | PlanCardLabels | none | Replace button text and the state notes. |
| headingLevel | 2 | 3 | 4 | 5 | 6 | 3 | Level of the part's own heading, so it fits the page outline. |
| 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 PlanCard 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 | state | Draft, Awaiting, Approved, Revised |
| Title | title | Any text |
| Estimate | estimate | Any text |
Tokens
Change one of these and every part that uses it follows.
--surface--border--surface-sunken--radius-card
Built in
- The card is named by its title, and the steps are a numbered list.
- Edit and Remove buttons include the step number and title.
- Screen readers hear when the plan is approved or a revision is requested.
- It does not move your place on the page when it appears.
- The state is written in words, and Approved adds a check mark.
What you need to do
- Set headingLevel so the title fits your page outline. It is 3 unless you change it.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide