16 / Agent UI
Approval Card
The question an agent asks before it acts. Ordinary answers take one click; destructive ones have to be held.
How many flavors should we launch with?
Installation
Copy the source into your project, or keep it behind a package.
Copy the component into your project and make it yours.
Usage
export function Confirm() {
return (
<ApprovalCard
question="Delete 40 files the agent flagged as unused?"
description="This cannot be undone from here."
options={[
{ id: "delete", label: "Delete all 40", destructive: true },
{ id: "review", label: "Show me the list first" },
]}
onApprove={handleApprove}
/>
)
}API
questionReactNodeWhat the agent is asking.descriptionReactNodeSupporting detail below the question.optionsApprovalOption[]Id, label, optional description, and a destructive flag.answerId, defaultAnswerIdstringThe chosen option, controlled or uncontrolled.holdDurationnumberHold time for destructive options in milliseconds. Defaults to 900, minimum 500.freeformbooleanAdds a field for an answer you did not list.onApprove(optionId: string) => voidRuns when an option is chosen.onFreeformSubmit(value: string) => voidRuns when the freeform answer is sent.onDismiss() => voidShows a dismiss control when supplied.Accessibility
The card is a labelled region and the options are a group tied to the question. Ordinary options are ordinary buttons. A destructive option cannot be triggered by a stray tap: pointer input has to be held, and releasing early cancels. Keyboard and assistive technology users activate it once instead, since holding a key is not a fair requirement. The progress fill is decorative and is hidden under reduced motion.
Dependencies
lucide-react