Click, drag, or paste target for files with consumer-owned validation. Defaults to images. Use the tile variant for compact square or circle add and replace controls such as profile photos.
Also known as: file uploader, file upload, image upload, image dropzone, image paste target, photo dropzone, dropzone, profile picture upload, avatar upload, add photo
Install with the CLI, or copy the component source into your project.
Click, drag, or paste an image into the uploader.
Solid border, token-backed colors, custom icon, and copy.
Compact add control and a circular replace control with preview.
Circular tiles in sm, md, lg, and xl.
Click, drag, or paste upload target. Defaults to images; pass pickFile for other media. Validation and copy stay with the consumer. Use variant tile for compact add or replace controls such as profile photos. Idle chrome is tokenized via --df-file-uploader-*.
| Prop | Type | Default | Notes |
|---|---|---|---|
| onFile | (file: File) => void | - | Called when a file passes validation (required). |
| validateFile | (file: File) => string | null | - | Return an error message to reject the file, or null to accept. |
| onReject | (message: string) => void | - | Called with the rejection message from validateFile. |
| accept | string | image/png,image/jpeg,image/webp,image/gif | File input accept attribute. |
| pickFile | (files: FileList | null | undefined) => File | undefined | - | Choose a candidate from a drop or browse list. Defaults to the first image file. |
| enablePaste | boolean | true | Listen for image paste on the window while mounted. |
| disabled | boolean | false | Disable interaction and paste handling. |
| variant | "default" | "tile" | "default" | default is a full-width drop target. tile is a fixed square or circle control for add and replace flows such as profile photos. |
| shape | "rounded" | "circle" | "rounded" | Tile corner shape. rounded uses radius-lg. circle uses a full pill radius. Ignored on default. |
| size | "sm" | "md" | "lg" | "xl" | "md" | Tile edge length. Maps to --df-file-uploader-tile-size-*. Ignored on default. Override with --df-file-uploader-tile-size for a custom length. |
| cornerShape | "round" | "smooth" | - | Instance corner curve. Omit to inherit --df-corner-shape from the theme (set at create/init). |
| title | ReactNode | "Drop an image here" (default) or "Add" (tile) | Primary heading inside the uploader. |
| description | ReactNode | "or click to browse. Paste also works." (default) or hidden (tile) | Secondary line under the title. Pass null or an empty value to hide it. |
| hint | ReactNode | - | Optional tertiary hint (formats, size limits). |
| icon | ReactNode | - | Leading icon. Defaults to ImagePlus. Pass a custom node to replace it. |
| previewSrc | string | - | Image URL for a filled replace state. Covers the shell and hides the idle icon and copy. Host manages object URL lifecycle. |
| borderStyle | "dashed" | "solid" | "dashed" | Idle border style. Sets --df-file-uploader-border-style. |
| borderColor | string | - | Idle border color. Prefer tokens such as var(--border). Sets --df-file-uploader-border-color. |
| background | string | - | Idle fill. Prefer tokens such as var(--muted) or transparent. Sets --df-file-uploader-bg. |
| className | string | - | Additional styles on the uploader shell. |
| Prop | Type | Default | Notes |
|---|---|---|---|
| Browse dialog | behavior | - | After the native file dialog closes (file chosen or cancelled), focus leaves the file input when it is still the active element. Host shortcuts such as Space are not kept on the uploader. |
Theme defaults live on :root. Override these globally or on a local host.
| Token | Type | Default | Notes |
|---|---|---|---|
| --df-file-uploader-min-height | CSS length | calc(30 * var(--spacing-unit)) | Minimum height for the default variant. |
| --df-file-uploader-border-style | CSS border-style | dashed | Idle border style. |
| --df-file-uploader-border-color | CSS color | var(--border) | Idle border color. |
| --df-file-uploader-bg | CSS color | color-mix(in oklch, var(--muted) 40%, transparent) | Idle fill. |
| --df-file-uploader-border-color-hover | CSS color | color-mix(in oklch, var(--primary) 40%, transparent) | Border color on hover. |
| --df-file-uploader-bg-hover | CSS color | color-mix(in oklch, var(--muted) 60%, transparent) | Fill on hover. |
| --df-file-uploader-border-color-active | CSS color | var(--primary) | Border color while dragging a file over the uploader. |
| --df-file-uploader-bg-active | CSS color | color-mix(in oklch, var(--primary) 5%, transparent) | Fill while dragging a file over the uploader. |
| --df-file-uploader-tile-size | CSS length | var(--df-file-uploader-tile-size-md) | Resolved tile edge length. Override for a custom tile size. |
| --df-file-uploader-tile-size-sm | CSS length | calc(16 * var(--spacing-unit)) | Tile size sm. |
| --df-file-uploader-tile-size-md | CSS length | calc(22 * var(--spacing-unit)) | Tile size md. |
| --df-file-uploader-tile-size-lg | CSS length | calc(28 * var(--spacing-unit)) | Tile size lg. |
| --df-file-uploader-tile-size-xl | CSS length | calc(36 * var(--spacing-unit)) | Tile size xl. |
| --df-file-uploader-tile-radius | CSS length | var(--radius-lg) | Tile corner radius. Circle shape sets this to radius-full. |
| --radius-lg | CSS length | - | Default and rounded-tile corner radius. |
| --radius-full | CSS length | - | Circle tile corner radius. |
| --df-corner-shape | CSS corner-shape | var(--df-corner-shape-round) | Theme corner curve for all kit chrome. round = circular arcs; smooth = continuous squircle. Set with df-ui init --corner-shape, or override on :root. Default round. |