# Changelog

> A list of product releases for a changelog page, newest first: each with its date and version, a title, a short summary, an optional cover, and its changes marked New, Improved, Fixed, or Removed.

- Name: `changelog`
- Status: beta
- Categories: changelog, releases, updates, marketing
- Files: the install writes `changelog.tsx`, and any part files named `changelog-*.tsx`, to your `components` alias, `@/components` by default. Edit them freely. They are yours.
- Other registry items: `@arbokui/badge`, `@arbokui/button`, `@arbokui/glide-highlight`, `@arbokui/panel-switch`, `@arbokui/tabs`. The install adds them.
- Gallery: https://arbokui.com/website/changelog
- Registry item: https://arbokui.com/r/changelog.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the website component. It also adds every component it uses:

   ```bash
   npx shadcn@latest add @arbokui/changelog
   ```

## Use it for

- The body of a changelog page, under a Headline as the page's h1. Each release title is an h2.
- Pass \`releases\` newest first. Write each \`date\` as an ISO date, like "2026-10-28". It shows in words, like "October 28, 2026", the same on the server and in every browser.
- Give a release a \`version\`, like "2.4", and it gets the id "2-4", so a link to /changelog#2-4 lands on it. With no version, pass an \`id\` of your own. Keep every id unique on the page.
- A link to a release that is hidden, past the limit or out of the filter, still lands: the list shows it at once, then scrolls to it.
- Mark each change with a \`type\`: "new" is green, "removed" is red, and "improved" and "fixed" stay gray, so the news stands out.
- Set \`limit\` for a long list. It shows that many, then a Show older releases button that shows the rest in place and moves focus to the first one it showed.
- Set \`filter\` to add tabs for each type of change in your releases. A tab shows only the releases with that type, and only those changes.
- Pass a \`cover\` for a release worth a picture, like a drawing from our illustrations or a screenshot. It fills a 16:9 frame.
- The dates stick below a floating navbar as you read, and a link scrolls each release to the same place. Both read \`--changelog-offset\`, 6rem by default. Set it in \`className\`, like \`\[--changelog-offset:1rem\]\`, when nothing floats over the page.

## Avoid it for

- An in-app feed of who did what, or the day's running order. Use Timeline, which keeps each item to one line on a rail.
- Live updates or alerts inside an app. Use a Toast or an Alert.
- Every commit or ticket. Group them into releases people can read, a few changes each.
- Long change lines. Keep each to one sentence, and put the detail in the summary or a page of its own.

## Props

- `releases`: `{ date: string; version?: string; id?: string; title: ReactNode; summary?: ReactNode; cover?: ReactNode; changes?: { type: "new" | "improved" | "fixed" | "removed"; text: ReactNode }[] }[]`. Default `[]`. The releases, newest first. date is an ISO date. version also gives the release its id, "2.4" as "2-4", unless you pass id. cover fills a 16:9 frame. Each change has a type and its words. With none, it says there are no releases yet.
- `limit`: `number`. Shows this many first, then a Show older releases button that shows the rest. With none, every release shows.
- `filter`: `boolean`. Default `false`. Adds tabs over the list, All and one per type of change your releases have. It needs two types or more.
- `locale`: `string`. Default `"en-US"`. The language the dates are written in, like "en-GB" or "de-DE".
- `className`: `string`. Extra classes on the root, which holds the container query. The date column sits beside each release from 48rem of its own width, and above it when narrower. Set --changelog-offset here.
- `ChangelogRelease`: `{ date: string; version?: string; id?: string; title: ReactNode; summary?: ReactNode; cover?: ReactNode; changes?: ChangelogChange[] }`. Type. One release.
- `ChangelogChange`: `{ type: "new" | "improved" | "fixed" | "removed"; text: ReactNode }`. Type. One change in a release.

## Accessibility

- The releases are an ordered list, newest first. Each is an article named by its title, an h2, so put the list under the page's h1.
- Each date is a \<time> with the ISO date in dateTime.
- Each change's type is written on its badge, so it never rests on color alone.
- The tabs are named "Type of change". Arrow keys move between them. When the list changes, screen readers hear how many releases are left.
- Show older releases is a real button. Once pressed, it goes away and focus moves to the first release it showed, which sits where the button was.
- The hover fill is for the pointer only. Nothing in a release takes focus by itself.
- Reduced motion keeps the fades and drops the slides and the height glide.
- In forced colors each cover keeps a border, since its fill is painted away.

## Examples

### Releases with versions, covers, and changes

```tsx
<Changelog
  releases={[
    {
      date: "2026-10-28",
      version: "2.4",
      title: "Shared views",
      summary: "Save a filtered view of any list and share it with your team.",
      cover: <ThemeLayers />,
      changes: [
        { type: "new", text: "Save any filter as a view." },
        { type: "improved", text: "Column widths stay put when you switch views." },
        { type: "fixed", text: "Sorting by date no longer puts empty dates first." },
      ],
    },
    {
      date: "2026-10-14",
      version: "2.3",
      title: "Faster search",
      changes: [{ type: "improved", text: "Results show as you type." }],
    },
  ]}
/>
```

### A long list that starts short, with tabs for each type of change

```tsx
<Changelog releases={releases} limit={5} filter />
```

### A changelog page under a floating navbar

```tsx
<Navbar floating {...navbar} />
<main className="mx-auto flex max-w-7xl flex-col gap-16 px-4 pt-12">
  <Headline as="h1" align="start" title="Changelog" description="New features, improvements, and fixes." />
  <Changelog releases={releases} limit={5} filter />
</main>
```

### Dates in British English, with nothing floating over the page

```tsx
<Changelog releases={releases} locale="en-GB" className="[--changelog-offset:1rem]" />
```
