shadcn.io is not affiliated with official shadcn/ui
Report Generator Command Menu Block for React
A report generator's command menu shown open over a reports page: five templates, a format switch and a period switch, a three-row preview of the file, and a Generate that downloads a real CSV of the period.
Installation
Overview
Pick a report, a format and a period, see the first rows, and download them with this report command menu for React with Base UI. It opens from the reports page in Sheafwright, a report generator, whose header holds an outline field with its ⌘ K cap, and the page is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The menu is the catalog Command: five templates found by name or column, with two ToggleGroup switches above the field (CSV, PDF, XLSX and 7, 30 or 90 days), a preview under the list that follows the highlighted template and shows the first three rows of the period, and a Generate button. With CSV chosen, Generate or Enter downloads every row of the period as a real file built in the browser; with PDF or XLSX the button is aria-disabled and says "Preview only in this demo." On a phone the switches scroll sideways. 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 template, format, period and query. For dashboards, finance tools and admin consoles that export what you are looking at.
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 reports page, 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 a format, a period or a search 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.
What does Generate download?
A .csv file named after the template and the period, such as revenue-last-30-days.csv, with a Date column, the template's columns and every record of the period (the preview shows the first three). It is made in the browser with a Blob and a link, with values containing a comma or a quote wrapped in quotes. The status line names the file and its row count.
How does the period change the file?
Each record is typed with how many days before the report date it falls (18 Oct 2026), and a period keeps the records inside it: 7 days holds three, 30 days six and 90 days all eight. The dates are computed from that fixed day, never from the clock. The rows in the list say how many rows the period holds, and the preview and the file change with it.
Why are PDF and XLSX disabled?
Because the demo has no renderer for them. They can be chosen, so you see the whole control, but Generate is then aria-disabled rather than disabled: it stays focusable, it reads as muted, and pressing it, like the slot beside it, says "Preview only in this demo." In your app render those formats on the server and return a link.
What stays local, and how do I wire it?
The download is real; the data is typed. The five templates and their records are constants. In your app request the rows for the template and period when they change, render the preview from the first page of the response, and stream the full export from make instead of holding it in the page.
Is it accessible from the keyboard?
Yes. Type to search, the arrow keys move through the rows and the preview follows, Enter generates, and Tab reaches the format and period switches and Generate. 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 cmdk listbox; the block turns off its own fuzzy filter and lists the rows itself.