shadcn.io is not affiliated with official shadcn/ui
Export Data Dialog Block for Svelte
A usage-report tool's Exports page with its export dialog shown open: a CSV or JSON format, a range with row counts, six fields behind a mixed Select all box and a size estimate, and a Download button that saves a real file.
Installation
Overview
Let people take their data with them, with this export dialog for Svelte with Ark UI. It opens from the Exports page of Reportory, a usage-report tool: the page's header holds an outline Export data Button, and the page itself, a list of the files already made, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The dialog holds a Segment Group for the format, a Select for the range with its row count, and six fields as Checkboxes behind a Select all box that turns mixed when only some are on. A line under them estimates the whole export from the range, the format and the fields, and says plainly when nothing is picked. Download CSV, the only Shine Button, is a Download Trigger: it saves a real file that holds the five sample rows typed in the block, with the fields you chose, then closes the dialog and adds a row to the page behind it. For preview the dialog is drawn open in place when the page loads; the Export data button opens the real Dialog, with the same controls and the same choices. For reports, admin tables, billing history and any app that hands data back.
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 page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Export data button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same ExportFields component and share the block's state, so a format picked in the copy is there in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
What does the downloaded file hold?
The five sample rows typed in SAMPLE, with only the fields you ticked, in table order, as CSV with a header row or as a JSON array. The file is real and the browser saves it, named for the range and the format, such as reportory-usage-30d.csv. The data is not the range you chose: the dialog and this page say so, and the estimate line describes the whole export your app would build. Nothing is uploaded and no request goes out.
Where does the size estimate come from?
From a pure helper, bytesOf: the row count of the range times the bytes of the picked fields, plus what the format adds around each value, a comma in CSV and the key and its punctuation in JSON. It is a guess, written as "about", and it moves as you change the range, the format or a field. In your app ask your server for the real count and size, or keep the estimate and let the file be the truth.
How does Select all work, and what if nothing is picked?
The box is ticked when every field is on, mixed when some are, and empty when none are; pressing it ticks everything or clears everything. With no field on, the Download button turns quiet and stays focusable, the line under the fields says to pick one, and pressing it answers in the polite status message instead of saving an empty file.
What stays local, and how do I wire a real export?
The past-exports list on the page is local state: a download adds a row for the file you just made, and a reload clears it. In your app build the file on your server for the chosen range and fields, give DownloadTrigger a URL or a function that returns a Blob, and add the row from the response. For a long export, start a job, close the dialog with a polite message, and let the page list the file when it is ready.
Is it accessible from the keyboard?
Yes. The real dialog is named by its title and described by its sentence, focus stays inside until it closes, and Escape, Cancel and the close button return focus to Export data. The trigger is the button wrapped in DialogTrigger with asChild, and the dialog is controlled with open and onOpenChange. The format moves with the arrow keys, every field is a labelled checkbox, and the copy shown on load moves no focus; Escape inside it, Cancel and its close button close it and put focus on Export data.