# V context menu 13

> File explorer rows with extension badge, rename, download, and delete per file

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

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

## Install

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

## Files

### `registry/default/variants/v-context-menu-13.tsx`

```tsx
"use client";

import {
  DownloadIcon,
  FolderOpenIcon,
  InfoIcon,
  PencilIcon,
  RefreshCwIcon,
  TrashIcon,
} from "lucide-react";
import { useState } from "react";
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuGroup,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from "@/registry/default/ui/context-menu";

type FileItem = {
  ext: string;
  id: string;
  modified: string;
  name: string;
  size: string;
};

const FILES: FileItem[] = [
  {
    ext: "tsx",
    id: "f1",
    modified: "2m ago",
    name: "button.tsx",
    size: "4.2 KB",
  },
  { ext: "ts", id: "f2", modified: "1h ago", name: "utils.ts", size: "1.8 KB" },
  {
    ext: "mdx",
    id: "f3",
    modified: "3h ago",
    name: "readme.mdx",
    size: "8.6 KB",
  },
  {
    ext: "json",
    id: "f4",
    modified: "1d ago",
    name: "package.json",
    size: "2.1 KB",
  },
];

const extColor: Record<string, string> = {
  json: "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-400",
  mdx: "bg-violet-100 text-violet-700 dark:bg-violet-900/40 dark:text-violet-400",
  ts: "bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-400",
  tsx: "bg-sky-100 text-sky-700 dark:bg-sky-900/40 dark:text-sky-400",
};

export function Pattern() {
  const [selected, setSelected] = useState<string | null>(null);

  return (
    <div className="w-full max-w-sm space-y-0.5 rounded-xl border p-1">
      {FILES.map((file) => (
        <ContextMenu key={file.id}>
          <ContextMenuTrigger
            className={`flex w-full cursor-default items-center justify-between rounded-md px-3 py-2 text-sm transition-colors hover:bg-muted ${selected === file.id ? "bg-muted" : ""}`}
            onClick={() => setSelected(file.id)}
          >
            <div className="flex items-center gap-2.5">
              <span
                className={`rounded px-1.5 py-0.5 font-mono font-semibold text-[10px] ${extColor[file.ext] ?? "bg-muted text-muted-foreground"}`}
              >
                .{file.ext}
              </span>
              <span>{file.name}</span>
            </div>
            <span className="text-muted-foreground text-xs">
              {file.modified}
            </span>
          </ContextMenuTrigger>
          <ContextMenuContent className="w-44">
            <ContextMenuGroup>
              <ContextMenuItem>
                <FolderOpenIcon />
                Open
              </ContextMenuItem>
              <ContextMenuItem>
                <PencilIcon />
                Rename
              </ContextMenuItem>
              <ContextMenuItem>
                <DownloadIcon />
                Download
              </ContextMenuItem>
            </ContextMenuGroup>
            <ContextMenuSeparator />
            <ContextMenuGroup>
              <ContextMenuItem>
                <InfoIcon />
                <span>
                  Get info
                  <span className="ml-auto text-muted-foreground text-xs">
                    {file.size}
                  </span>
                </span>
              </ContextMenuItem>
              <ContextMenuItem>
                <RefreshCwIcon />
                Refresh
              </ContextMenuItem>
            </ContextMenuGroup>
            <ContextMenuSeparator />
            <ContextMenuGroup>
              <ContextMenuItem variant="destructive">
                <TrashIcon />
                Delete
              </ContextMenuItem>
            </ContextMenuGroup>
          </ContextMenuContent>
        </ContextMenu>
      ))}
    </div>
  );
}
```
