shadcn.io is not affiliated with official shadcn/ui
Undo and Redo Form Block for React Aria
Document properties with a history list: Undo and Redo in the header with their keys, a run of typing as one entry, entries you can jump to, undone entries kept until you type, and a status line that says what moved.
Installation
Overview
Give people a way back from every edit, with this undo and redo form for React with React Aria. A header with Undo and Redo buttons at its end, each showing its keys, sits over a hairline frame with a plus mark on each corner. The frame has a title, a description and a tags field on one side and a History list on the other. Every change becomes an entry, but a run of typing in one field counts as one: it is written when the field loses focus or 800 ms after the last key, so Undo takes back a thought rather than a letter. Ctrl or Cmd plus Z undoes, adding Shift redoes, and choosing an entry in the history jumps straight to it. Entries after the current one stay listed as Undone until something new is typed, which cuts them off, and the list keeps the last twelve. The polite line says what moved, "Undid Title changed.", and a button with nothing to do stays focusable but inert and says so. The foot holds the Shine Button Save document, the only colored control, inert until the properties differ from the saved ones. On a phone the history sits under the form in a scroll box of its own. It's built from Field, Input, Textarea, Kbd, Button, Shine Button and Guides, with a CSS entrance only. For document editors, design tools, settings and any form where a mistake should be cheap.
FAQ
How do I change the fields and what counts as one entry?
Edit START for the document and LABELS for the entry names. PAUSE is the typing pause (800 ms) and CAP is the number of entries kept. Entries are written by pushedOf, which writes nothing when the field's value is the same as the current entry's, so typing a letter and deleting it leaves no entry.
Which keys does it handle, and how do they coexist with the browser's own undo?
Ctrl or Cmd+Z undoes, Ctrl or Cmd+Shift+Z or Ctrl+Y redoes, while focus is inside the block. They replace the browser's per-field undo, so one stack covers all three fields. The buttons carry aria-keyshortcuts for the same keys, and the key hints are decoration, hidden from assistive tech.
What happens when I jump back and then type?
The entries after the one you jumped to are dropped and the new change becomes the next entry, as in any editor. Until then they stay in the list marked Undone, so you can jump forward again or press Redo.
How is it announced and reached?
Each history entry is a button, the current one is marked as current and read as "Current state", and the list is a scroll region you can reach with Tab. The block has one polite status line ("Undid Title changed.", "Went to Tags changed."), and the counter "3 of 5" in the history heading is a plain figure.
What stays local, and how do I connect it for real?
Everything, including the history: nothing is sent and a reload starts again. To make it real, save the document from the submit handler and, if the history should survive, store the entries on your side. A shared document needs an operation log on the server rather than whole-document snapshots.
How do I connect it to react-hook-form or TanStack Form?
Keep the history outside the form library and let it write the form's values on undo, redo and jump. With react-hook-form, call reset(entry.doc, { keepDefaultValues: true }) or setValue for each field from goTo, and push entries from watch using the same pause.