Skip to content

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.

The invite to the workspace goes here.

Production access

Required

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.json

Usage

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

PropTypeDefaultDescription
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 / onValuesChangeFormValues—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.
revealErrorsbooleanfalseShows every error at once. Otherwise a field shows its error after blur or a submit attempt.
submitLabelstring"Submit"Text of the primary button.
classNamestring—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>;