Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

File Upload with List Input for Svelte

An Upload Files field that accepts several files and then lists each name, its size in KB, and a remove button.

UI library: Ark UI

An Upload Files label and a file field that accepts more than one file. After a pick, each row shows a file icon, the name, the size in KB, and a remove button.

Use it when people attach a few files before they submit. A dashed drop zone that keeps the list is File Upload. In Svelte, Ark UI does not remove the input's file when the row goes away.

Preview

Preview width

Installation

MCP · Pro
Make your AI a shadcn expert
Your agent installs components, builds pages and restyles your app from one prompt, in Claude Code, Cursor or VS Code.
Part of Pro

Anatomy

Input anatomy: input, placeholder, value, caret

Usage

<Field class="w-full max-w-sm"><FieldLabel>Upload Files</FieldLabel><Input class="bg-background" multiple oninput={handleFileChange} type="file" />{#if files.length > 0}<ul class="flex flex-col gap-2">{#each files as file, index (`${file.name}-${file.lastModified}`)}<li class="flex items-center justify-between gap-2 rounded-md border p-2"><div class="flex min-w-0 items-center gap-2"><FileTextIcon aria-hidden="true" class="size-4 shrink-0 text-muted-foreground" /><span class="truncate text-sm">{file.name}</span><span class="shrink-0 text-muted-foreground text-xs">({(file.size / 1024).toFixed(1)} KB)</span></div><Button aria-label={`Remove ${file.name}`} data-index={index} onclick={handleRemove} size="icon-xs" type="button" variant="ghost"><XIcon aria-hidden="true" /></Button></li>{/each}</ul>{:else}{/if}</Field>

FAQ

How does the field accept several files?

multiple on the file input lets the picker select more than one. Each time the selection changes, the chosen files are copied from the input into a list kept in state, which renders the rows.

What does each row show?

A FileTextIcon, the file name, truncated when it's long, and the size in kilobytes with one decimal, from the file's size divided by 1024. The rows are a list with a border and rounded corners.

How does the remove button work?

It's a ghost Button at size icon-xs with an XIcon. It carries its row's index in data-index and removes that file from the list. Its aria-label names the file, such as Remove report.pdf.

Does removing a row change what the input holds?

No. The list is the example's own state; the browser's file input still holds the files from the last pick. Submit the list from state, for example with FormData, rather than the input itself.

How do I limit the file types?

Add accept to the input, such as accept="image/*" or accept=".pdf,.docx". The picker then filters to those types; check them again on the server.

How is Upload Files tied to the field?

Clicking the label focuses the field, and screen readers announce it with the field. Field links FieldLabel to the input inside it, so there is no id to match.

API Reference

Field

No extra props in this demo. The rest is on the Field page.

Input

Sets multiple, oninput={handleFileChange} and type="file". The rest is on the Input page.

Button

Sets aria-label, Remove, file, name, data-index={index} and onclick={handleRemove}. The rest is on the Button page.