Version history

Going back to earlier drafts of something written with AI: a history sidebar in a document, a timeline you scrub through on a canvas, and two versions compared side by side.

Loading preview…

Install

  1. 1

    Run this command in your Tailwind CSS project. It adds components/ai/version-history-default.tsx and installs its dependencies.

    $ npx shadcn@latest add https://gradientdeck.com/ai-components/r/version-history-default.json

Usage & API

Example

version-history-default.tsx
import { VersionHistory } from "@/components/ai/version-history-default"

<VersionHistory
  versions={[]}
  selectedId="…"
  onSelect={() => {}}
  onRestore={() => {}}
  onRename={() => {}}
/>

Props VersionHistory

PropType & descriptionRequired
versionsDocVersion[]Newest first. The first one is the current document.Required
selectedIdstringRequired
onSelect(id: string) => voidRequired
onRestore(id: string) => voidRequired
onRename(id: string, name: string) => voidRequired
docPathstringOptional

Dependencies

  • React
  • Tailwind CSS
  • motion
  • lucide-react
Implementation notes

Document sidebar is a full window. The title row shows a path, defaulting to Marketing, the current title, the time it was edited, two initials, a History mark, and a Share button. Share has no handler in the file. The article shows a word count and the title and body. On the current row those render as plain text. On an older row they render through a word diff, and a legend in the banner explains the green and red marks. Back to current reselects the first id. Restore this version calls onRestore with the selected id. The side panel is labelled Version history and counts the rows. Days are group headings. Each group is a listbox. Up and down arrows move the selection and the focus. A pencil on the row turns the name into a field with a forty-character limit. Enter or blur saves through onRename. Escape cancels. The current row wears a Current pill. The preview's article is a product announcement, with assistant and human rows across Today.

Choosing a layout

Use the document sidebar when the draft is the product and the history is a panel beside it. People can scan Today and Yesterday, name a version in place, and restore without leaving the article. The Share control and the two initial marks in the header are part of that chrome. Use the canvas timeline when the artifact was built in a thread and each user message produced the next snapshot. Scrubbing the slider, pressing a version chip in the thread, or using the arrows all set the same index. Use compare when keeping the newer wording is a decision per section, not a restore of the whole file. Accept these changes, Keep older, and Save as new version are that workflow.

Do not open the full history surface for a single suggested sentence. Prose diff already accepts or rejects inside the paragraph and stays the size of a card. Do not use compare to watch a picture or a table evolve. The compare panes are headings and paragraphs, with additions in green on the right and deletions in red on the left. The canvas is the variant that can hold a table, and in this file that table is a vendor shortlist with transit, on-time rate, an optional price, and notes. None of the variants record a version by themselves. Restoring, renaming, and saving call the parent, and the parent has to insert the new row.

Which variant is the document, the canvas, and the compare view?

default is the article plus the history sidebar, with rename and restore. scrubber is the thread, the artifact, and the version slider. Its export is the canvas timeline, not the sidebar component. compare is the two-pane review with per-block decisions and Save as new version. They do not share one props object. Each file has its own version shape.

Can both compare panes show the same version?

No. Each menu disables the id chosen on the other side, and that row explains it is shown on the other side. Keyboard and click both refuse that id. The panes can still be any other pair, and changing either pair resets the change navigator to the first difference.