Skip to content

Dropzone

Headless component for Drag'n'Drop Files Upload.

Usage

Upload Document

preview
vue
<template>
  <p-dropzone accept="application/pdf">
    <template #default="{ isDragover, isHovered, model, browse }">
      <div class="flex flex-col items-center justify-center w-full p-5 space-y-3 border-2 border-dashed rounded "
        :class="[isDragover ? 'bg-info dark:bg-dark-info border-info-emphasis dark:border-dark-info-emphasis' : 'bg-default dark:bg-dark-default border-default dark:border-dark-default']">
        <p-spread :active="isDragover || isHovered">
          <IconFile class="w-16 h-16 mt-5 fill-info-emphasis dark:fill-dark-info-emphasis" />
        </p-spread>
        <p-heading element="h5">
          Upload Document
        </p-heading>
        <p-heading element="h6">
          <template v-if="!model">
            Drag your document here or click
            <a href="#" @click.prevent="browse">Browse</a>
          </template>
          <template v-else>
            {{ model.name }}
          </template>
        </p-heading>
        <p-caption weight="bold">PDF, DOC & DOCX up to 25MB each</p-caption>
        <p-caption>10 documents max for multiple upload</p-caption>
        <p-caption class="mt-16 text-sm">PDF file format is recommended for a faster uploading process.</p-caption>
      </div>
    </template>
  </p-dropzone>
</template>

Add Photo

preview
vue
<template>
  <p-dropzone accept="image/*">
    <template #default="{ isDragover, isHovered, model, browse }">
      <div class="flex flex-col items-center justify-center w-full p-5 space-y-3 border-2 border-dashed rounded "
        :class="[isDragover ? 'bg-info dark:bg-dark-info border-info-emphasis dark:border-dark-info-emphasis' : 'bg-default dark:bg-dark-default border-default dark:border-dark-default']">
        <p-spread :active="isDragover || isHovered">
          <IconImage class="w-16 h-16 mt-5 fill-info-emphasis dark:fill-dark-info-emphasis" />
        </p-spread>
        <p-heading element="h5">
          Add Photo
        </p-heading>
        <p-heading element="h6">
          <template v-if="!model">
            Drag your document here or click
            <a href="#" @click.prevent="browse">Browse</a>
          </template>
          <template v-else>
            {{ model.name }}
          </template>
        </p-heading>
        <p-caption weight="bold">JPG & PNG up to 5MB</p-caption>
      </div>
    </template>
  </p-dropzone>
</template>

Multiple upload

Add prop multiple to enable multi-selected upload.

preview
vue
<template>
  <p-dropzone accept="image/*" multiple maxlength="5">
    <template #default="{ isDragover, isHovered, model, browse }">
      <div class="flex flex-col items-center justify-center w-full p-5 space-y-3 border-2 border-dashed rounded "
        :class="[isDragover ? 'bg-info dark:bg-dark-info border-info-emphasis dark:border-dark-info-emphasis' : 'bg-default dark:bg-dark-default border-default dark:border-dark-default']">
        <p-spread :active="isDragover || isHovered">
          <IconImage class="w-16 h-16 mt-5 fill-info-emphasis dark:fill-dark-info-emphasis" />
        </p-spread>
        <p-heading element="h5">
          Add Photo
        </p-heading>
        <p-heading element="h6">
          <template v-if="!model">
            Drag your document here or click
            <a href="#" @click.prevent="browse">Browse</a>
          </template>
          <template v-else>
            <ol>
              <li v-for="file in model">
                {{ file.name }}
              </li>
            </ol>
          </template>
        </p-heading>
        <p-caption weight="bold">JPG & PNG up to 5MB</p-caption>
      </div>
    </template>
  </p-dropzone>
</template>

Appending values

When user selecting the files, and then selecting again, the old list of files is replaced with new ones. Set multiple prop to 'append' if you want to keep the last ones.

preview
vue
<template>
  <p-dropzone accept="image/*" multiple="append" maxlength="10">
    <template #default="{ isDragover, isHovered, model, browse }">
      <div class="flex flex-col items-center justify-center w-full p-5 space-y-3 border-2 border-dashed rounded "
        :class="[isDragover ? 'bg-info dark:bg-dark-info border-info-emphasis dark:border-dark-info-emphasis' : 'bg-default dark:bg-dark-default border-default dark:border-dark-default']">
        <p-spread :active="isDragover || isHovered">
          <IconImage class="w-16 h-16 mt-5 fill-info-emphasis dark:fill-dark-info-emphasis" />
        </p-spread>
        <p-heading element="h5">
          Add Photo
        </p-heading>
        <p-heading element="h6">
          <template v-if="!model">
            Drag your document here or click
            <a href="#" @click.prevent="browse">Browse</a>
          </template>
          <template v-else>
            <ol>
              <li v-for="file in model">
                {{ file.name }}
              </li>
            </ol>
          </template>
        </p-heading>
        <p-caption weight="bold">JPG & PNG up to 5MB</p-caption>
      </div>
    </template>
  </p-dropzone>
</template>

Binding v-model

preview

result:

vue
<template class="flex-col items-stretch">
  <p-dropzone accept="image/*" v-model="result">
    <template #default="{ isDragover, isHovered, model, browse }">
      <div class="flex flex-col items-center justify-center w-full p-5 space-y-3 border-2 border-dashed rounded "
        :class="[isDragover ? 'bg-info dark:bg-dark-info border-info-emphasis dark:border-dark-info-emphasis' : 'bg-default dark:bg-dark-default border-default dark:border-dark-default']">
        <p-spread :active="isDragover || isHovered">
          <IconImage class="w-16 h-16 mt-5 fill-info-emphasis dark:fill-dark-info-emphasis" />
        </p-spread>
        <p-heading element="h5">
          Add Photo
        </p-heading>
        <p-heading element="h6">
          <template v-if="!model">
            Drag your document here or click
            <a href="#" @click.prevent="browse">Browse</a>
          </template>
          <template v-else>
            {{ model.name }}
          </template>
        </p-heading>
        <p-caption weight="bold">JPG & PNG up to 5MB</p-caption>
      </div>
    </template>
  </p-dropzone>
</template>

Encode to base64

By default, this component keep v-model value as File object. If you need base64-dataURI format, you can add modifier base64 to your v-model.

preview

result:

vue
<template>
  <p-dropzone accept="image/*" v-model.base64="result">
    <template #default="{ isDragover, isHovered, rawModel, browse }">
      <div class="flex flex-col items-center justify-center w-full p-5 space-y-3 border-2 border-dashed rounded "
        :class="[isDragover ? 'bg-info dark:bg-dark-info border-info-emphasis dark:border-dark-info-emphasis' : 'bg-default dark:bg-dark-default border-default dark:border-dark-default']">
        <p-spread :active="isDragover || isHovered">
          <IconImage class="w-16 h-16 mt-5 fill-info-emphasis dark:fill-dark-info-emphasis" />
        </p-spread>
        <p-heading element="h5">
          Add Photo
        </p-heading>
        <p-heading element="h6">
          <template v-if="!rawModel">
            Drag your document here or click
            <a href="#" @click.prevent="browse">Browse</a>
          </template>
          <template v-else>
            {{ rawModel.name }}
          </template>
        </p-heading>
        <p-caption weight="bold">JPG & PNG up to 5MB</p-caption>
      </div>
    </template>
  </p-dropzone>
</template>

Clear on cancel

By default, if you browse the file and cancel it, this component keep the last selected file as value for v-model. If you want reset the value when canceling, use clearOnCancel prop to reset the value.

preview
vue
<template>
  <p-dropzone accept="image/*" v-model.base64="result2" clear-on-cancel>
    <template #default="{ isDragover, isHovered, rawModel, browse }">
      <div class="flex flex-col items-center justify-center w-full p-5 space-y-3 border-2 border-dashed rounded "
        :class="[isDragover ? 'bg-info dark:bg-dark-info border-info-emphasis dark:border-dark-info-emphasis' : 'bg-default dark:bg-dark-default border-default dark:border-dark-default']">
        <p-spread :active="isDragover || isHovered">
          <IconImage class="w-16 h-16 mt-5 fill-info-emphasis dark:fill-dark-info-emphasis" />
        </p-spread>
        <p-heading element="h5">
          Add Photo
        </p-heading>
        <p-heading element="h6">
          <template v-if="!rawModel">
            Drag your document here or click
            <a href="#" @click.prevent="browse">Browse</a>
          </template>
          <template v-else>
            {{ rawModel.name }}
          </template>
        </p-heading>
        <p-caption bold>JPG & PNG up to 5MB</p-caption>
      </div>
    </template>
  </p-dropzone>
</template>

API

Props

PropsTypeDefaultDescription
multipleBoolean, StringfalseEnable multiple mode, set to append to appening values
maxlengthNumber-Maxlength selected files, only work on multiple mode
acceptString-Limitting file type can be selected, see HTML attribute: accept
clearOnCanelBooleanfalseClear v-model when user cancel the browse file
modelValueFile-v-model value

Slots

NameDescription
defaultContent to place for dropzone

Events

NameArgumentsDescription
changeFilesEvent when value changed
cancel-Event when user cancel selecting file

See Also

Released under the MIT License.