Upload
Pick or drop files with a compact upload button or a dashed dropzone, built on react-dropzone.
Upload is a client component built on react-dropzone. It renders either a compact button (type="button") or a dashed drop area (type="dropzone"). Both open the file picker on click and accept dropped files. It accepts every useDropzone option, so validation (accept, maxSize, multiple, and so on) is handled by react-dropzone.
Drop images here
PNG, JPG or GIFImport#
import { Upload } from "@reactberry/system/blocks";
import type { UploadProps, UploadComponent, DropzoneProps } from "@reactberry/system/blocks";
Usage#
import { useState } from "react";
import { Upload } from "@reactberry/system/blocks";
export default function AvatarUpload() {
const [loading, setLoading] = useState(false);
return (
<Upload
type="dropzone"
accept={{ "image/*": [] }}
maxSize={5 * 1024 * 1024}
multiple={false}
loading={loading}
dropzoneProps={{ title: "Upload an avatar", description: "Images up to 5 MB" }}
onDropAccepted={async ([file]) => {
setLoading(true);
await uploadAvatar(file);
setLoading(false);
}}
onDropRejected={(rejections) => console.warn(rejections[0]?.errors)}
/>
);
}
Examples#
Custom button#
Pass any icon component to icon and restyle the button through buttonProps. Here accept limits the picker to PDFs.
Dropzone with an icon#
Use dropzoneProps to give the empty state an icon, a title and a description that explain what to drop.
Import a CSV
One row per contactLoading#
Set loading while files are being processed. Both looks show progress and stop accepting files.
API#
Upload#
| Prop | Type | Default | Description |
|---|---|---|---|
type | "button""dropzone" | "button" | Which look to render: a compact button or a dashed drop area. |
label | ReactNode | — | Button text. In the dropzone, the fallback text when |
icon | any | — | Button only. A component (not an element) rendered at |
dropzoneProps | Partial<DropzoneProps> | — | Dropzone only. Content of the empty state: |
loading | boolean | — | Disables the input and shows a loading state ("Working" on the button, "Processing…" in the dropzone). |
buttonProps | any | — | Button only. Props spread onto the |
dropzoneContainerProps | any | — | Dropzone only. Props spread onto the drop area |
Upload also accepts every useDropzone option: accept, onDrop, onDropAccepted, onDropRejected, maxSize, minSize, maxFiles, multiple, disabled, noClick, validator, and so on.
DropzoneProps#
| Prop | Type | Default | Description |
|---|---|---|---|
icon | ReactNode | — | Element shown above the title. |
title | ReactNode | — | Heading of the empty state. |
description | ReactNode | — | Text under the title. Falls back to |
showPreview | boolean | — | With |
imgSrc | string | — | Image shown when |
Accessibility#
- The button look renders a native
<button type="button">withrole="button", and is disabled whileloading. - The dropzone look is a focusable element (
tabindex="0") handled by react-dropzone.
| Key | Action |
|---|---|
Tab | Moves focus to the button or dropzone. |
EnterorSpace | Opens the file picker. |
Notes#
- The dropzone colour follows the drag state:
success.subtlewhen the dragged files are accepted,error.subtlewhen rejected,info.subtlewhile dragging, andbrand.subtleotherwise. loadingis passed to react-dropzone asdisabled; an explicitdisabledprop takes precedence.- The button spreads react-dropzone's root props after
buttonProps, so root handlers such asonClickandonKeyDownwin over the same keys inbuttonProps. - The preview uses
next/imagewithoutwidth,height, orfill. Next.js requires those for string sources, so a plain URL (including an object URL fromURL.createObjectURL) inimgSrcmakesnext/imagethrow. Use your own preview next to the dropzone until this is changed. dropzoneContainerProps.stylereplaces the dropzone's default inline style (padding, opacity, transition) rather than merging with it.UploadContainerProps(the internal props for the two looks) is not exported.