WorkflowAlea Pro
ReviewChanges
A merge-style review of what someone else changed while you worked: Base, Mine and Theirs side by side, each numbered change with where it is, who made it and when, a choice of Mine, Theirs or Both, apply all, undo, redo and saved points to go back to.
import { ReviewChanges } from '@alea-design/pro';
Examples
Review changes
Base, Mine and Theirs for each change; choose, apply all, undo and redo. The component keeps the choices when you do not pass them.
Case 1042
The three people of the case scenario: three changes to the same record, with Both offered for the text fields only.
Safety and effect
A change with safety needs a second, explicit step and is never applied by Apply all. The effect slot shows what choosing would cause.
Undo, redo and history
Hold the choices in your state to undo, redo and go back to a saved point from before or after merging.
What you pass and what you get back
ReviewChanges knows nothing about your data or your network. You pass changes: an id, where it is (screen, record, field), its kind (added, removed, modified), the base, mine and theirs values, the author and the time. You get back onResolve({ changeId, choice }) for each choice and onApplyAll({ choice, changeIds }) after the confirmation.
Without choices the component keeps the choices itself and offers undo and redo. With choices you hold them: it calls onUndo and onRedo and reads canUndo and canRedo, so you can keep them in your own history.
The shape of a change
| Field | What it is |
|---|---|
| id | A stable id for the change. |
| location | Where it lives: { screen, record, field }, read from the widest to the narrowest. |
| kind | added, removed or modified: what the other person did. |
| valueKind | text (default), number, flag or list. |
| base, mine, theirs | The three values: what you both started from, yours and theirs. |
| author, at | Who made the change ({ id, name }) and when. |
| safety | confirm: choosing needs a second, explicit step and Apply all skips it. |
| hidden | The values are not shown, listed or applied; the change only counts in the summary line. |
| renderValue | Draws a value your way: (value, { side, change }) returns a node. |
| effect | A computed effect drawn under the values. |
Value kinds
| valueKind | Looks like | Both |
|---|---|---|
| text | Plain text, line breaks kept | Yes |
| list | A bulleted list | Yes |
| number | Formatted for the language | No |
| flag | On or off | No |
History points
Pass history with a point saved before merging and one after, and onRestore receives the point whose Restore was pressed. Restoring means setting your choices to what that point held, so keep the choices in your own state.
Tokens
The design tokens this component reads, with their value in the current theme. Override any of them to restyle it.
Color
--alea-accent…--alea-accent-subtle…--alea-bg…--alea-border…--alea-border-strong…--alea-status-warning…--alea-status-warning-bg…--alea-surface…--alea-surface-raised…--alea-text…--alea-text-muted…
Space
--alea-space-0-5…--alea-space-1…--alea-space-2…--alea-space-3…--alea-space-4…--alea-space-6…
Radius
--alea-radius-full…--alea-radius-md…--alea-radius-sm…
Type
--alea-font-family-body…--alea-font-size-sm…--alea-font-size-xs…--alea-font-weight-medium…--alea-font-weight-semibold…
Component
--alea-hit-min…
Props
ReviewChanges props
A merge-style review of what someone else changed while you worked: Base, Mine and Theirs side by side, each change with where it is, who made it and when, and a choice of Mine, Theirs or Both. Apply all mine or theirs (after a confirmation), undo, redo and saved points to go back to. It knows nothing about your data or your network: you pass the changes and read the choices back. Keys while a change has focus: N and P (or the arrows) move between changes, M, T and B choose. A change with safety never applies on its own.
| Prop | Type | Default | Description |
|---|---|---|---|
changesrequired | ReviewChange[] | Every change to review. | |
canRedo | boolean | false | Whether Redo is possible (controlled mode only). |
canUndo | boolean | false | Whether Undo is possible (controlled mode only; otherwise the component knows). |
choices | ReviewChoices | none | What is chosen for each change id (controlled). Without it the component keeps the choices itself and offers undo and redo. |
className | string | none | Extra class names for the root element. |
defaultChoices | ReviewChoices | none | What is chosen to start with (uncontrolled). |
headingLevel | 2 | 3 | 4 | 5 | 1 | 2 | The outline level of the heading; the history heading is one deeper. Default 2. |
hiddenLabel | ((count: number) => ReactNode) | "N changes are hidden" | The summary line for hidden changes. Default "N changes are hidden". |
history | ReviewHistoryPoint[] | none | Saved points to go back to: before and after merging. |
onApplyAll | ((event: { choice: "mine" | "theirs"; changeIds: string[]; }) => void) | none | Called after "Apply all mine" or "Apply all theirs" is confirmed, with the ids it set. Changes with safety and hidden ones are never in it. |
onRedo | (() => void) | none | Called on Redo. |
onResolve | ((event: { changeId: string; choice: "mine" | "theirs" | "both"; }) => void) | none | Called when a choice is made, after the confirmation step for a change with safety. |
onRestore | ((point: ReviewHistoryPoint) => void) | none | Called with the point whose Restore was pressed. Restoring means setting your choices to what that point held, so it needs controlled choices. |
onUndo | (() => void) | none | Called on Undo. In controlled mode you undo; the component asks. |
title | ReactNode | "Review changes" | The heading. Default "Review changes". |
Specs
Generated from the source: the variants in the types, the states and tokens in the CSS, and the motion patterns that apply. The grids render the real component in both themes; the numbers are measured from the page.
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-review-none.alea-review-list-value.alea-review.alea-review-head.alea-review-title.alea-review-count.alea-review-tools.alea-review-hint.alea-review-empty.alea-review-items.alea-review-item.alea-review-card- Data attributes
data-decideddata-chosendata-markdata-mark=addeddata-mark=modifieddata-mark=removed
Accessibility
- Every change is a group named like "Change 3 of 7, Amount, modified by Ana on Nov 9, 2026, 4:12 PM", and the place is read from the widest part to the narrowest.
- Added, removed and modified are words with an icon and a line style (underline, dotted underline, strike-through), never color alone.
- The chosen value is marked with a check, an outline and the words "Mine chosen", and the buttons are pressed toggles.
- Choices, undo, redo, apply all and restore are announced in a polite status, joined when they come close together.
- A change with safety needs a second, explicit step and "Apply all" never touches it; nothing is applied by default.
- Values you hide are not in the page at all: only the summary line you word is read.
- Below 40 rem of room, and at 200 percent text, Base, Mine and Theirs stack one under the other; the buttons keep a 44 px target on touch screens.
- Light, dark, high contrast, Windows forced colors, reduced motion and right to left are covered.
Keyboard
| Key | Does |
|---|---|
| Tab | Moves into the list (one stop), then through the buttons of the change |
| N or Down arrow | Next change (while a change has focus) |
| P or Up arrow | Previous change |
| Home or End | First or last change |
| M | Choose mine |
| T | Choose theirs |
| B | Choose both (text and lists only) |
| Enter (on Confirm) | Confirms a change that needs it |
Do and don't
Do
- Pass every change with its where (screen, record, field), its author and its time: they are what make a long list readable.
- Set valueKind and use renderValue for money, dates and rich text; numbers are never animated.
- Mark customs, money and legal dates with safety="confirm".
- Hide what the person may not see with hidden and word the summary yourself with hiddenLabel.
- Control the choices when you want to save them or restore saved points.
Don't
- Don't offer Both for a number or a flag: two numbers do not add up to a number.
- Don't apply anything on load: nothing is chosen until the person chooses.
- Don't put a domain widget inside the component: draw your own value with renderValue.
In Figma
The properties of the Figma components, generated from the kit, so they always match it. The last column is the React prop each one stands for.
Review change · 24 variants
| Figma property | Kind | Values | Default | React prop |
|---|---|---|---|---|
| Layout | Variant | Wide, Stacked | Wide | className |
| Kind | Variant | Modified, Added, Removed | Modified | changes |
| Decision | Variant | Undecided, Mine, Theirs, Both | Undecided | choices, onResolve |
| Screen | Text | - | Case 1042 | changes |
| Record | Text | - | Payment | changes |
| Field | Text | - | Amount | changes |
| Author | Text | - | Ana, | changes |
| Time | Text | - | Nov 9, 2026, 4:12 PM | changes |
| Number | Text | - | 3 | changes |
| Base value | Text | - | Consulting | changes |
| Mine value | Text | - | Consulting, March | changes |
| Effect text | Text | - | The tax would go from 120 to 150. | changes |
| Confirm text | Text | - | Use theirs for Amount? | changes |
| Both | Boolean | - | true | changes |
| Effect | Boolean | - | false | changes |
| Safety | Boolean | - | false | changes |
| Confirm step | Boolean | - | false | changes |
Review changes · 2 variants
| Figma property | Kind | Values | Default | React prop |
|---|---|---|---|---|
| Layout | Variant | Wide, Stacked | Wide | className |
| Title | Text | - | Review changes | title |
| Count | Text | - | 1 of 3 decided | changes |
| Summary text | Text | - | 2 clinical changes a doctor reviews | hiddenLabel |
| Hidden summary | Boolean | - | true | hiddenLabel |
| History | Boolean | - | true | history |