Checkbox Field

Checkbox component integrated with React Hook Form for type-safe boolean field management.

npx shadcn@latest add https://shuip.plvo.dev/r/rhf-checkbox-field.json
pnpm dlx shadcn@latest add https://shuip.plvo.dev/r/rhf-checkbox-field.json
bun x shadcn@latest add https://shuip.plvo.dev/r/rhf-checkbox-field.json
import type { FieldPath, FieldValues, UseFormRegisterReturn } from 'react-hook-form';
import { Checkbox } from '@/components/ui/checkbox';
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
export interface CheckboxFieldProps<T extends FieldValues> extends React.ComponentProps<typeof Checkbox> {
register: UseFormRegisterReturn<FieldPath<T>>;
label: string;
boxLabel?: string;
description?: string;
}
export function CheckboxField<T extends FieldValues>({
register,
label,
description,
...props
}: CheckboxFieldProps<T>) {
return (
<FormField
{...register}
render={({ field, fieldState }) => {
return (
<FormItem data-invalid={fieldState.invalid}>
<FormControl>
<div className='flex items-center gap-2'>
<Checkbox
id={field.name}
checked={field.value}
onCheckedChange={field.onChange}
aria-invalid={fieldState.invalid}
{...props}
/>
<FormLabel htmlFor={field.name}>{label}</FormLabel>
</div>
</FormControl>
<FormMessage className='text-xs text-left' />
{description && <FormDescription className='text-xs'>{description}</FormDescription>}
</FormItem>
);
}}
/>
);
}
export default CheckboxField;
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.

Common patterns include required checkboxes for terms acceptance (validated with Zod's .refine() method) or grouped checkboxes for multi-select options using separate field registrations.

Built-in features

  • Clickable inline label positioned next to checkbox
  • Boolean field type for true/false state
  • Required validation for terms acceptance
  • Zod validation: Native integration with react-hook-form

Required checkbox

const schema = z.object({
  terms: z.boolean().refine(val => val === true, {
    message: 'You must accept the terms and conditions',
  }),
})

const form = useForm({
  defaultValues: { terms: false },
  resolver: zodResolver(schema),
})

<CheckboxField
  register={form.register('terms')}
  label='I accept the terms and conditions'
  description='Read our terms before proceeding'
/>

Examples

Box Label

Loading...
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Form } from '@/components/ui/form';
import { CheckboxField } from '@/components/ui/shuip/react-hook-form/checkbox-field';
import { SubmitButton } from '@/components/ui/shuip/submit-button';
const zodSchema = z.object({
checkbox: z.boolean(),
});
export default function CheckboxFieldExample() {
const form = useForm({
defaultValues: { checkbox: false },
resolver: zodResolver(zodSchema),
});
async function onSubmit(values: z.infer<typeof zodSchema>) {
try {
alert(`Checkbox: ${values}`);
} catch (error) {
console.error(error);
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className='space-y-4'>
<CheckboxField
register={form.register('checkbox')}
label='Checkbox'
description='Your checkbox'
boxLabel='Box description'
/>
<SubmitButton>Submit</SubmitButton>
</form>
</Form>
);
}

Default

Loading...
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Form } from '@/components/ui/form';
import { CheckboxField } from '@/components/ui/shuip/react-hook-form/checkbox-field';
import { SubmitButton } from '@/components/ui/shuip/submit-button';
const zodSchema = z.object({
checkbox: z.boolean().refine((val) => val === true, {
message: 'Accept your destiny!',
}),
});
export default function CheckboxFieldExample() {
const form = useForm({
defaultValues: { checkbox: false },
resolver: zodResolver(zodSchema),
});
async function onSubmit(values: z.infer<typeof zodSchema>) {
try {
alert(`Checkbox: ${values.checkbox}`);
} catch (error) {
console.error(error);
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className='space-y-4'>
<CheckboxField
register={form.register('checkbox')}
label='Accept terms and conditions'
description='To continue, you must accept the terms and conditions because tbh it says so'
/>
<SubmitButton>Submit</SubmitButton>
</form>
</Form>
);
}

Group

Loading...
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Form } from '@/components/ui/form';
import { CheckboxField } from '@/components/ui/shuip/react-hook-form/checkbox-field';
import { SubmitButton } from '@/components/ui/shuip/submit-button';
const zodSchema = z.object({
features: z.object({
notifications: z.boolean(),
analytics: z.boolean(),
darkMode: z.boolean(),
apiAccess: z.boolean(),
}),
});
export default function CheckboxFieldGroupExample() {
const form = useForm({
defaultValues: { features: { notifications: false, analytics: false, darkMode: false, apiAccess: false } },
resolver: zodResolver(zodSchema),
});
async function onSubmit(values: z.infer<typeof zodSchema>) {
try {
alert(`Features: ${JSON.stringify(values.features, null, 2)}`);
} catch (error) {
console.error(error);
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} 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'>
<CheckboxField
register={form.register('features.notifications')}
label='Enable push notifications'
description='Receive real-time updates about your activity'
/>
<CheckboxField
register={form.register('features.analytics')}
label='Enable analytics tracking'
description='Help us improve by sharing usage data'
/>
<CheckboxField
register={form.register('features.darkMode')}
label='Enable dark mode'
description='Switch to a darker color scheme'
/>
<CheckboxField
register={form.register('features.apiAccess')}
label='Enable API access'
description='Get programmatic access to your data'
/>
</div>
</div>
<SubmitButton>Save Preferences</SubmitButton>
</form>
</Form>
);
}

Props

Prop

Type

On this page