shadcn.io is not affiliated with official shadcn/ui
Table Filter Chips Command Menu Block for Vue
A records table's command menu hung from its Filter button: Status, Priority, Assignee and Due options become removable chips and the table behind re-renders to the records that match, with a Showing 4 of 12 count.
Installation
Overview
Filter a table without leaving the keyboard with this table filter command menu for Vue with Ark UI. It opens from the Records page in Rowlark, a records table, whose header holds an outline field with its ⌘ K cap, and the table is drawn under a soft scrim inside a hairline frame with a plus mark on each corner, with the menu hung from its Filter button. The menu is the catalog Command in the wide size: four groups of options, Status, Priority, Assignee and Due, each row a check box, the option and how many of the twelve records carry it. Each pick adds a removable chip to the band above the field and the drawn table behind it re-renders to the records that match, the band saying "Showing 4 of 12 records"; options in one group widen the match and groups narrow it. A row and a button clear every filter. For preview the menu is drawn open in place when the page loads; the field, or Ctrl or ⌘ K while focus is in the block, opens the real command dialog with the same filters and query. For data tables, admin lists and any screen where filters are many and screen space is not.
FAQ
Why is the menu already open, and what do I keep?
So you can see it without a click. On load the menu is the Command drawn inline over a picture of a records table, in a plain shell that is not modal, so nothing is trapped, hidden or focused and the page around the preview keeps working. The header's field opens the real command dialog, modal, with its focus trap, Escape and focus return, and the inline copy stays closed until a reload. Both show the same Palette and share the block's state, so the filters in the copy is in the dialog. In your app keep the dialog and drop the copy: the "in-place" state, the scrim with its shell and the Escape and blur effects.
How do the filters combine?
Within a group they are an OR (Status is Open or Blocked) and across groups an AND (and Priority is High). matchedBy applies that to the typed records, and the drawn table, the chip band and the status line all read the same result. Choosing an option that is already on removes it, and each chip is a button named "Remove filter Status: Open".
How is Due worked out?
The block compares ISO dates, as text, against a fixed day (18 October 2026) with fixed ends for this week and next, so Overdue, Due this week, Due next week and Later give the same records on every load. In your app compute the same buckets from the current date on the server, in the viewer's time zone, and send the bucket or the range to your query.
Why is the chip band always the same height?
So adding the first chip or the twelfth never moves the field or the list. The band is one line tall, holds a hint when nothing is on, and scrolls sideways when the chips are many; the count text drops out on a phone, where the status line and the table behind carry it. Clear all is a button there and a row in the list while any filter is on.
What stays local, and how do I wire it?
All of it. The twelve records and their values are typed constants and the table is a drawing, so nothing is queried. In your app turn the chips in active into query parameters or a request body, keep them in the URL so a filtered view can be shared, and take the option counts from a facet query rather than from the loaded page.
Is it accessible from the keyboard?
Yes. Type to search, the arrow keys move through the rows, Enter adds or removes a filter, and Tab reaches each chip's remove button and Clear all. Escape closes the menu with focus on the field, and Ctrl or ⌘ K opens the dialog while focus is inside the block, and only then. The rows are options of a combobox and the first is highlighted when it opens.