A form control that allows the user to toggle between checked and not checked. Supports indeterminate state.
Pair with Field.* for label/description/error wiring in forms:
You must accept before continuing.
1import { Checkbox } from "@ngrok/mantle/checkbox";2import { Field } from "@ngrok/mantle/field";3 4<Field.Item name="terms-of-service">5 <Field.Label className="flex items-center gap-2">6 <Field.Control>7 <Checkbox />8 </Field.Control>9 Accept terms and conditions10 </Field.Label>11 <Field.Description>You must accept before continuing.</Field.Description>12</Field.Item>;Or render the control on its own:
1import { Checkbox } from "@ngrok/mantle/checkbox";2import { Label } from "@ngrok/mantle/label";3 4<Label htmlFor="terms" className="flex items-center gap-2">5 <Checkbox name="terms" id="terms" />6 Accept terms and conditions7</Label>8<Label htmlFor="unchecked" className="flex items-center gap-2">9 <Checkbox id="unchecked" name="unchecked" checked={false} readOnly />10 Unchecked11</Label>12<Label htmlFor="checked" className="flex items-center gap-2">13 <Checkbox id="checked" name="checked" checked readOnly />14 Checked15</Label>16<Label htmlFor="indeterminate" className="flex items-center gap-2">17 <Checkbox id="indeterminate" name="indeterminate" defaultChecked="indeterminate" readOnly />18 Indeterminate19</Label>Use @tanstack/react-form with zod to keep the checkbox controlled and render errors through Field.Errors.
1import { Button } from "@ngrok/mantle/button";2import { Checkbox } from "@ngrok/mantle/checkbox";3import { Field, toErrorMessages } from "@ngrok/mantle/field";4import { useForm } from "@tanstack/react-form";5import { z } from "zod";6 7export const formSchema = z.object({8 acceptedTerms: z.boolean().refine((value) => value, "Accept the terms to continue."),9});10function Example() {11 const defaultValues = {12 acceptedTerms: false,13 };14 const form = useForm({15 defaultValues,16 validators: {17 onSubmit: formSchema,18 },19 onSubmit: ({ value }) => {20 // Handle form submission here21 },22 });23 24 return (25 <form26 className="space-y-4"27 onSubmit={(event) => {28 event.preventDefault();29 event.stopPropagation();30 void form.handleSubmit();31 }}32 >33 <form.Field name="acceptedTerms">34 {(field) => (35 <Field.Item name={field.name}>36 <Field.Label className="flex items-center gap-2">37 <Field.Control>38 <Checkbox39 checked={field.state.value}40 onBlur={field.handleBlur}41 onChange={(event) => field.handleChange(event.target.checked)}42 />43 </Field.Control>44 Accept terms and conditions45 </Field.Label>46 <Field.Errors messages={toErrorMessages(field.state.meta.errors)} />47 </Field.Item>48 )}49 </form.Field>50 <Button type="submit" appearance="filled">51 Submit52 </Button>53 </form>54 );55}All props from input[type="checkbox"], plus: