Approval routingPro
Who must approve an agent's action, in order, with each step's status and your decision right on your step.
On this page
Installation
Usage
import { ApprovalRouting } from "@/components/ui/chatcn/pro/approval-routing"
<ApprovalRouting
requester={ledger}
action="void the second charge of $84.20 on order 4471"
rule="Voids over $50 need billing ops, then finance."
steps={[
{ id: "ops", label: "Billing ops", approvers: [tomasz, me], mode: "any", status: "waiting" },
{ id: "finance", approvers: [noor], status: "pending" },
]}
currentUserId={me.id}
onApprove={(stepId) => api.approve(stepId)}
onDecline={(stepId, note) => api.decline(stepId, note)}
onRemind={(stepId) => api.remind(stepId)}
/>The route is a rail of steps. Passed segments are solid ink and the rest are dashed; each step's node is its own shape (a check, a cross, an amber diamond for the step waiting now, a hollow ring for later, a dash for not needed). A step can be one person, any one of a group, or all of a group. When the waiting step includes the viewer, Approve and Decline sit right on it, and Decline asks why because the agent reads the note. Other people's waiting steps offer Remind. Decisions apply the moment they resolve, so the route moves on (and a decline marks the rest as not needed) before new steps arrive; new steps always win.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
requester | CollabMember | Who wants to act, usually an agent |
action, detail, rule | ReactNode | What, extra context, and the policy |
steps | { id, approvers, mode?, label?, status, decidedBy?, at?, note? }[] | status: approved, declined, waiting, pending, skipped |
currentUserId | string | Steps the viewer can decide get the buttons |
onApprove, onDecline | (stepId, note?) => unknown | Promise<unknown> | Reject to show the error |
onRemind | (stepId) => void | Shows Remind on other people's steps |
labels, locale | Every string, for translation |
Labels
labels covers the ask line, the route line, any one of and all of, every status word with and without a name, the buttons, the decline prompt, the progress count, the closing lines and the error.
Keyboard
| Key | Action |
|---|---|
| Tab | Approve, Decline, Remind |
| Enter in the note | Decline with the note |
| Shift Enter | New line in the note |
Accessibility
- The route is an ordered list; the waiting step has
aria-current="step". - Every status is said in words beside its node; the nodes are decorative.
- A failed decision is an alert; the closing line is a status.
Motion
The closing line rises 4 px and fades in over 200 ms. Buttons press at 0.97. Reduced motion keeps the fade.