EdgeStore

Dropzone

The drop area and the useUploadDropzone hook that the other upload components are built on.

dropzone.tsx exports:

  • Dropzone: a drop area that adds files to the nearest UploaderProvider.
  • useUploadDropzone: react-dropzone's useDropzone, connected to the UploaderProvider. It enforces maxFiles across drops, adds what fits, and returns readable messages about skipped files.
  • DropzonePrompt, DropzoneOverlay and UploadErrors: the building blocks for the empty state, the drag overlay and the error notice.
  • dropzoneVariants and dropzoneState: the classes for a drop area and the data attributes that drive its drag styles.

If you are installing the other upload components via the CLI, this component will be installed automatically. You can skip the following steps.

Installation

Use the shadcn CLI to add the component to your project.

npx shadcn@latest add https://edgestore.dev/r/dropzone.json

Usage

Install or copy the component from Installation before using this example.

'use client';

import { Dropzone } from '@/components/upload/dropzone';
import {
  UploaderProvider,
  type UploadFn,
} from '@/components/upload/uploader-provider';
import { useEdgeStore } from '@/lib/edgestore';
import * as React from 'react';

export function DropzoneUsage() {
  const { edgestore } = useEdgeStore();

  const uploadFn: UploadFn = React.useCallback(
    async ({ file, onProgressChange, signal }) => {
      const res = await edgestore.publicFiles.upload({
        file,
        signal,
        onProgressChange,
      });
      // you can run some server action or api here
      // to add the necessary data to your database
      console.log(res);
      return res;
    },
    [edgestore],
  );

  return (
    <UploaderProvider uploadFn={uploadFn} autoUpload>
      <Dropzone
        dropzoneOptions={{
          maxFiles: 5,
          maxSize: 1024 * 1024 * 2, // 2MB
          accept: {
            'image/*': ['.jpeg', '.jpg', '.png'],
          },
          typesLabel: 'JPG or PNG',
        }}
      />
      {/* You can create a component that uses the provider context */}
      {/* (from the `useUploader` hook) to show a custom file list here */}
    </UploaderProvider>
  );
}

Custom dropzones

Use useUploadDropzone to build your own drop area. Spread dropzoneState() on the root element so the data-dragging, data-rejected and data-disabled attributes drive the styles in dropzoneVariants:

import {
  dropzoneState,
  dropzoneVariants,
  UploadErrors,
  useUploadDropzone,
} from '@/components/upload/dropzone';

function MyDropzone() {
  const { getRootProps, getInputProps, isDragActive, isDragReject, errors } =
    useUploadDropzone({ maxFiles: 3, maxSize: 1024 * 1024 });

  return (
    <>
      <div
        {...getRootProps({ className: dropzoneVariants })}
        {...dropzoneState({ isDragActive, isDragReject })}
      >
        <input {...getInputProps()} />
        <p>Drop files here</p>
      </div>
      <UploadErrors errors={errors} />
    </>
  );
}

upload-utils.ts has the helpers the components share: formatFileSize, accept presets (IMAGE_ACCEPT, DOCUMENT_ACCEPT, SPREADSHEET_ACCEPT), the minImageSize validator and the useObjectUrl preview hook.

On this page