Integrations
Forms
Typed form primitives built on TanStack Form with per-field Zod validation. Loading + dirty states handled.
Full example
import { useAppForm } from '@kana-consultant/ui-kit'
import { z } from 'zod'
const titleSchema = z.string().min(3, 'At least 3 characters')
const descSchema = z.string().max(200, 'Keep it under 200 characters')
export function CreateTaskForm() {
const form = useAppForm({
defaultValues: { title: '', description: '', notify: true, remindMe: false },
onSubmit: async ({ value }) => {
await api.createTask(value)
},
})
return (
<form
onSubmit={(e) => {
e.preventDefault()
void form.handleSubmit()
}}
>
<form.AppField name='title' validators={{ onChange: titleSchema, onBlur: titleSchema }}>
{(field) => <field.TextField label='Title' required />}
</form.AppField>
<form.AppField name='description' validators={{ onChange: descSchema }}>
{(field) => <field.TextareaField label='Description' />}
</form.AppField>
<form.AppField name='notify'>
{(field) => <field.SwitchField label='Notify assignees' />}
</form.AppField>
<form.AppField name='remindMe'>
{(field) => <field.CheckboxField label='Remind me 1 hour before due' />}
</form.AppField>
<form.AppForm>
<form.ResetButton>Reset</form.ResetButton>
<form.SubmitButton>Create task</form.SubmitButton>
</form.AppForm>
</form>
)
} Field components
TextField
Wraps Input. Handles label, required indicator, error message.
TextareaField
Wraps Textarea with the same label/error affordances.
CheckboxField
Label + Checkbox with optional description.
SwitchField
Label + Switch in a space-between row layout.
Form-level components
-
form.SubmitButton— auto-disables when invalid or submitting, renders a loader. PassdisabledWhenPristineto also disable on unchanged forms. form.ResetButton— callsform.reset().
Hooks & context
Advanced use cases can grab the field / form API directly via
useFieldContext<T>() and useFormContext(), both exported from
the package. These mirror TanStack Form's native contexts.