Interactive Answers
Form Card
A form the agent asks the user to fill — fields, selects, validation and a submitted state.
2 variantsMIT
Preview
New teammate details
The onboarding agent needs these to set up accounts.
Installation
Copies the component into components/ui and installs its dependencies and theme tokens.
pnpm dlx shadcn@latest add https://tuffui.com/r/form-card.jsonUsage
Pass your own data and wire the callbacks to your agent runtime.
import { FormCard, type FormField } from "@/components/ui/form-card";
// The agent asks for structured input with a tool call like request_form(fields).
export function AgentForm({ call }: { call: { title: string; fields: FormField[] } }) {
return (
<FormCard
data={{ title: call.title, fields: call.fields }}
onSubmit={async (values) => {
await agent.sendToolResult(call.id, values); // the run continues with the answers
}}
validate={(values) => ({
email: String(values.email ?? "").endsWith("@company.com")
? undefined
: "Use your company address",
})}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| data* | { title: string; description?: string; fields: FormField[] } | — | The form the agent asked for, usually straight from a tool call. |
| onSubmit | (values: FormValues) => void | Promise<void> | — | Called once every field is valid. Return a promise to show the loading state; a rejection returns to editing. |
| validate | (values) => Record<string, string | undefined> | — | Extra checks after the built-in ones (required, email format, number min/max). |
| values / defaultValues / onValuesChange | FormValues | — | Controlled or uncontrolled answers, keyed by field name. |
| status / onStatusChange | "editing" | "submitting" | "submitted" | — | Controls the state from outside. Submitted collapses into a summary with Edit. |
| revealErrors | boolean | false | Shows every error at once. Otherwise a field shows its error after blur or a submit attempt. |
| submitLabel | string | "Submit" | Text of the primary button. |
| className | string | — | Extra classes for the shell. |
type FormField = {
name: string;
label: string;
type: "text" | "email" | "number" | "textarea" | "select" | "radio" | "checkbox" | "switch";
required?: boolean;
description?: string;
placeholder?: string;
options?: { value: string; label: string; description?: string }[]; // select, radio
min?: number; // number
max?: number;
};
type FormValues = Record<string, string | boolean | undefined>;