dotUI
dotUI
beta
  1. Components
  2. Drag and drop
  3. Dropzone

Dropzone

A drop zone is an area into which one or multiple objects can be dragged and dropped.

"use client";

import React from "react";
import { DropZone, DropZoneLabel } from "@/lib/components/core/default/drop-zone";
import { UploadIcon } from "@/lib/icons";

function DropZoneDemo() {
  return (
    <DropZone>
      <UploadIcon />
      <DropZoneLabel>Drag and drop files here</DropZoneLabel>
    </DropZone>
  );
}

Installation

Install the following dependencies:

npm install react-aria-components

Copy and paste the following code into your project.

"use client";

import * as React from "react";
import {
  DropZone as AriaDropZone,
  Text as AriaText,
  type DropZoneProps as AriaDropZoneProps,
  type TextProps as AriaTextProps,
} from "react-aria-components";
import { tv } from "tailwind-variants";

const dropZoneStyles = tv({
  slots: {
    root: "flex flex-col p-6 w-full items-center justify-center gap-2 rounded-md border-2 border-dashed text-sm drop-target:border-border-focus focus-visible:border-border-focus drop-target:bg-bg-accent-muted disabled:text-fg-disabled disabled:border-border-disabled",
    label: "font-semibold text-md",
  },
});

interface DropZoneProps extends Omit<AriaDropZoneProps, "className"> {
  className?: string;
}
const DropZone = ({ className, ...props }: DropZoneProps) => {
  const { root } = dropZoneStyles();
  return <AriaDropZone className={root({ className })} {...props} />;
};

type DropZoneLabelProps = Omit<AriaTextProps, "slot">;
const DropZoneLabel = ({ className, ...props }: DropZoneLabelProps) => {
  const { label } = dropZoneStyles();
  return <AriaText slot="label" className={label({ className })} {...props} />;
};

export { DropZone, DropZoneLabel };

Update the import paths to match your project setup.

Options

Label

A visual label can be provided for the DropZone using the DropZoneLabel component, or a hidden label using aria-label prop.

"use client";

import React from "react";
import { DropZone, DropZoneLabel } from "@/lib/components/core/default/drop-zone";
import { UploadIcon } from "@/lib/icons";

function DropZoneDemo() {
  return (
    <div className="w-full space-y-2">
      <DropZone aria-label="drag and drop files here">
        <UploadIcon />
      </DropZone>
      <DropZone>
        <UploadIcon />
        <DropZoneLabel>Drag and drop files here</DropZoneLabel>
      </DropZone>
    </div>
  );
}

Disabled

Use the isDisabled prop to disable the drop zone.

import React from "react";
import { DropZone, DropZoneLabel } from "@/lib/components/core/default/drop-zone";
import { UploadIcon } from "@/lib/icons";

function DropZoneDemo() {
  return (
    <DropZone isDisabled>
      <UploadIcon />
      <DropZoneLabel>Drag and drop files here</DropZoneLabel>
    </DropZone>
  );
}

Examples

File trigger

"use client";

import React from "react";
import { Button } from "@/lib/components/core/default/button";
import { DropZone, DropZoneLabel } from "@/lib/components/core/default/drop-zone";
import { FileTrigger } from "@/lib/components/core/default/file-trigger";
import { UploadIcon } from "@/lib/icons";

function DropZoneDemo() {
  return (
    <DropZone>
      <UploadIcon />
      <DropZoneLabel>Drag and drop files here</DropZoneLabel>
      <FileTrigger>
        <Button className="mt-2">Select files</Button>
      </FileTrigger>
    </DropZone>
  );
}

API Reference

PropTypeDefaultDescription
getDropOperation
(types: DragTypes, allowedOperations: DropOperation[]) => DropOperation
-
A function returning the drop operation to be performed when items matching the given types are dropped on the drop target.
isDisabled
boolean
-
Whether the drop target is disabled. If true, the drop target will not accept any drops.
children
ReactNode | (values: DropZoneRenderProps & {defaultChildren: ReactNode | undefined}) => ReactNode
-
The children of the component. A function may be provided to alter the children based on component state.
className
string
-
The CSS className for the element.
style
CSSProperties | (values: DropZoneRenderProps & {defaultStyle: CSSProperties}) => CSSProperties
-
The inline style for the element. A function may be provided to compute the style based on component state.
EventTypeDescription
onDropEnter
(e: DropEnterEvent) => void
Handler that is called when a valid drag enters the drop target.
onDropMove
(e: DropMoveEvent) => void
Handler that is called when a valid drag is moved within the drop target.
onDropExit
(e: DropExitEvent) => void
Handler that is called when a valid drag exits the drop target.
onDrop
(e: DropEvent) => void
Handler that is called when a valid drag is dropped on the drop target.
onHoverStart
(e: HoverEvent) => void
Handler that is called when a hover interaction starts.
onHoverEnd
(e: HoverEvent) => void
Handler that is called when a hover interaction ends.
onHoverChange
(isHovering: boolean) => void
Handler that is called when the hover state changes.
Data attributeDescription
[data-hovered]
Whether the dropzone is currently hovered with a mouse.
[data-focused]
Whether the dropzone is focused, either via a mouse or keyboard.
[data-focus-visible]
Whether the dropzone is keyboard focused.
[data-drop-target]
Whether the dropzone is the drop target.
[data-disabled]
Whether the dropzone is disabled.

Accessibilty

Keyboard interactions

KeyDescription
Tab
Moves focus to the dropzone.
Enter
Activates the dropzone.

Built by mehdibha. The source code is available on GitHub.