Vize

use-drop-zone

Test a file against accept-attribute style patterns.

Package @vizejs/composable/use-drop-zone
Own the source vize lib pull composable:use-drop-zone
Runtime exports matchesAccept, useDropZone
Gzip budget 2816 B

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/composable

Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.

import { matchesAccept, useDropZone } from "@vizejs/composable/use-drop-zone";

Try it

Accept dropped images

Turn an element into a drop target that filters file types.

Open the interactive example

What to observe: Drag image files onto the area: it highlights while files are over it and lists their names after the drop. Other file types are ignored.

accept takes MIME patterns or a function. Provide a file input as well for keyboard and screen-reader users.

Compare the initial and interacted states
Accept dropped images: initial state
Initial state
Accept dropped images: state after the verified interactions
After the verified interactions

Copy the example

Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.

<script setup lang="ts">
import { ref } from "vue";
import { useDropZone } from "@vizejs/composable/use-drop-zone";

const zone = ref<HTMLElement | null>(null);
const { isOverDropZone, files } = useDropZone(zone, { accept: ["image/*"], multiple: true });
</script>

<template>
  <div class="composable-example">
    <p>Accept images dropped onto an area and list them.</p>
    <div
      ref="zone"
      role="region"
      aria-label="Image drop area"
      :style="{
        border: '2px dashed',
        padding: '16px',
        background: isOverDropZone ? '#42b88333' : 'transparent',
      }"
    >
      {{ isOverDropZone ? "Release to add the images" : "Drop images here" }}
    </div>
    <output aria-live="polite">{{
      files?.length ? `Added: ${files.map((file) => file.name).join(", ")}` : "No images yet."
    }}</output>
  </div>
</template>

Runtime contract

Utility Category Stability SSR Hydration Cleanup Targets Host globals Uses
matchesAccept events experimental safe not-applicable none web, server, worker, native, desktop, terminal — —
useDropZone events experimental safe stable caller, reactive-scope web, desktop — matchesAccept, tryOnScopeDispose

API

matchesAccept

Test a file against accept-attribute style patterns. Supports exact MIME types, wildcard subtypes ("image/*"), extensions (".png", case-insensitive), and "*". An empty pattern list accepts everything. An empty name (the file is still being dragged) makes extension patterns match provisionally.

function matchesAccept(accept: readonly string[], file: DropZoneFileInfo): boolean

useDropZone

Headless drop-zone logic for any element. Tracks whether a drag is over the target (a nesting counter keeps dragleave from child elements from flickering the state), decides acceptance from the dragged MIME types while dragging, and filters the dropped files by accept (including extension patterns) and multiple. Rejected drags show the "none" drop effect. Rendering is entirely up to the caller. Listeners follow the reactive target and are removed when the owning reactive scope stops. Server rendering: no listener is attached; all state is empty/false.

function useDropZone( target: MaybeRefOrGetter<EventTarget | null | undefined>, options: UseDropZoneOptions = {}, ): DropZoneControls
const zone = useTemplateRef<HTMLElement>("zone");
const { isOverDropZone, files } = useDropZone(zone, { accept: ["image/*"] });

Types

DataTransferItemLike

One entry of DataTransfer.items.

Member Type Description
kind string "file" or "string".
type string MIME type of the item.

DataTransferLike

Minimal DataTransfer consumed by useDropZone.

Member Type Description
items? ArrayLike<DataTransferItemLike> Items being dragged; types are readable during the drag.
files ArrayLike<File> Dropped files; populated on drop.
dropEffect string Feedback shown to the user ("copy", "none", …).

DropZoneFileInfo

File name and MIME type used for acceptance checks.

Member Type Description
name string File name including extension. Empty while dragging.
type string MIME type, possibly empty for unknown types.

UseDropZoneOptions

Options for useDropZone.

Member Type Description
accept? MaybeRef<DropZoneAccept | undefined> Accepted files. Extension patterns can only be verified on drop because browsers hide file names while dragging. A ref rather than a getter, because a predicate is itself a function.
multiple? MaybeRefOrGetter<boolean> Accept more than one file per drop.
preventDefaultForUnhandled? boolean Call preventDefault even for rejected drags, so the browser never opens a rejected file dropped onto the zone.
onDrop? (files: readonly File[] | null, event: Event) => void Called with the accepted files (or null when none were accepted).
onEnter? (event: Event) => void Called when a drag enters the zone.
onLeave? (event: Event) => void Called when a drag leaves the zone (including its children).
onOver? (event: Event) => void Called for every dragover inside the zone.

DropZoneControls

Reactive state returned by useDropZone.

Member Type Description
isOverDropZone Readonly<Ref<boolean>> Whether a drag is currently over the zone (children included).
accepted Readonly<Ref<boolean>> Whether the current drag is acceptable.
files Readonly<ShallowRef<readonly File[] | null>> Files accepted by the most recent drop.