shadcn.io is not affiliated with official shadcn/ui
Bulk Actions Table Block for Vue
A contacts table whose head checkbox ticks the page, a strip that offers to select all 48 contacts across pages, a toolbar that swaps to Archive, Tag and Delete at the same height, and an Undo receipt.
Installation
Overview
Act on many rows at once, even rows you can't see, with this bulk actions table for Vue with Ark UI. A framed panel holds a native table of eight contacts from a small-business contacts app (name and email, company, status), each with a Checkbox; the one in the head ticks the page, with a dash when only some rows are ticked. Once the whole page is ticked a strip under the toolbar says "All 8 on this page are selected" and offers "Select all 48 contacts", because the other 40 are on pages you haven't loaded. Selecting rows swaps the toolbar for an action bar of exactly the same height: how many are selected, Archive as the one Shine Button, Tag and Delete, and Clear. Delete asks first in an Alert Dialog. Archive and Delete take the rows out, an Empty state fills the same frame when the page runs out, and a receipt in the strip ("Archived 48 contacts in this demo.") has an Undo that puts them all back. It's built from Checkbox, Alert Dialog, Shine Button, Button, Badge, Empty and Guides, with a CSS entrance only. For contact lists, inboxes, admin consoles and any table with more rows than one page.
FAQ
How does select across pages work?
The block holds two things: which rows of the page are ticked, and a flag that says every contact is selected. The head checkbox ticks the page. Only when the whole page is ticked, and more contacts exist than the page shows, does the strip offer "Select all 48 contacts", which sets the flag; the action bar then counts all 48. Unticking any row, or pressing "Only this page", drops the flag again. Wire the flag to a "select everything that matches this query" request on your server.
Why doesn't the toolbar change height?
The toolbar and the action bar sit in one grid cell and the one you are not using is unseen, so the band is as tall as the taller of the two whichever shows. The strip under it always holds a line, and the table lives in a frame of fixed height with a sticky head, so ticking, archiving and emptying the page never move anything below.
What do Archive, Delete and Undo do?
Both take the ticked rows out of the table and take their count off the total, and both leave a receipt in the strip with an Undo. Undo restores exactly those rows, including the ones counted from other pages, and moves focus back to the head checkbox. Delete confirms first in an alert dialog whose focus starts on Cancel and returns to Delete if you back out. Tag marks the ticked rows "Follow up", and pressing it again on rows that all have it clears the mark.
Is it accessible?
It's a real table with a caption, column headers and the contact as each row header; every box is named ("Select" and the contact, "Select all contacts on this page"). One polite status line, present from load, announces each change: how many are selected, what was archived or deleted and that Undo is above the table. Selected rows are marked by a tint, a bar and the count, never colour alone, and the ticked-some state is a dash, not a tick.
How does it look on a phone?
The company folds away, leaving name, email and status, and the action bar becomes two rows: the count with Clear, then Archive, Tag and Delete across the width. The strip keeps room for two lines so it never moves the table.
What stays local?
All 48 contacts are demo data: eight rows and a count for the rest. Archive, Tag and Delete only change this page's state and say so; nothing is sent or saved, and reloading brings everything back. To make it real, send the ids (or the query, when everything is selected) to your API, remove the rows when it answers, and keep the receipt until the request can be undone.