# Release Pill: Version Bump

> A dark developer-tool hero: monospace versions with a Feature, Fix or Breaking tag on each row, and a last row with the upgrade command whose copy button turns into Copied.

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

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/release-pill-devtool-demo
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/keyframeui/release-pill-devtool-demo-light-93e37254ec4b309b.png
- Registry item: https://keyframeui.com/r/release-pill-devtool-demo.json
- Categories: badge, hover, changelog
- Listed: 2026-10-14, source last changed 2026-10-15

## Install

```bash
npx shadcn@latest add https://keyframeui.com/r/release-pill-devtool-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/release-pill.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/release-pill#release-pill-devtool-demo

## Files

### `registry/demos/release-pill-devtool-demo.tsx`

```tsx
"use client";

import * as React from "react";

import { ReleasePill, type Release } from "@/components/ui/release-pill";

const KIND = {
  Feature: "bg-emerald-500/15 text-emerald-300",
  Fix: "bg-amber-500/15 text-amber-300",
  Breaking: "bg-rose-500/15 text-rose-300",
};

function Kind({ kind }: { kind: keyof typeof KIND }) {
  return (
    <span
      className={`shrink-0 rounded px-1.5 py-px font-mono text-[10px] leading-4 font-medium ${KIND[kind]}`}
    >
      {kind}
    </span>
  );
}

const releases: Release[] = [
  {
    version: "v3.2.0",
    title: "Parallel task graph",
    date: "Oct 10",
    href: "#v3.2.0",
    label: <Kind kind="Feature" />,
    summary: "Independent tasks run side by side. 2.4× faster on 8 cores.",
  },
  {
    version: "v3.1.4",
    title: "Fix watch-mode leak",
    date: "Oct 3",
    href: "#v3.1.4",
    label: <Kind kind="Fix" />,
  },
  {
    version: "v3.0.0",
    title: "ESM-only output",
    date: "Sep 19",
    href: "#v3.0.0",
    label: <Kind kind="Breaking" />,
  },
];

const COMMAND = "npm i acme@3";

function UpgradeCommand() {
  const [copied, setCopied] = React.useState(false);
  const timer = React.useRef(0);
  React.useEffect(() => () => window.clearTimeout(timer.current), []);

  const copy = () => {
    navigator.clipboard?.writeText(COMMAND).catch(() => {});
    setCopied(true);
    window.clearTimeout(timer.current);
    timer.current = window.setTimeout(() => setCopied(false), 1800);
  };

  return (
    <div className="flex items-center gap-2 font-mono text-xs">
      <span aria-hidden className="text-muted-foreground select-none">
        $
      </span>
      <code className="min-w-0 flex-1 truncate">{COMMAND}</code>
      <button
        type="button"
        onClick={copy}
        aria-label={copied ? "Copied" : `Copy ${COMMAND}`}
        className="relative inline-flex h-7 w-[4.5rem] shrink-0 cursor-pointer items-center justify-center rounded-md bg-foreground/10 text-[11px] font-medium outline-none hover:bg-foreground/15 focus-visible:ring-2 focus-visible:ring-foreground/60"
      >
        <span
          className={`absolute transition-all duration-200 ${copied ? "-translate-y-1.5 opacity-0" : "opacity-100"}`}
        >
          Copy
        </span>
        <span
          aria-hidden={!copied}
          className={`absolute inline-flex items-center gap-1 text-emerald-300 transition-all duration-200 ${copied ? "opacity-100" : "translate-y-1.5 opacity-0"}`}
        >
          <svg
            aria-hidden
            viewBox="0 0 16 16"
            className="size-3"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="m3.5 8.5 3 3 6-7" />
          </svg>
          Copied
        </span>
      </button>
    </div>
  );
}

export function ReleasePillDevtoolDemo() {
  return (
    // The panel is always dark, so it re-points the theme colors the pill reads.
    <section className="relative w-full max-w-3xl rounded-3xl bg-background px-6 py-16 text-center text-foreground ring-1 ring-white/10 [--background:#0b0b0e] [--foreground:#f4f4f5] [--muted-foreground:#9a9aa6] sm:py-24">
      <div className="flex flex-col items-center">
        <ReleasePill releases={releases} tag="Release" changelogHref="#changelog">
          <UpgradeCommand />
        </ReleasePill>

        <h2 className="mt-7 max-w-[16ch] font-mono text-3xl/[1.15] font-semibold tracking-tight text-balance sm:text-5xl/[1.1]">
          Builds that finish before you look away
        </h2>
        <p className="mt-5 max-w-md text-base/7 text-pretty text-muted-foreground">
          Acme runs your tasks as a graph, caches what hasn&apos;t changed, and tells you why when
          something does.
        </p>

        <div className="mt-9 flex flex-wrap items-center justify-center gap-3">
          <a
            href="#docs"
            className="inline-flex h-11 items-center rounded-lg bg-foreground px-5 text-sm font-medium text-background outline-none hover:opacity-90 focus-visible:ring-2 focus-visible:ring-foreground focus-visible:ring-offset-2 focus-visible:ring-offset-background"
          >
            Read the docs
          </a>
          <a
            href="#github"
            className="inline-flex h-11 items-center rounded-lg px-5 font-mono text-sm ring-1 ring-foreground/15 outline-none hover:bg-foreground/5 focus-visible:ring-2 focus-visible:ring-foreground"
          >
            github.com/acme
          </a>
        </div>
      </div>
    </section>
  );
}
```
