vaiperui

components / upload

Upload

Area to pick files by clicking or dragging them in, with an accept filter.

How to use

The Upload only **captures** files: listing them, validating the size and sending them to a server are up to you. `onFilesChange` receives plain `File[]` with the files just chosen, not the sum with earlier ones, so merge them into your own state to accumulate. It is a real `<input type="file">` hidden only visually (Tab to focus, Enter or Space to open), and `accept` also filters dragged files, which the browser does not do by itself. Without `multiple`, only the first file of a selection is kept. Always validate again on the server.

preview
  • No files yet
Upload.tsx
import { Upload } from "vaiperui";
const [files, setFiles] = useState<File[]>([]);
<Upload
multiple
accept=".pdf,image/*"
label="Attachments"
description="PDF or image, up to 5 MB"
onFilesChange={(chosen) => setFiles((current) => [...current, ...chosen])}
/>

Sizes

preview
sm
md
lg
sizes.tsx
<Upload size="sm" onFilesChange={...} />
<Upload size="md" onFilesChange={...} />
<Upload size="lg" onFilesChange={...} />

Colors

The color shows on hover, while dragging and on keyboard focus.

preview
primary
success
warning
danger
colors.tsx
<Upload variantColor="primary" onFilesChange={...} />
<Upload variantColor="success" onFilesChange={...} />
<Upload variantColor="warning" onFilesChange={...} />
<Upload variantColor="danger" onFilesChange={...} />

Accepted types

preview
.pdf
image/* + multiple
accept.tsx
<Upload accept=".pdf" description="PDF" />
<Upload accept="image/*" multiple description="Images" />

States

preview
Extra detail
helper
The file must be a PDF
error
disabled
states.tsx
<Upload label="..." helperText="..." />
<Upload label="..." errorMessage="..." />
<Upload label="..." disabled />

Custom color

preview
Orange
custom-color.tsx
<Upload customColor="#ff6600" onFilesChange={...} />

Props

PropValuesDefaultDescription
onFilesChange(files: File[]) => voidrequiredCalled with the files just chosen (not the sum with earlier ones)
titleReactNode"Drag files here or click to choose"Main text of the area
descriptionReactNodenoneSupport text, e.g. accepted formats and size
acceptstringnoneAccepted types: .pdf, image/*, image/png, comma-separated. Also filters dragged files
multiplebooleanfalseAccepts several files. Without it, only the first of a selection is kept
label / helperTextstringnoneLabel above the area and help text below
errorMessagestringnoneError text; its presence alone forces the error state (red border, aria-invalid)
disabledbooleanfalseBlocks click and drag
namestringnoneField name for a native <form> (dropped files are mirrored into the input)
variantColorprimary | success | warning | dangerprimaryColor of the checked state and focus ring
customColorstring | { light, dark }noneAny CSS color (or a pair per theme). Overrides variantColor
sizesm | md | lgmdSize of the control and its text
animationnone | smooth | fast | bouncesmoothTransition when it toggles
radiusnone | sm | md | lg | fulllgCorner rounding of the area
(native)InputHTMLAttributes<HTMLInputElement>nonechecked, defaultChecked, onChange, name, value, disabled, required, aria-*, className, ref, etc.

Accessibility

  • A native `<input type="file">` (visually hidden) is the real control; the dashed area is a `<label htmlFor>` for it.
  • The input is focusable and the focus ring shows on the drop area (`peer-focus-visible`), so keyboard focus is visible.
  • The accessible name is the `title` text inside the area, plus `label` when you pass one (the input has both labels).
  • `errorMessage` sets `aria-invalid="true"`; `aria-describedby` points to the error, or to `helperText` when there is no error.
  • Drag and drop is an extra path: keyboard and screen reader users open the system picker through the native input. The upload icon is `aria-hidden`.

Keyboard

KeyAction
TabFocuses the file input.
Enter / SpaceOpens the system file picker (native input behavior).

Keep in mind

  • Files rejected by `accept` are dropped silently, with no message or live region; validate and tell the user in `errorMessage`.
  • Selected files are not listed by the component; render the list yourself and make it readable by assistive tech.