shadcn.io is not affiliated with official shadcn/ui
Duplicate Record Dialog CRUD Block for Vue
A wholesaler's product list with a Duplicate button per row that opens a dialog to name the copy, suggest the next SKU, tick what to carry over, and add the copy marked New with an Undo.
Installation
Overview
Start a new record from an existing one without retyping it, with this duplicate dialog for Vue with Ark UI. It starts from the Products page of Clonewick, a homeware wholesaler: five real rows with name, SKU, variants, notes, price and stock, each with an outline Duplicate Button, under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog prefills the name as "Linen cushion (copy)" and selects it for typing, suggests the SKU by adding one to the highest SKU in the list ("CSH-014" becomes "CSH-015") and checks both for shape and uniqueness with a reason under the field, and asks what to carry over with four Checkboxes: pricing, variants and notes on, the stock count off with "Counts start at 0". Create copy, the only Shine Button, puts the copy at the end of the list marked New, scrolls the frame to it and focuses it, and the foot says "Created Linen cushion (copy) with pricing, variants and notes." beside an Undo that removes it. For product catalogues, plan lists, templates and any record that is mostly a variation of another.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the dialog is a copy drawn in place over the real product list: a native dialog element that isn't modal, so nothing is trapped, hidden or focused. A row's Duplicate opens the real Dialog, modal, with its focus trap, the name selected for typing and focus back on that row when it closes, and the copy stays closed until a reload. Both show the same CopyFields component and share the block's state. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element in the frame.
How is the SKU suggested and checked?
The suggestion keeps the source's three letters and takes the highest number in the whole list plus one, so a copy of the wool throw is "THR-015" while the cushion is "CSH-015". A SKU must be three capital letters, a dash and three digits, and must not belong to another product; the Problem line names the product that holds it. The checks run when you press Create copy, then follow your typing, and a refused press focuses the first field to fix.
What does each checkbox carry over?
Pricing copies the price, variants and notes copy their counts, and the stock count copies the units in stock. Anything left unticked starts empty: no price, zero variants, zero notes, zero stock. The line under each box says what it copies, and the foot names what was carried after the copy is made.
What does Undo restore?
It removes the copy that was just made and puts focus back on the Duplicate button of the product it came from. It undoes the last copy only; there is nothing older to restore here, and nothing times out. The "New" mark goes with the copy.
What stays local, and how do I wire a real copy?
The five products are typed in PRODUCTS and the copy is added to state; a reload brings the originals back and nothing is sent. In your app post the draft in create, show a uniqueness error from the server on the field it names, and add the row from the response. New ids come from a counter held in state, never the clock.
Is it accessible from the keyboard?
Yes. The real dialog is named by its title and described by its sentence, focus starts in the Name field with its text selected, and Escape returns focus to the row's Duplicate button. Every field has a label and a problem slot that is always rendered, and each checkbox is named by its label with its hint as the description. The copy shown on load moves no focus; Escape inside it and its Close button behave like the real dialog's.