# V command 14

> Appearance picker with theme and accent-color options and active check marks

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

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

## Install

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

## Files

### `registry/default/variants/v-command-14.tsx`

```tsx
"use client";

import { CheckIcon, MoonIcon, SunIcon, SunMediumIcon } from "lucide-react";
import { Fragment, useState } from "react";
import { Button } from "@/registry/default/ui/button";
import {
  Command,
  CommandCollection,
  CommandDialog,
  CommandDialogPopup,
  CommandDialogTrigger,
  CommandEmpty,
  CommandGroup,
  CommandGroupLabel,
  CommandInput,
  CommandItem,
  CommandList,
  CommandPanel,
  CommandSeparator,
} from "@/registry/default/ui/command";

type Option = { icon: React.ReactNode; label: string; value: string };
type OptionGroup = { items: Option[]; label: string; value: string };

const optionGroups: OptionGroup[] = [
  {
    items: [
      { icon: <SunIcon className="size-4" />, label: "Light", value: "light" },
      { icon: <MoonIcon className="size-4" />, label: "Dark", value: "dark" },
      {
        icon: <SunMediumIcon className="size-4" />,
        label: "System",
        value: "system",
      },
    ],
    label: "Theme",
    value: "theme",
  },
  {
    items: [
      {
        icon: <span className="size-4 rounded-full bg-violet-500" />,
        label: "Violet",
        value: "violet",
      },
      {
        icon: <span className="size-4 rounded-full bg-blue-500" />,
        label: "Blue",
        value: "blue",
      },
      {
        icon: <span className="size-4 rounded-full bg-emerald-500" />,
        label: "Green",
        value: "green",
      },
      {
        icon: <span className="size-4 rounded-full bg-rose-500" />,
        label: "Rose",
        value: "rose",
      },
      {
        icon: <span className="size-4 rounded-full bg-orange-500" />,
        label: "Orange",
        value: "orange",
      },
    ],
    label: "Accent Color",
    value: "accent",
  },
];

export default function Particle() {
  const [open, setOpen] = useState(false);
  const [theme, setTheme] = useState("light");
  const [accent, setAccent] = useState("violet");

  const handleSelect = (group: string, value: string) => {
    if (group === "theme") setTheme(value);
    else setAccent(value);
    setOpen(false);
  };

  return (
    <CommandDialog onOpenChange={setOpen} open={open}>
      <CommandDialogTrigger render={<Button variant="outline" />}>
        Appearance settings
      </CommandDialogTrigger>
      <CommandDialogPopup>
        <Command items={optionGroups}>
          <CommandInput placeholder="Search appearance..." />
          <CommandPanel>
            <CommandEmpty>No options found.</CommandEmpty>
            <CommandList>
              {(group: OptionGroup, i: number) => (
                <Fragment key={group.value}>
                  {i > 0 && <CommandSeparator />}
                  <CommandGroup items={group.items}>
                    <CommandGroupLabel>{group.label}</CommandGroupLabel>
                    <CommandCollection>
                      {(opt: Option) => {
                        const isActive =
                          group.value === "theme"
                            ? theme === opt.value
                            : accent === opt.value;
                        return (
                          <CommandItem
                            className="gap-2"
                            key={opt.value}
                            onSelect={() =>
                              handleSelect(group.value, opt.value)
                            }
                            value={`${group.value}-${opt.value}`}
                          >
                            {opt.icon}
                            <span className="flex-1">{opt.label}</span>
                            {isActive && (
                              <CheckIcon className="size-4 text-primary" />
                            )}
                          </CommandItem>
                        );
                      }}
                    </CommandCollection>
                  </CommandGroup>
                </Fragment>
              )}
            </CommandList>
          </CommandPanel>
        </Command>
      </CommandDialogPopup>
    </CommandDialog>
  );
}
```
