# Redline: Design System

> A settings panel where every spacing label reads as a token through `tokens`, and `selector="[data-redline]"` keeps the pointer on named parts. Pin a row, hold Alt and point at another to see the space between them.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/redline-tokens-demo).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/redline-tokens-demo
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/keyframeui/redline-tokens-demo-light-53b772d134f255e9.png
- Registry item: https://keyframeui.com/r/redline-tokens-demo.json
- Categories: inspector, hover, design
- Listed: 2026-10-14, source last changed 2026-10-15

## Install

```bash
npx shadcn@latest add https://keyframeui.com/r/redline-tokens-demo.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: `https://keyframeui.com/r/redline.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/redline#redline-tokens-demo

## Files

### `registry/demos/redline-tokens-demo.tsx`

```tsx
import { Redline } from "@/components/ui/redline";

const tokens = {
  4: "space-1",
  8: "space-2",
  12: "space-3",
  16: "space-4",
  24: "space-6",
  32: "space-8",
};

const rows = [
  {
    name: "Comments",
    note: "Replies and mentions in threads you follow",
    on: true,
    icon: "M4 5h16v11H8l-4 4V5Z",
  },
  {
    name: "Reviews",
    note: "When someone asks you to review a file",
    on: true,
    icon: "M5 12.5 9.5 17 19 7",
  },
  {
    name: "Weekly digest",
    note: "A summary of the week, every Monday",
    on: false,
    icon: "M4 6h16M4 12h16M4 18h10",
  },
];

export function RedlineTokensDemo() {
  return (
    <div className="w-full max-w-md text-zinc-900 dark:text-zinc-50">
      <Redline
        tokens={tokens}
        selector="[data-redline]"
        tour={["panel", ["Comments row", "Reviews row"], "header", "footer"]}
        aria-label="Notification settings, with spacing tokens"
        className="rounded-2xl"
      >
        <div
          data-redline="panel"
          className="flex flex-col gap-6 rounded-2xl bg-white p-6 shadow-sm ring-1 ring-zinc-950/5 dark:bg-zinc-900 dark:ring-white/10"
        >
          <header data-redline="header" className="flex flex-col gap-1">
            <h3 data-redline="heading" className="text-base/6 font-semibold">
              Notifications
            </h3>
            <p data-redline="summary" className="text-sm/5 text-zinc-500 dark:text-zinc-400">
              Choose what reaches you, and when.
            </p>
          </header>

          <ul data-redline="list" className="flex flex-col gap-2">
            {rows.map((row) => (
              <li
                key={row.name}
                data-redline={`${row.name} row`}
                className="flex items-center gap-3 rounded-xl bg-zinc-50 p-4 ring-1 ring-zinc-950/5 dark:bg-zinc-950/50 dark:ring-white/5"
              >
                <span
                  data-redline={`${row.name} icon`}
                  className="grid size-8 shrink-0 place-items-center rounded-lg bg-white ring-1 ring-zinc-950/10 dark:bg-zinc-800 dark:ring-white/10"
                >
                  <svg
                    viewBox="0 0 24 24"
                    aria-hidden
                    className="size-4 fill-none stroke-current stroke-2 text-zinc-500 dark:text-zinc-400"
                    strokeLinecap="round"
                    strokeLinejoin="round"
                  >
                    <path d={row.icon} />
                  </svg>
                </span>
                <span className="min-w-0 flex-1">
                  <span className="block text-sm/5 font-medium">{row.name}</span>
                  <span className="block truncate text-xs/4 text-zinc-500 dark:text-zinc-400">
                    {row.note}
                  </span>
                </span>
                <span
                  data-redline={`${row.name} switch`}
                  role="img"
                  aria-label={row.on ? "On" : "Off"}
                  className={
                    row.on
                      ? "flex h-5 w-9 shrink-0 justify-end rounded-full bg-zinc-900 p-0.5 dark:bg-zinc-50"
                      : "flex h-5 w-9 shrink-0 rounded-full bg-zinc-200 p-0.5 dark:bg-zinc-700"
                  }
                >
                  <span
                    className={
                      row.on
                        ? "size-4 rounded-full bg-white shadow-sm dark:bg-zinc-900"
                        : "size-4 rounded-full bg-white shadow-sm dark:bg-zinc-300"
                    }
                  />
                </span>
              </li>
            ))}
          </ul>

          <footer
            data-redline="footer"
            className="flex justify-end gap-2 border-t border-zinc-950/5 pt-6 dark:border-white/10"
          >
            <button
              data-redline="cancel"
              type="button"
              className="h-9 rounded-lg px-4 text-sm font-medium text-zinc-600 ring-1 ring-zinc-950/10 dark:text-zinc-300 dark:ring-white/15"
            >
              Cancel
            </button>
            <button
              data-redline="save"
              type="button"
              className="h-9 rounded-lg bg-zinc-900 px-4 text-sm font-medium text-white dark:bg-zinc-50 dark:text-zinc-900"
            >
              Save
            </button>
          </footer>
        </div>
      </Redline>

      <p className="mt-10 text-center text-xs/5 text-pretty text-zinc-500">
        Click a row to pin it, then hold{" "}
        <kbd className="rounded bg-zinc-100 px-1.5 py-0.5 font-sans text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300">
          ⌥ Option
        </kbd>{" "}
        and point at another. On a phone, tap two rows.
      </p>
    </div>
  );
}
```
