Checkbox field

One yes or no, with its label beside the box.

You can read them before you sign up.

Installation

npx shadcn@latest add @formdef/checkbox-field

Register it under widgets in lib/formdef/index.tsx, as widgets: { checkbox: CheckboxField }. The widget serves boolean values.

Usage

export const  = createForm({
  : .({
    : .().(() => , 'Accept the terms to continue'),
  }),
  : { : false },
  fields: {
    terms: { : 'checkbox', : { : 'I accept the terms' } },
  },
})

The label sits beside the box, so the widget takes no labelAside. A checkbox that has to be ticked is a refine in the schema: z.boolean() alone accepts false.

For several choices out of a list, take the checkbox group field.

Props

Prop

Type

Source

import { type FieldOf, fieldParts } from '@formdef/core'
import type { ComponentProps } from 'react'

import { FieldNotes } from '@/components/formdef/field-notes'
import { Checkbox } from '@/components/ui/checkbox'
import { Field, FieldContent, FieldLabel } from '@/components/ui/field'
import type { FieldLabels } from '@/lib/formdef/field-labels'

type Attrs = Pick<
  ComponentProps<typeof Checkbox>,
  'className' | 'disabled' | 'readOnly' | 'required'
>

type CheckboxFieldProps = FieldOf<boolean> & Omit<FieldLabels, 'labelAside'> & Attrs

export const CheckboxField = ({ field, label, description, ...attrs }: CheckboxFieldProps) => {
  const parts = fieldParts(field, { description })
  const { name: _carriedByTheForm, ...control } = parts.control
  const checked = field.state.value ?? false

  return (
    <Field orientation="horizontal" data-invalid={parts.isErrorDue} data-disabled={attrs.disabled}>
      <Checkbox
        {...attrs}
        {...control}
        checked={checked}
        onCheckedChange={(isChecked) => field.handleChange(isChecked)}
      />
      <FieldContent>
        {label !== undefined && <FieldLabel htmlFor={control.id}>{label}</FieldLabel>}
        <FieldNotes parts={parts} description={description} />
      </FieldContent>
    </Field>
  )
}