GitHubnpm

Accent theme

Base radius

GitHubnpm

Accent theme

Base radius

Colour scheme

Docs menu

Guides


Primitives
Forms
Layout
Feedback
Overlays
Navigation
Data Display
AI

File Upload

A real <input type="file">, wrapped entirely inside a real <label> that IS the drop zone — the whole padded area is natively clickable, no .click()forwarding needed. Drag-and-drop is a progressive enhancement on top of that: the native element has none, and accept only filters the OS dialog, never a drop, so both are reimplemented once and reused by whichever path a file actually arrives through. The real input stays authoritative either way — dropped files are re-assigned onto its own .files via a fresh DataTransfer, so it still participates correctly in a plain, non-JS <form> submission. While dragging, the active wash scales outward from the pointer's live position; its radius is counter-scaled to preserve the dropzone's roundness, and reduced-motion users get a simple opacity transition. Opt into preview to mould the dropzone around the selection — displayable images fill or tile as object-URL thumbnails; other files show as compact name chips. Pair with aspectRatio="square" for a 1:1 tile that uses Card's concentric radius pair (--kernel-radius-sheet outer, --kernel-radius-md inner via --kernel-padding-sheet).

Playground

Toggle every adjustable prop and watch the component — and the code — update live.

Drag any desktop item into the dropzone — images preview; other types list as files.

Unstyled

Same component — Kernel look stripped. See Platforms.

multiple
preview
aspect ratio
invalid
disabled
hide label
label offset
Usage
<FileUpload label="Upload files" description="Any file type" multiple preview aspectRatio="square" maxFiles={8} errorMessage="That file is too large." />

Props

Props for File Upload.
PropTypeDefault
labelReactNode (required)
hideLabelbooleanfalse
descriptionReactNode
filesFile[]
defaultFilesFile[][]
acceptstring
multiplebooleanfalse
maxFilesnumber
maxSizenumber (bytes)
previewbooleanfalse
aspectRatio"auto" | "square""auto"
onError(error) => void
errorMessageReactNode
invalidbooleanfalse
disabledbooleanfalse

Rejections (wrong type, over maxSize, over maxFiles, or a dropped folder rather than a file) reject the whole attempted batch and call onError rather than silently keeping only some of what was dropped. Dropping accumulates onto the existing selection; re-opening the OS picker still replaces it, the same as the native element's own behaviour — that inconsistency comes from the browser, not from this wrapper.

Accessibility

  • Drag-and-drop is a progressive enhancement only: Tab to the drop zone, Enter or Space opens the native OS dialog, fully usable with zero pointer/drag involvement.
  • Each file's remove button gets aria-label="Remove {filename}" since it's otherwise an icon-only control.
  • Rejected files go through the same role="alert" error region as every other Kernel form field's errorMessage.