Overview
A 3-step wizard for importing data from CSV or JSON. Automatically detects format, validates against a Zod schema, and allows inline editing to fix errors before final import.
Key Capabilities
Data Input
- Paste data or upload CSV/JSON files
- Auto-detect format (CSV vs JSON)
- Download template files for correct format
Validation & Editing
- Zod schema validation per row
- Inline editing to fix validation errors
- Fuzzy matching for lookup fields
When to Use ImportWizardBlock
- Bulk importing data from spreadsheets or external systems
- Allowing users to paste or upload data without strict format requirements
- Providing error correction before committing imports
Quick Start
Define your import columns and Zod schema, then render the ImportButton component.
import { ImportButton, type ImportColumn } from '@/ui/blocks';
import { z } from 'zod';
const schema = z.object({
name: z.string().min(1),
email: z.string().email(),
status: z.enum(['active', 'pending']),
});
const columns: ImportColumn[] = [
{ key: 'name', label: 'Name', type: 'text', required: true },
{ key: 'email', label: 'Email', type: 'text', required: true },
{ key: 'status', label: 'Status', type: 'choice', choices: ['active', 'pending'] },
];
<ImportButton
columns={columns}
schema={schema}
entityName="users"
onImport={async (data) => {
await bulkCreateUsers(data);
return { success: true, importedCount: data.length };
}}
/>Live Examples
Basic Import
Simple import with text and choice fields. Click the button to open the wizard.
Multiple Field Types
Import with text, number, date, and boolean fields. Uses matchPatterns for flexible column matching.
Integration with AdminListTable
Add an import button to the AdminListTableBlock toolbar for seamless integration.
Add ImportButton to the toolbar.actions array to enable import alongside your table.
// In a page with AdminListTableBlock
import { AdminListTableBlock, ImportButton } from '@/ui/blocks';
<AdminListTableBlock
items={items}
columns={tableColumns}
toolbar={{
actions: [
<ImportButton
key="import"
columns={importColumns}
schema={itemSchema}
entityName="items"
onImport={handleBulkImport}
/>
]
}}
/>Column Configuration
Each ImportColumn defines a field in your import schema.
| Prop | Type | Description |
|---|---|---|
key | string | Internal field key (matches Zod schema property) |
label | string | Display label for templates and mapping UI |
type | 'text' | 'number' | 'date' | 'choice' | 'boolean' | 'lookup' | Field data type for parsing and editing |
required | boolean | Whether the field must have a value |
choices | string[] | Valid values for choice fields |
matchPatterns | string[] | Alternative column names for auto-matching |
example | string | Example value for template files |
Props Reference
Core Props
Required props for configuring the import wizard.
| Prop | Type | Default | Description |
|---|---|---|---|
columns | ImportColumn[] | required | Array of ImportColumn configurations |
schema | z.ZodType<T> | required | Zod schema for validating each row |
onImport | (data: T[]) => Promise<ImportResult> | required | Callback when import is confirmed |
entityName | string | 'items' | Entity name for display (e.g., 'users', 'projects') |
Options
Optional props for customizing behavior.
| Prop | Type | Default | Description |
|---|---|---|---|
batchMode | 'simple' | 'chunked' | 'simple' | Processing mode: 'simple' for <100 rows, 'chunked' for larger imports |
chunkSize | number | 50 | Number of rows per chunk when using chunked mode |
title | string | - | Custom modal title (overrides default) |
description | string | - | Modal description text |
ImportButton Props
Props specific to the ImportButton companion component.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'outline' | 'ghost' | 'outline' | Button visual style |
size | 'default' | 'sm' | 'lg' | 'default' | Button size |
label | string | - | Custom button label (defaults to 'Import') |
disabled | boolean | false | Disable the button |
Usage Pattern
Add ImportButton to your page toolbar to enable bulk import functionality alongside your data tables.
// In a page with AdminListTableBlock
import { AdminListTableBlock, ImportButton } from '@/ui/blocks';
<AdminListTableBlock
items={items}
columns={tableColumns}
toolbar={{
actions: [
<ImportButton
key="import"
columns={importColumns}
schema={itemSchema}
entityName="items"
onImport={handleBulkImport}
/>
]
}}
/>