Command Palette

Search for a command...

Checkbox

A control that allows the user to toggle between checked and not checked.

By clicking this checkbox, you agree to the terms and conditions.

import { styled } from "styled-system/jsx";
import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";

export default function CheckboxDemo() {
  return (
    <styled.div css={{ display: "flex", flexDir: "column", gap: "6" }}>
      <styled.div css={{ display: "flex", alignItems: "center", gap: "3" }}>
        <Checkbox id="terms" />
        <Label htmlFor="terms">Accept terms and conditions</Label>
      </styled.div>
      <styled.div css={{ display: "flex", alignItems: "flex-start", gap: "3" }}>
        <Checkbox id="terms-2" defaultChecked />
        <styled.div css={{ display: "grid", gap: "2" }}>
          <Label htmlFor="terms-2">Accept terms and conditions</Label>
          <styled.p css={{ color: "muted.fg", textStyle: "sm" }}>
            By clicking this checkbox, you agree to the terms and conditions.
          </styled.p>
        </styled.div>
      </styled.div>
      <styled.div css={{ display: "flex", alignItems: "center", gap: "3" }}>
        <Checkbox id="toggle" disabled />
        <Label htmlFor="toggle">Enable notifications</Label>
      </styled.div>
      <Label
        css={{
          display: "flex",
          alignItems: "flex-start",
          gap: "3",
          rounded: "lg",
          borderWidth: "1px",
          p: "3",
          _hover: {
            bg: "accent/50",
          },
          "&:has([aria-checked='true'])": {
            bg: "blue.50",
            borderColor: "blue.600",
            _dark: {
              borderColor: "blue.900",
              bg: "blue.950",
            },
          },
        }}
      >
        <Checkbox
          id="toggle-2"
          defaultChecked
          css={{
            _checked: {
              bg: "blue.600",
              color: "white",
              borderColor: "blue.600",
              _dark: {
                bg: "blue.700",
                borderColor: "blue.700",
              },
            },
          }}
        />
        <styled.div css={{ display: "grid", gap: "1.5", fontWeight: "normal" }}>
          <styled.p css={{ textStyle: "sm", lineHeight: "none", fontWeight: "medium" }}>
            Enable notifications
          </styled.p>
          <styled.p css={{ color: "muted.fg", textStyle: "sm" }}>
            You can enable or disable notifications at any time.
          </styled.p>
        </styled.div>
      </Label>
    </styled.div>
  );
}

Installation

npx nore-ui-cli@latest add checkbox

Usage

import { Checkbox } from "@/components/ui/checkbox";
<Checkbox />

Examples

Form

You can manage your mobile notifications in the mobile settings page.

"use client";

import { Controller, useForm } from "react-hook-form";
import Link from "next/link";
import { zodResolver } from "@hookform/resolvers/zod";
import { styled } from "styled-system/jsx";
import { z } from "zod";
import { toast } from "@/hooks/use-toast";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldContent, FieldDescription, FieldLabel } from "@/components/ui/field";

const formSchema = z.object({
  mobile: z.boolean().default(false).optional(),
});

type FormSchema = z.infer<typeof formSchema>;

export default function CheckboxFormSingle() {
  const form = useForm<FormSchema>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      mobile: true,
    },
  });

  const onSubmit = form.handleSubmit((data) => {
    toast({
      title: "You submitted the following values:",
      description: (
        <styled.pre
          css={{ mt: "2", w: "340px", rounded: "md", bg: "slate.950", p: "4", borderWidth: "1px" }}
        >
          <styled.code css={{ color: "white" }}>{JSON.stringify(data, null, 2)}</styled.code>
        </styled.pre>
      ),
    });
  });

  return (
    <styled.form onSubmit={onSubmit} css={{ spaceY: "6" }}>
      <Controller
        control={form.control}
        name="mobile"
        render={({ field, fieldState }) => (
          <Field
            data-invalid={fieldState.invalid}
            orientation="horizontal"
            css={{ p: "4", borderWidth: "1px", rounded: "md" }}
          >
            <Checkbox checked={field.value} onCheckedChange={field.onChange} />
            <FieldContent>
              <FieldLabel>Use different settings for my mobile devices</FieldLabel>
              <FieldDescription>
                You can manage your mobile notifications in the{" "}
                <Link href="/examples/forms">mobile settings</Link> page.
              </FieldDescription>
            </FieldContent>
          </Field>
        )}
      />
      <Button type="submit">Submit</Button>
    </styled.form>
  );
}

Select the items you want to display in the sidebar.

"use client";

import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { styled } from "styled-system/jsx";
import { z } from "zod";
import { toast } from "@/hooks/use-toast";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldDescription, FieldError, FieldLabel } from "@/components/ui/field";

const items = [
  {
    id: "recents",
    label: "Recents",
  },
  {
    id: "home",
    label: "Home",
  },
  {
    id: "applications",
    label: "Applications",
  },
  {
    id: "desktop",
    label: "Desktop",
  },
  {
    id: "downloads",
    label: "Downloads",
  },
  {
    id: "documents",
    label: "Documents",
  },
] as const;

const formSchema = z.object({
  items: z.array(z.string()).refine((value) => value.some((item) => item), {
    message: "You have to select at least one item.",
  }),
});

type FormSchema = z.infer<typeof formSchema>;

export default function CheckboxFormMultiple() {
  const form = useForm<FormSchema>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      items: ["recents", "home"],
    },
  });

  const onSubmit = form.handleSubmit((data) => {
    toast({
      title: "You submitted the following values:",
      description: (
        <styled.pre
          css={{ mt: "2", w: "340px", rounded: "md", bg: "slate.950", p: "4", borderWidth: "1px" }}
        >
          <styled.code css={{ color: "white" }}>{JSON.stringify(data, null, 2)}</styled.code>
        </styled.pre>
      ),
    });
  });

  return (
    <styled.form onSubmit={onSubmit} css={{ spaceY: "8" }}>
      <Controller
        control={form.control}
        name="items"
        render={({ field, fieldState }) => (
          <Field data-invalid={fieldState.invalid}>
            <styled.div css={{ mb: "4" }}>
              <FieldLabel css={{ textStyle: "md" }}>Sidebar</FieldLabel>
              <FieldDescription>
                Select the items you want to display in the sidebar.
              </FieldDescription>
            </styled.div>
            {items.map((item) => (
              <styled.div
                key={item.id}
                css={{
                  display: "flex!",
                  flexDir: "row!",
                  alignItems: "center",
                  gap: "2",
                }}
              >
                <Checkbox
                  checked={field.value?.includes(item.id)}
                  onCheckedChange={(checked) => {
                    return checked
                      ? field.onChange([...field.value, item.id])
                      : field.onChange(field.value?.filter((value: string) => value !== item.id));
                  }}
                />
                <FieldLabel css={{ fontWeight: "normal" }}>{item.label}</FieldLabel>
              </styled.div>
            ))}
            <FieldError>{fieldState.error?.message}</FieldError>
          </Field>
        )}
      />
      <Button type="submit">Submit</Button>
    </styled.form>
  );
}