shadcn.io is not affiliated with official shadcn/ui
Merge Records Survivor CRUD Block for React Aria
A CRM duplicate finder with a queue of suspected groups and, for the open one, the records side by side, a Survivor radio per record, a Take from select per differing field, summed orders and notes, and an Undo merge.
Installation
Overview
Merge two or three records into one without losing anything that matters, with this duplicate finder for React with React Aria. It is a hairline frame with a plus mark on each corner for Joinwick, a CRM: a queue of three suspected groups at the start ("Hana Thorvaldsen, 3 records", matched by email and name; on a phone it becomes a Native Select) and the open group at the end. The group's records are the columns of a table that counts each one's orders and notes, a Survivor radio sits in each column head, and every field that differs has a "Take from" select in the last column, with the record numbers that hold each value. An empty value never overwrites a filled one, so a field only one record has fills itself. Orders and notes add up. The foot shows the merged record and "7 orders and 2 notes will point to it"; Merge records, the only Shine Button, turns the group into "Merged 3 into 1" in an Empty state with a Badge in the queue, and "Undo merge" in the foot restores all three records. For CRMs, contact books, product catalogues and any list that collects duplicates.
FAQ
What does the survivor decide?
The survivor is the record that stays: it keeps its place in the list and its id, and every order and note of the others is repointed to it. Choosing a different survivor resets every field to that record's values (or to the first filled value where the survivor's is empty), and starts as the record with the most orders. Nothing about the others is kept except what you took.
How are the field values chosen?
A field that has two or more different filled values gets a select named "Take name from", "Take email from" and so on, whose options show each value with the records that hold it. A field that is the same everywhere, or filled in only one record, has no choice to make and says so. The ticked cell in each row shows which record's value the merged record takes, and the merged record in the foot follows every choice.
What does Undo merge restore?
All of the group's records, as they were: the survivor and the choices you had made are put back and the group returns to the queue as open. It undoes the last merge only; merging another group replaces it, and nothing times out. Every other merged group keeps its Merged mark in the queue.
What happens when every group is merged?
The pane keeps its height and shows the last merge in the catalog Empty state with "Every group is reviewed." The queue still lists all three, each marked Merged, and the foot's Undo merge still works. Nothing is hidden from the page, so the frame never changes size.
What stays local, and how do I wire a real merge?
The three groups are typed in GROUPS; the survivor, the choices and the merged flags live in this tab, and a reload brings the originals back. In your app post the survivor and the picks in merge, repoint orders and notes on the server in one transaction, and make Undo call a restore endpoint. This block merges records in a list; merging two accounts field by field in a dialog is dialog-merge-accounts.
Is it accessible from the keyboard?
Yes. The survivor radios are one group named for the person, arrow keys move between records, and each select is named for its field. The table has a caption and row and column headings, and it scrolls sideways in a region that is reachable by keyboard on a phone. The queue is a list of buttons with the open group marked current, or a select on a phone, and the foot is the one polite status.