Export Scope

Reads back exactly what an export file will hold, so it doesn't go out as page 1 of 250, silently capped or full of personal data.

StopsExport only had page 1 of 250

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/export-scope.json

The files land in your project. They're yours to edit.

Usage

export-scope-usage.tsx
import { ExportScope, type ExportScopeData } from "@/components/ui/export-scope"

<ExportScope
  scope={scope}
  onExport={(options, summary) => setDone(`Exported ${summary.rowCount.toLocaleString("en-IN")} rows (${options.rows === "all" ? "all pages" : options.rows}, personal data: ${options.pii}).`)}
/>

What it catches

  • Exporting only the current page when all rows were meant
  • Exports silently capped at a row limit
  • Active filters and the real date range, with a day count
  • Hidden columns and personal-data columns, with a mask option

Props

ExportScope props
PropTypeDefault
scope* (required)

What the table currently shows: filters, range, pages, columns.

ExportScopeData—
value

Controlled options.

ExportOptions—
defaultValue

Initial options when uncontrolled. Defaults to the current page, the way most "Export" buttons behave.

ExportOptions{ rows: "page", includeHidden: false, pii: "include" }
onValueChange

Called with the export options whenever they change.

(value: ExportOptions) => void—
onExport

Called with the chosen options and the readback. May return a Promise.

(options: ExportOptions, summary: ReturnType<typeof summarizeExport>) => void | Promise<void>—
locale

Locale for dates and numbers.

string—
title

Heading for the export panel.

string"This export includes"
downloadLabel

Template: `{count}` rows.

string"Download {count} rows"
pageOnlyText

Templates: `{exporting}`, `{total}`, `{requested}`, `{columns}`.

string"Only this page: {exporting} of {total} matching rows."
truncatedText

Warning when the export is capped.

string"Capped at {exporting} of {requested} rows. Narrow the fi…
piiText

Warning when personal-data columns are included.

string"Includes personal data: {columns}."
allRowsLabel

Text for the export-all fix.

string"Export all {total}"
maskLabel

Text for the mask fix.

string"Mask it"
labels

Override any other string.

Partial<typeof EXPORT_SCOPE_LABELS>—

* required. Also accepts the native props of <div> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Options are role="radiogroup" segmented controls with roving tabIndex and arrow keys
  • The readback is written in text

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: Apply the same scope, row limit and masking when generating the file on the server, and log exports of personal data.

  • Reads back the scope you describe; it doesn't produce the file
  • Which columns hold personal data is up to your scope definition

What it stops

Export only had page 1 of 250

Also known as

export · csv · download · data table · filters · date range · pii · excel

Field type

Dependencies

Pairs well with