Checkbox Field
Checkbox component integrated with TanStack Form via React context for boolean field management.
npx shadcn@latest add https://shuip.plvo.dev/r/tsf-checkbox-field.json
pnpm dlx shadcn@latest add https://shuip.plvo.dev/r/tsf-checkbox-field.json
bun x shadcn@latest add https://shuip.plvo.dev/r/tsf-checkbox-field.json
'use client';import { Checkbox } from '@/components/ui/checkbox';import { Field, FieldDescription, FieldError, FieldLabel } from '@/components/ui/field';import { useFieldContext } from '@/components/ui/shuip/tanstack-form/form-context';export interface CheckboxFieldProps {label: string;description?: string;fieldProps?: React.ComponentProps<typeof Field>;props?: React.ComponentProps<typeof Checkbox>;}export function CheckboxField({ label, description, fieldProps, props }: CheckboxFieldProps) {const field = useFieldContext<boolean>();const { isValid, errors } = field.state.meta;return (<Field className='gap-2' data-invalid={!isValid} {...fieldProps}><div className='flex items-center gap-2'><Checkboxid={field.name}name={field.name}checked={field.state.value}onCheckedChange={(checked) => field.handleChange(checked === true)}onBlur={field.handleBlur}aria-invalid={!isValid}{...props}/><FieldLabel htmlFor={field.name} className='text-sm cursor-pointer'>{label}</FieldLabel></div>{!isValid && (<FieldErrorclassName='text-xs text-left'errors={errors.map((error) => ({ message: typeof error === 'string' ? error : error?.message }))}/>)}{description && <FieldDescription className='text-xs'>{description}</FieldDescription>}</Field>);}
Loading...
Checkboxes are binary inputs for opting in or accepting terms. CheckboxField combines Radix UI's Checkbox with an inline clickable label, making the entire label area interactive — not just the checkbox itself.
The component reads the surrounding field via useFieldContext, so you compose it inside a <form.AppField>. Common patterns include required checkboxes for terms acceptance (validated with !value check) or grouped checkboxes for multi-select options (using nested field paths like features.notifications).
Built-in features
- Context-bound field state via
useFieldContext— no prop drilling - Clickable inline label positioned next to checkbox
- Boolean field type for true/false state
- Required validation for terms acceptance
- Nested paths for grouped checkboxes
Setup
Field components are bound via React context. In your project, create lib/form.ts once:
// lib/form.ts
import { createFormHook } from '@tanstack/react-form';
import { fieldContext, formContext } from '@/components/ui/shuip/tanstack-form/form-context';
import { CheckboxField } from '@/components/ui/shuip/tanstack-form/checkbox-field';
import { SubmitButton } from '@/components/ui/shuip/tanstack-form/submit-button';
export const { useAppForm } = createFormHook({
fieldContext,
formContext,
fieldComponents: { CheckboxField },
formComponents: { SubmitButton },
});See the form-context item for details.
Required checkbox
import { useAppForm } from '@/lib/form';
const form = useAppForm({
defaultValues: { terms: false },
onSubmit: async ({ value }) => {
await saveData(value);
},
});
<form.AppField
name='terms'
validators={{
onChange: ({ value }) =>
!value ? 'You must accept the terms' : undefined,
}}
children={(field) => (
<field.CheckboxField label='I accept the terms and conditions' />
)}
/>Examples
Dependent Fields
Loading...
'use client';import { createFormHook, useStore } from '@tanstack/react-form';import { CheckboxField } from '@/components/ui/shuip/tanstack-form/checkbox-field';import { fieldContext, formContext } from '@/components/ui/shuip/tanstack-form/form-context';import { InputField } from '@/components/ui/shuip/tanstack-form/input-field';import { SubmitButton } from '@/components/ui/shuip/tanstack-form/submit-button';const { useAppForm } = createFormHook({fieldContext,formContext,fieldComponents: { CheckboxField, InputField },formComponents: { SubmitButton },});export default function TsfCheckboxFieldDependentFieldsExample() {const form = useAppForm({defaultValues: {customShipping: false,shippingAddress: '',sameAsBilling: false,billingAddress: '',},onSubmit: async ({ value }) => {await new Promise((resolve) => setTimeout(resolve, 1000));alert(JSON.stringify(value, null, 2));},});const customShipping = useStore(form.store, (state) => state.values.customShipping);const sameAsBilling = useStore(form.store, (state) => state.values.sameAsBilling);return (<formonSubmit={(e) => {e.preventDefault();form.handleSubmit();}}className='space-y-4'><form.AppFieldname='billingAddress'validators={{onChange: ({ value }) => (!value ? 'Billing address is required' : undefined),}}children={(field) => <field.InputField label='Billing Address' />}/><form.AppFieldname='customShipping'listeners={{onChange: ({ value }) => {if (!value) {form.setFieldValue('shippingAddress', '');form.setFieldValue('sameAsBilling', false);}},}}children={(field) => <field.CheckboxField label='Use a different shipping address' />}/>{customShipping && (<div className='space-y-4 pl-6 border-l-2'><form.AppFieldname='sameAsBilling'listeners={{onChange: ({ value }) => {if (!value) {form.setFieldValue('shippingAddress', '');} else {form.setFieldValue('shippingAddress', form.getFieldValue('billingAddress'));}},}}children={(field) => <field.CheckboxField label='Same as billing address' />}/><form.AppFieldname='shippingAddress'validators={{onChange: ({ value }) => {if (!value && customShipping) return 'Shipping address is required';return undefined;},}}children={(field) => <field.InputField label='Shipping Address' props={{ disabled: sameAsBilling }} />}/></div>)}<form.AppForm><form.SubmitButton>Submit Order</form.SubmitButton></form.AppForm></form>);}
Default
Loading...
'use client';import { createFormHook } from '@tanstack/react-form';import { CheckboxField } from '@/components/ui/shuip/tanstack-form/checkbox-field';import { fieldContext, formContext } from '@/components/ui/shuip/tanstack-form/form-context';import { SubmitButton } from '@/components/ui/shuip/tanstack-form/submit-button';const { useAppForm } = createFormHook({fieldContext,formContext,fieldComponents: { CheckboxField },formComponents: { SubmitButton },});export default function TsfCheckboxFieldExample() {const form = useAppForm({defaultValues: {termsExample: false,marketingExample: false,},onSubmit: async ({ value }) => {await new Promise((resolve) => setTimeout(resolve, 1000));alert(JSON.stringify(value, null, 2));},});return (<formonSubmit={(e) => {e.preventDefault();form.handleSubmit();}}className='space-y-4'><form.AppFieldname='termsExample'validators={{onChange: ({ value }) => (!value ? 'You must accept the terms and conditions' : undefined),}}children={(field) => <field.CheckboxField label='I accept the terms and conditions' />}/><form.AppFieldname='marketingExample'children={(field) => (<field.CheckboxFieldlabel='Send me promotional emails'description='Optional: Receive updates about new features'/>)}/><form.AppForm><form.SubmitButton /></form.AppForm></form>);}
Group
Loading...
'use client';import { createFormHook } from '@tanstack/react-form';import { CheckboxField } from '@/components/ui/shuip/tanstack-form/checkbox-field';import { fieldContext, formContext } from '@/components/ui/shuip/tanstack-form/form-context';import { SubmitButton } from '@/components/ui/shuip/tanstack-form/submit-button';const { useAppForm } = createFormHook({fieldContext,formContext,fieldComponents: { CheckboxField },formComponents: { SubmitButton },});export default function TsfCheckboxFieldGroupExample() {const form = useAppForm({defaultValues: {features: {notifications: false,analytics: false,darkMode: false,apiAccess: false,},},onSubmit: async ({ value }) => {await new Promise((resolve) => setTimeout(resolve, 1000));alert(JSON.stringify(value, null, 2));},});return (<formonSubmit={(e) => {e.preventDefault();form.handleSubmit();}}className='space-y-4'><div className='space-y-3'><h3 className='font-semibold'>Features</h3><p className='text-sm text-muted-foreground'>Select the features you want to enable</p><div className='space-y-3'><form.AppFieldname='features.notifications'children={(field) => (<field.CheckboxFieldlabel='Enable push notifications'description='Receive real-time updates about your activity'/>)}/><form.AppFieldname='features.analytics'children={(field) => (<field.CheckboxFieldlabel='Enable analytics tracking'description='Help us improve by sharing usage data'/>)}/><form.AppFieldname='features.darkMode'children={(field) => (<field.CheckboxField label='Enable dark mode' description='Switch to a darker color scheme' />)}/><form.AppFieldname='features.apiAccess'children={(field) => (<field.CheckboxField label='Enable API access' description='Get programmatic access to your data' />)}/></div></div><form.AppForm><form.SubmitButton>Save Preferences</form.SubmitButton></form.AppForm></form>);}
Props
Prop
Type