shadcn.io is not affiliated with official shadcn/ui
CSV Import File Upload Block for Svelte
A CSV parse step: a delimiter, a quote character and a header switch over editable sample text, with a live preview of the first six rows and the ragged rows named.
Installation
Overview
Let people fix a file before it is imported, with this CSV import panel for Svelte with Ark UI. It is the parse step of Sheetmatch, a CRM import tool. At the start, the settings: a Segment Group for the delimiter (comma, semicolon, tab or pipe), a Native Select for the quote character, a Switch for whether the first row is the header, and a Textarea holding a typed sample you can edit. At the end, a table previews the first six rows as they would import, and a list of problems names every row whose field count differs from the header ("Row 7 has 5 fields, expected 4") or whose quote never closes. A wrong delimiter shows one fat column and names the delimiter to try. A small parser reads quoted fields and doubled quotes. The File Upload zone lists a picked file by name only. Import counts the rows that fit and skips the rest. The panel is ruled by Guides, and the one primary is a Shine Button. For CRMs, admin tools and any importer that should show its working.
FAQ
What does the parser understand?
Fields split on the chosen delimiter, a field wrapped in the quote character may hold the delimiter, and two quote characters in a row inside quotes make one. A quote that opens and never closes is reported with its row number. Values with line breaks inside quotes are not joined; each physical line is its own row, which is also how the row numbers in the problem list count.
What is a ragged row?
A row whose number of fields differs from the first row's. In the sample, row 7 has an unquoted comma in its note, so it has five fields where the header has four. The preview marks it with an icon and the problem list says why. Quoting that note, or choosing another delimiter, clears it.
Why is a picked file only listed?
The block never opens a file, so a picked file shows its name and nothing more, and the text you edit stays the sample. That keeps the demo honest and nothing leaves your device. To parse a real file, read it with file.text() in the accept handler and put the result in the text state; the parser and the preview already follow it.
What does Import do?
It counts the rows that fit the header and says how many it skipped ("Imported 6 rows, skipped 1."). Nothing is sent or saved. In your app, replace the handler with a call that posts the good rows and returns the skipped ones for a download or a fix-up step.
How is it made accessible?
Every control is named, the delimiter group is labelled by its heading, and the preview and problem list are keyboard scroll regions with names. A ragged row carries an icon and hidden text that says it does not fit the header, so colour is never the only signal. One polite status line reports the result.