# V toggle 11

> Bookmark toggle per article row with saved count

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

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

## Install

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

## Files

### `registry/default/variants/v-toggle-11.tsx`

```tsx
"use client";

import { BookmarkIcon } from "lucide-react";
import { useState } from "react";
import { Toggle } from "@/registry/default/ui/toggle";

const articles = [
  {
    author: "Olivia Martin",
    id: "1",
    title: "Building scalable design systems with Base UI",
  },
  {
    author: "Jackson Lee",
    id: "2",
    title: "Tailwind CSS v4 migration guide",
  },
  {
    author: "Isabella Nguyen",
    id: "3",
    title: "Accessible React components from scratch",
  },
];

export function Pattern() {
  const [saved, setSaved] = useState<Set<string>>(new Set());

  const toggle = (id: string) =>
    setSaved((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });

  return (
    <div className="w-full max-w-sm space-y-2">
      {articles.map((a) => {
        const isBookmarked = saved.has(a.id);
        return (
          <div
            className="flex items-center justify-between gap-2 rounded-lg border border-border px-3 py-2.5"
            key={a.id}
          >
            <div className="flex min-w-0 flex-col gap-0.5">
              <span className="truncate font-medium text-sm">{a.title}</span>
              <span className="text-muted-foreground text-xs">{a.author}</span>
            </div>
            <Toggle
              aria-label={isBookmarked ? "Remove bookmark" : "Bookmark article"}
              className="shrink-0"
              onPressedChange={() => toggle(a.id)}
              pressed={isBookmarked}
              size="sm"
              variant="outline"
            >
              <BookmarkIcon
                className={`size-4 transition-colors ${isBookmarked ? "fill-current" : ""}`}
              />
            </Toggle>
          </div>
        );
      })}
      <p className="text-center text-muted-foreground text-xs">
        {saved.size} of {articles.length} saved
      </p>
    </div>
  );
}
```
