shadcn.io is not affiliated with official shadcn/ui
Compare Changes Form Block for Radix UI
A price change shown against what is live: current values as plain text beside editable proposed values, a Changed mark with the old value on every edited row, a Revert per row, a count of changes and a Request approval action.
Installation
Overview
Show people exactly what a change will do before it goes anywhere, with this compare form for React with Radix UI. A compact header sits over a hairline frame with a plus mark on each corner. One product, a walnut desk, is laid out as four rows: list price, discount, availability and a note for the approver. Each row has three columns: the label with a hint, the current value as plain read-only text, and the proposed value as a field. A row whose proposal differs says "Changed, was $48.00" with a glyph and shows its own Revert button; a row that breaks a rule, a price that is not a positive amount or a discount outside 0 to 60, names the rule instead. The band heading counts the changes, and the foot holds the Shine Button Request approval, the only colored control, with a polite status line. It stays inert until at least one value differs, and a request with a problem moves focus to the first field to fix. Below the large breakpoint each row stacks the current value above the proposed one. It's built from Field, Input, Native Select, Button, Shine Button and Guides, with a CSS entrance only. For price lists, settings reviews, profile changes and any form where someone else approves the difference.
FAQ
How do I change the fields and the live values?
Edit CURRENT for what is live, LABELS and HINTS for the row text, and SLOTS for the order. A rule is a branch in problemOf and what counts as a change is changedOf, so a price of 48 and 48.00 are the same value. The count, the Changed marks and the status line all derive from those two functions.
What does Revert do?
It puts that one row's proposed value back to the current one, moves focus to its field and says so in the status line ("List price is back to $48.00."). The button keeps its space when the row is unchanged, so rows never change height, and is hidden from the tab order until there is something to revert.
How is the difference conveyed without color?
Always with words and a glyph: "Changed, was $48.00" with a diff icon, and a problem as an alert icon with its sentence. The column names Current and Proposed are visible from the medium breakpoint and read to assistive tech as hidden prefixes on every cell, so a screen reader hears "Current $48.00" and "Proposed" before each field.
How does it look on a phone, and right to left?
Each row stacks: label, current value, then the proposed field with its Changed line and Revert. In a right-to-left page the columns mirror and prices are kept left to right so the digits stay in order.
What stays local, and how do I connect it for real?
Everything: Request approval says "Requested approval for 2 changes in this demo." and sends nothing. To make it real, post only the changed rows (changes holds their slots) with the live values you compared against, and have the server reject the request if those values have moved since, so an approver never signs off a stale diff.