Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Bulk Edit Form Block for Radix UI

A shelf list where you tick several items and give them one status together: a mixed select-all box, an Apply that marks changed rows Updated, Undo last apply, and a filter that can empty the list.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Change many rows at once without opening each one, with this bulk edit form for React with Radix UI. A compact header sits over a hairline frame with a plus mark on each corner. The first band is a toolbar: how many items are selected (its space is always reserved), a Set status select, an Apply button, Undo last apply and a Show select that can narrow the list to the items that still need a status. Under it, a list head holds a Checkbox that is mixed while only some of the shown rows are picked, then eight products, each with its own box, a name you can edit where it stands and a status select. Apply sets the chosen status on exactly the selected rows, marks those rows Updated and says how many changed, and it tells you when the rows already had that status. Undo last apply puts the statuses back. Filtering to Needs a status and applying a status to all of them empties the list, so the Empty state is reachable inside the same held box. The foot holds the Shine Button Save list, the only colored control, with a polite status line. It stays inert until something has changed. It's built from Checkbox, Input, Native Select, Badge, Empty, Button, Shine Button and Guides, with a CSS entrance only. For inventory, user lists, task triage and any list where one change applies to many.

FAQ

How do I change the items and the statuses?

Edit START for the items and STATUSES for the options. An item is { id, name, status }, and an empty status means it needs one. The counts, the head box and the Show filter are all derived from the list, never typed twice.

How does the select-all box work?

It is checked when every shown row is picked, mixed when some are, and clear when none are. Pressing it picks every shown row, or clears the selection if all were picked. The count and the box follow the shown rows only: with the Show filter on, hidden rows are never changed by Apply.

What does Undo last apply undo?

The last Apply, whole: it puts every row's status back to what it was just before and clears the Updated marks. Edits to a name, or a status chosen on a single row, are not part of it. The button stays focusable but inert when there is nothing to undo, and says so.

How does it look on a phone, and for assistive tech?

Each row stacks: box and name, then the status, then the Updated mark in its reserved slot, so nothing shifts when it appears. Every box and select is named for its item ("Select Tahini, 400 g"), and the status line, the block's one polite region, reads every result.

What stays local, and how do I connect it for real?

Everything: Save list keeps the items in this tab and says "Saved 8 items in this demo. Nothing was sent." To make it real, send the changed rows from the submit handler, or the one bulk change as a single request with the ids, and let the server's answer drive the Updated marks.

How do I connect it to react-hook-form or TanStack Form?

Keep the items as a field array and the selection as separate state, since it is not part of the record. With react-hook-form, call setValue for each selected index in apply, with shouldDirty: true, and keep the previous array for undo.