Form

react-hook-form wiring with accessible errors.

Installation

npm install @aspyn-io/kit @aspyn-io/tokens
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormDescription,
  FormMessage,
} from "@aspyn-io/kit";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";

Validated profile form

react-hook-form + zod, with labels, descriptions, and errors wired for accessibility automatically (aria-describedby, aria-invalid, error announcement). Submit empty to see validation.

Shown on your profile and in mentions.

const schema = z.object({
  display_name: z.string().min(2, "Display name must be at least 2 characters."),
  email: z.string().email("Enter a valid email address."),
});

const form = useForm<z.infer<typeof schema>>({
  resolver: zodResolver(schema),
  defaultValues: { display_name: "", email: "" },
});

<Form {...form}>
  <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
    <FormField
      control={form.control}
      name="display_name"
      render={({ field }) => (
        <FormItem>
          <FormLabel>Display name</FormLabel>
          <FormControl>
            <Input placeholder="Ada Lovelace" {...field} />
          </FormControl>
          <FormDescription>Shown on your profile and in mentions.</FormDescription>
          <FormMessage />
        </FormItem>
      )}
    />
    <Button type="submit">Save profile</Button>
  </form>
</Form>

Notes

  • FormControl works with any kit input via Slot — Input, Textarea, Select triggers, Checkbox, Switch.
  • Field names follow Aspyn API conventions: snake_case (display_name), so payloads map 1:1.
  • Install peer deps in your app: react-hook-form is bundled; add zod + @hookform/resolvers for schema validation.