Skip to main content

Installation

npm install @kuzenbo/core

Usage

import { Dropzone } from "@kuzenbo/core";

function Example() {
  const handleDrop = (files: File[]) => {
    console.log("Accepted files:", files);
  };

  return (
    <Dropzone onDrop={handleDrop}>
      <div className="flex flex-col items-center justify-center gap-2 p-8">
        <Dropzone.Idle>
          <p className="text-sm text-muted-foreground">
            Drag files here or click to select
          </p>
        </Dropzone.Idle>
        <Dropzone.Accept>
          <p className="text-sm text-primary">Drop files here</p>
        </Dropzone.Accept>
        <Dropzone.Reject>
          <p className="text-sm text-danger">Invalid file type</p>
        </Dropzone.Reject>
      </div>
    </Dropzone>
  );
}

Props

onDrop
(files: FileWithPath[]) => void
required
Callback when valid files are dropped.
onReject
(fileRejections: FileRejection[]) => void
Callback when dropped files are rejected.
onDropAny
(files: FileWithPath[], rejections: FileRejection[]) => void
Callback when any files are dropped (both accepted and rejected).
accept
Accept | string[]
MIME types to accept. Can be object or array of MIME types.
multiple
boolean
default:"true"
Whether to allow multiple files.
maxSize
number
default:"Infinity"
Maximum file size in bytes.
maxFiles
number
Maximum number of files.
disabled
boolean
Whether the dropzone is disabled.
loading
boolean
Whether to display a loading overlay.
variant
'default' | 'filled' | 'light'
default:"'light'"
The visual style variant.
activateOnClick
boolean
default:"true"
Whether clicking opens the file picker.
activateOnDrag
boolean
default:"true"
Whether drag and drop is enabled.
activateOnKeyboard
boolean
default:"true"
Whether Space/Enter opens the file picker.
validator
(file: File) => FileError | FileError[] | null
Custom validation function.
enablePointerEvents
boolean
Whether to enable pointer events on inner content.

Advanced Patterns

Accept Specific Files

<Dropzone
  accept={["image/png", "image/jpeg", "image/gif"]}
  onDrop={handleDrop}
>
  {/* ... */}
</Dropzone>

File Size Limit

<Dropzone
  maxSize={5 * 1024 * 1024} // 5MB
  onDrop={handleDrop}
  onReject={(rejections) => {
    rejections.forEach((rejection) => {
      console.error(rejection.errors);
    });
  }}
>
  {/* ... */}
</Dropzone>

Loading State

const [loading, setLoading] = useState(false);

const handleDrop = async (files: File[]) => {
  setLoading(true);
  await uploadFiles(files);
  setLoading(false);
};

<Dropzone loading={loading} onDrop={handleDrop}>
  {/* ... */}
</Dropzone>

Custom Validation

<Dropzone
  validator={(file) => {
    if (file.name.includes("invalid")) {
      return {
        code: "invalid-name",
        message: "File name cannot contain 'invalid'"
      };
    }
    return null;
  }}
  onDrop={handleDrop}
>
  {/* ... */}
</Dropzone>

Variants

{/* Filled variant */}
<Dropzone variant="filled" onDrop={handleDrop}>
  {/* ... */}
</Dropzone>

{/* Light variant (default) */}
<Dropzone variant="light" onDrop={handleDrop}>
  {/* ... */}
</Dropzone>

Build docs developers (and LLMs) love