# Changed files summary with border markers

> Changed files summary with border markers

A shadcn/ui block from the [@reui](https://reui.io) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/reui/c-marker-5).

- Page, with a live preview: https://shadcn.exchange/r/reui/c-marker-5
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/reui/c-marker-5-light-7ed33c6e7c772c52.png
- Registry item: https://reui.io/r/new-york-v4/c-marker-5.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://reui.io/r/new-york-v4/c-marker-5.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: `@reui/badge`, `marker`

## Files

### `c-marker-5.tsx`

```tsx
import type { ReactNode } from "react"
import { Badge } from "@/components/reui/badge"

import {
  Marker,
  MarkerContent,
  MarkerIcon,
} from "@/components/ui/marker"
import { IconPlaceholder } from "@/app/(create)/components/icon-placeholder"

type Change = {
  path: string
  kind: "added" | "modified" | "removed"
  delta: string
}

const CHANGES: Change[] = [
  { path: "src/lib/rate-limit.ts", kind: "added", delta: "+64" },
  { path: "src/app/api/send/route.ts", kind: "modified", delta: "+18 -4" },
  { path: "src/db/schema.ts", kind: "modified", delta: "+6 -1" },
  { path: "src/lib/legacy-throttle.ts", kind: "removed", delta: "-91" },
  { path: "README.md", kind: "modified", delta: "+3" },
]

// Both maps are written out per kind rather than assembled from the kind
// string, so every icon library prop stays a literal the registry installer
// can rewrite and every badge variant stays one the design system declares.
const ICONS: Record<Change["kind"], ReactNode> = {
  added: (
    <IconPlaceholder
      lucide="PlusIcon"
      tabler="IconPlus"
      hugeicons="PlusSignIcon"
      phosphor="PlusIcon"
      remixicon="RiAddLine"
    />
  ),
  modified: (
    <IconPlaceholder
      lucide="PencilIcon"
      tabler="IconPencil"
      hugeicons="PenIcon"
      phosphor="PencilIcon"
      remixicon="RiPencilLine"
    />
  ),
  removed: (
    <IconPlaceholder
      lucide="Trash2Icon"
      tabler="IconTrash"
      hugeicons="Delete02Icon"
      phosphor="TrashIcon"
      remixicon="RiDeleteBinLine"
    />
  ),
}

const BADGES: Record<
  Change["kind"],
  "success-light" | "info-light" | "destructive-light"
> = {
  added: "success-light",
  modified: "info-light",
  removed: "destructive-light",
}

// The border variant rules off a row from the one BELOW it, so the last row
// drops back to the default: leaving it on ends the list on a line with
// nothing under it, which reads as a missing sixth file.
//
// The path is its own block level span because truncation needs a block box to
// apply to, and it carries a title so the tail a narrow card clips is still
// recoverable.
//
// The auto margin belongs on the badge, not on the delta: on the delta alone
// each badge trails its own path, and five paths of five lengths read ragged.
export function Pattern() {
  return (
    <div className="mx-auto flex w-full max-w-sm flex-col gap-2">
      {CHANGES.map((change, index) => (
        <Marker
          key={change.path}
          variant={index < CHANGES.length - 1 ? "border" : "default"}
        >
          <MarkerIcon>{ICONS[change.kind]}</MarkerIcon>
          <MarkerContent>
            <span
              className="block truncate font-mono text-xs"
              title={change.path}
            >
              {change.path}
            </span>
          </MarkerContent>
          <Badge className="ms-auto" variant={BADGES[change.kind]}>
            {change.kind}
          </Badge>
          <span className="shrink-0 text-xs tabular-nums">{change.delta}</span>
        </Marker>
      ))}
    </div>
  )
}
```
