# V switch 8

> Switch with descriptions in card grid

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

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

## Install

```bash
npx shadcn@latest add https://ui.cnippet.dev/r/v-switch-8.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/switch`

## Files

### `registry/default/variants/v-switch-8.tsx`

```tsx
"use client";

import { BarChart3Icon, BugIcon, DatabaseIcon, GlobeIcon } from "lucide-react";
import { useState } from "react";

import { Field, FieldLabel } from "@/registry/default/ui/field";
import { Switch } from "@/registry/default/ui/switch";

const features = [
  {
    checked: true,
    description: "Track page views and user interactions",
    icon: <BarChart3Icon aria-hidden="true" className="size-4" />,
    id: "feat-analytics",
    title: "Analytics",
  },
  {
    checked: true,
    description: "Capture and report runtime errors",
    icon: <BugIcon aria-hidden="true" className="size-4" />,
    id: "feat-logging",
    title: "Error Logging",
  },
  {
    checked: false,
    description: "Serve static assets from edge network",
    icon: <GlobeIcon aria-hidden="true" className="size-4" />,
    id: "feat-cdn",
    title: "CDN Caching",
  },
  {
    checked: false,
    description: "Daily snapshots of your database",
    icon: <DatabaseIcon aria-hidden="true" className="size-4" />,
    id: "feat-backup",
    title: "Auto Backup",
  },
];

export function Pattern() {
  const [checked, setChecked] = useState<Record<string, boolean>>(
    Object.fromEntries(features.map((f) => [f.id, f.checked])),
  );

  return (
    <div className="grid w-full max-w-lg grid-cols-2 gap-4">
      {features.map((feature) => (
        <Field key={feature.id}>
          <FieldLabel
            className={`h-full w-full cursor-pointer rounded-xl border p-3 transition-colors ${
              checked[feature.id]
                ? "border-primary/5 bg-sidebar"
                : "border-border"
            }`}
            htmlFor={feature.id}
          >
            <div className="flex w-full items-start justify-between gap-2">
              <div className="flex items-start gap-2">
                <div
                  className={`flex shrink-0 items-center justify-center rounded-md border p-1.5 shadow-black/5 shadow-xs transition-colors ${
                    checked[feature.id]
                      ? "border-primary/30 bg-primary/10 text-primary"
                      : "border-border bg-background"
                  }`}
                >
                  {feature.icon}
                </div>
                <div className="flex flex-col items-start gap-0.5">
                  <span className="font-semibold text-sm">{feature.title}</span>
                  <span className="text-muted-foreground text-xs">
                    {feature.description}
                  </span>
                </div>
              </div>
              <Switch
                checked={checked[feature.id]}
                id={feature.id}
                onCheckedChange={(val) =>
                  setChecked((prev) => ({ ...prev, [feature.id]: val }))
                }
              />
            </div>
          </FieldLabel>
        </Field>
      ))}
    </div>
  );
}
```
