# V checkbox 9

> Notification Channel Selector

A shadcn/ui block from the [@cnippet](https://ui.cnippet.dev/) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/cnippet/v-checkbox-9).

- Page, with a live preview: https://shadcn.exchange/r/cnippet/v-checkbox-9
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/cnippet/v-checkbox-9-light-15ad4cdf90242ac6.png
- Registry item: https://ui.cnippet.dev/r/v-checkbox-9.json
- Categories: checkbox
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://ui.cnippet.dev/r/v-checkbox-9.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `@cnippet/checkbox`

## Files

### `registry/default/variants/v-checkbox-9.tsx`

```tsx
"use client";

import {
  BellIcon,
  MailIcon,
  MessageSquareIcon,
  SmartphoneIcon,
} from "lucide-react";
import { useState } from "react";

import { Checkbox } from "@/registry/default/ui/checkbox";
import { Separator } from "@/registry/default/ui/separator";

const channels = [
  {
    description: "Receive updates in your inbox",
    icon: MailIcon,
    id: "ch-email",
    label: "Email",
  },
  {
    description: "Alerts sent to your phone",
    icon: SmartphoneIcon,
    id: "ch-sms",
    label: "SMS",
  },
  {
    description: "Banners while using the app",
    icon: BellIcon,
    id: "ch-inapp",
    label: "In-app",
  },
  {
    description: "Messages to your Slack workspace",
    icon: MessageSquareIcon,
    id: "ch-slack",
    label: "Slack",
  },
];

export function Pattern() {
  const [checked, setChecked] = useState<Record<string, boolean>>({
    "ch-email": true,
    "ch-inapp": true,
    "ch-slack": false,
    "ch-sms": false,
  });

  const toggle = (id: string, val: boolean) =>
    setChecked((prev) => ({ ...prev, [id]: val }));

  return (
    <div className="w-full max-w-xs">
      <p className="mb-3 font-semibold text-sm">Notification channels</p>
      <Separator className="mb-1" />
      {channels.map((ch) => {
        const Icon = ch.icon;
        return (
          <label
            className="flex cursor-pointer items-start gap-3 border-b py-3 last:border-b-0"
            htmlFor={ch.id}
            key={ch.id}
          >
            <Checkbox
              checked={checked[ch.id]}
              id={ch.id}
              onCheckedChange={(val) => toggle(ch.id, !!val)}
            />
            <div
              className={`flex size-8 shrink-0 items-center justify-center rounded-md border transition-colors ${
                checked[ch.id]
                  ? "border-primary/20 bg-primary/10 text-primary"
                  : "border-border bg-muted/50 text-muted-foreground"
              }`}
            >
              <Icon className="size-3.5" />
            </div>
            <div className="flex flex-col gap-0.5">
              <span className="pt-0.5 font-medium text-sm leading-none">
                {ch.label}
              </span>
              <span className="text-muted-foreground text-xs">
                {ch.description}
              </span>
            </div>
          </label>
        );
      })}
    </div>
  );
}
```
