third party plugins
Tailwind CSS File Upload
File Upload enhances web forms with a Tailwind CSS-compatible interface, featuring drag-and-drop, previews, progress bars, and simultaneous multiple uploads. It supports automatic or manual submission and validates file types and sizes.
Below are the comprehensively outlined steps you can follow to seamlessly integrate Dropzone JS with FlyonUI.
- 1Step 1: Installation
Install
Dropzone
andlodash
using npm. Certain JavaScript helpers for Dropzone require the lodash plugin, so make sure to install it as well.npm i dropzone lodash
- 2Step 2: Include Dropzone and Lodash JavaScript and CSS
Include the necessary CSS and JavaScript files in your project at the specified locations:
<head> <link rel="stylesheet" href="../path/to/dropzone/dist/dropzone.css" /> </head> <body> <script src="../path/to/lodash/lodash.js"></script> <script src="../path/to/dropzone/dist/dropzone-min.js"></script> </body>
Since no custom CSS overrides are required, you can also use a CDN link.Insert the following JavaScript and CSS CDN links into their respective sections:
<head> <link rel="stylesheet" href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" type="text/css" /> </head> <body> <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script> <script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script> </body>
Class Name | Type | Description |
---|---|---|
file-upload-complete:{tw-utility-class} | Modifier | A modifier that allows you to set Tailwind classes to items that successfully uploaded. |
Using the most basic file upload markup, here’s how file upload look.
Use <template>
to style your file upload output. The following example demonstrates the default template layout.
Pick a file up to 2MB.
<div
data-file-upload='{
"url": "/upload",
"extensions": {
"csv": {
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4\"/><path d=\"M14 2v4a2 2 0 0 0 2 2h4\"/><path d=\"m5 12-3 3 3 3\"/><path d=\"m9 18 3-3-3-3\"/></svg>",
"class": "shrink-0 size-5"
}
}
}' >
<div class="border-base-content/20 bg-base-100 rounded-box flex cursor-pointer justify-center border border-dashed p-12" data-file-upload-trigger="" >
<div class="text-center">
<span class="bg-base-200/80 text-base-content/90 inline-flex size-16 items-center justify-center rounded-full">
<span class="icon-[tabler--upload] size-6 shrink-0"></span>
</span>
<div class="mt-4 flex flex-wrap justify-center">
<span class="text-base-content/90 pe-1 text-base font-medium">Drop your file here or</span>
<span class="link link-animated link-primary font-semibold">browse</span>
</div>
<p class="text-base-content/50 mt-1 text-xs">Pick a file up to 2MB.</p>
</div>
</div>
<div class="mt-4 space-y-2 empty:mt-0" data-file-upload-previews=""></div>
</div>
The system will throw an error if the file size exceeds 1 MB.
.
File exceeds size limit.
Pick a file up to 2MB.
<div
id="file-upload-limit"
data-file-upload='{
"url": "/upload",
"maxFilesize": 1,
"extensions": {
"csv": {
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4\"/><path d=\"M14 2v4a2 2 0 0 0 2 2h4\"/><path d=\"m5 12-3 3 3 3\"/><path d=\"m9 18 3-3-3-3\"/></svg>",
"class": "shrink-0 size-5"
}
}
}' >
<template data-file-upload-preview="">
<div class="rounded-box bg-base-100 p-4 shadow-lg">
<div class="mb-1 flex items-center justify-between">
<div class="flex items-center gap-x-3">
<span class="text-base-content/80 border-base-content/20 flex size-8 items-center justify-center rounded-lg border p-0.5" data-file-upload-file-icon="" >
<img class="hidden rounded-md" data-dz-thumbnail="" />
</span>
<div>
<p class="text-base-content/90 text-sm font-medium">
<span class="inline-block truncate align-bottom" data-file-upload-file-name=""></span>
.
<span data-file-upload-file-ext=""></span>
</p>
<p class="text-base-content/50 text-xs" data-file-upload-file-size=""></p>
<p class="text-error text-xs" style="display: none" data-file-upload-file-error="">
File exceeds size limit.
</p>
</div>
</div>
<div class="flex items-center">
<div class="tooltip [--placement:top]" style="display: none" data-file-upload-file-error="">
<button type="button" class="tooltip-toggle btn btn-sm btn-circle btn-text btn-error">
<span class="icon-[tabler--alert-circle] size-4 shrink-0"></span>
</button>
<span class="tooltip-content tooltip-shown:opacity-100 tooltip-shown:visible" role="tooltip">
<span class="tooltip-body">Please try to upload a file smaller than 1MB.</span>
</span>
</div>
<button type="button" class="btn btn-sm btn-circle btn-text" data-file-upload-reload="">
<span class="icon-[tabler--refresh] size-4 shrink-0"></span>
</button>
<button type="button" class="btn btn-sm btn-circle btn-text" data-file-upload-remove="">
<span class="icon-[tabler--trash] size-4 shrink-0"></span>
</button>
</div>
</div>
<div class="flex items-center gap-x-3 whitespace-nowrap">
<div class="progress h-2" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" data-file-upload-progress-bar="" >
<div class="progress-bar progress-primary file-upload-complete:progress-success transition-all duration-500" style="width: 0" data-file-upload-progress-bar-pane="" ></div>
</div>
<span class="text-base-content/90 mb-0.5 text-sm">
<span data-file-upload-progress-bar-value="">0</span>%
</span>
</div>
</div>
</template>
<div class="border-base-content/20 bg-base-100 rounded-box flex cursor-pointer justify-center border border-dashed p-12" data-file-upload-trigger="" >
<div class="text-center">
<span class="bg-base-200/80 text-base-content/90 inline-flex size-16 items-center justify-center rounded-full">
<span class="icon-[tabler--upload] size-6 shrink-0"></span>
</span>
<div class="mt-4 flex flex-wrap justify-center">
<span class="text-base-content/90 pe-1 text-base font-medium">Drop your file here or</span>
<span class="link link-animated link-primary font-semibold">browse</span>
</div>
<p class="text-base-content/50 mt-1 text-xs">Pick a file up to 2MB.</p>
</div>
</div>
<div class="mt-4 space-y-2 empty:mt-0" data-file-upload-previews=""></div>
</div>
Using file upload as a gallery.
Pick a file up to 2MB.
<div
data-file-upload='{
"url": "/upload",
"acceptedFiles": "image/*",
"autoHideTrigger": false,
"extensions": {
"csv": {
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4\"/><path d=\"M14 2v4a2 2 0 0 0 2 2h4\"/><path d=\"m5 12-3 3 3 3\"/><path d=\"m9 18 3-3-3-3\"/></svg>",
"class": "shrink-0 size-5"
}
}
}' >
<template data-file-upload-preview="">
<div class="relative mt-2 rounded-box shadow-md bg-base-100 p-2" >
<img class="mb-2 w-full rounded-lg object-cover" data-dz-thumbnail="" />
<div class="mb-1 flex items-center justify-between gap-x-3 whitespace-nowrap">
<div class="w-10">
<span class="text-base-content/90 mb-0.5 text-sm">
<span data-file-upload-progress-bar-value="">0</span>%</span>
</div>
<div class="flex items-center gap-x-2">
<button type="button" class="btn btn-sm btn-circle btn-text" data-file-upload-remove="">
<span class="icon-[tabler--trash] size-4 shrink-0"></span>
</button>
</div>
</div>
<div class="progress h-2" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" data-file-upload-progress-bar="" >
<div class="progress-bar progress-primary file-upload-complete:progress-success transition-all duration-500" style="width: 0" data-file-upload-progress-bar-pane="" ></div>
</div>
</div>
</template>
<div class="border-base-content/20 bg-base-100 rounded-box flex cursor-pointer justify-center border border-dashed p-12" data-file-upload-trigger="" >
<div class="text-center">
<span class="bg-base-200/80 text-base-content/90 inline-flex size-16 items-center justify-center rounded-full">
<span class="icon-[tabler--upload] size-6 shrink-0"></span>
</span>
<div class="mt-4 flex flex-wrap justify-center">
<span class="text-base-content/90 pe-1 text-base font-medium">Drop your file here or</span>
<span class="link link-animated link-primary font-semibold">browse</span>
</div>
<p class="text-base-content/50 mt-1 text-xs">Pick a file up to 2MB.</p>
</div>
</div>
<div class="grid grid-cols-4 gap-2 empty:gap-0 max-sm:grid-cols-2" data-file-upload-previews=""></div>
</div>
Use file upload for a single image.
<div
data-file-upload='{
"url": "/upload",
"acceptedFiles": "image/*",
"maxFiles": 1,
"singleton": true
}' >
<template data-file-upload-preview="">
<div class="size-20">
<img class="w-full rounded-full object-contain" data-dz-thumbnail="" />
</div>
</template>
<div class="flex flex-wrap items-center gap-3 sm:gap-5">
<div class="group" data-file-upload-previews="" data-file-upload-pseudo-trigger="">
<span class="border-base-content/30 text-base-content/50 flex size-20 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-dotted hover:bg-base-200/60 group-has-[div]:hidden" >
<span class="icon-[tabler--user-circle] size-9 shrink-0"></span>
</span>
</div>
<div class="grow">
<div class="flex items-center gap-x-2">
<button type="button" class="btn btn-primary" data-file-upload-trigger="">
<span class="icon-[tabler--upload] size-4 shrink-0"></span>
Upload photo
</button>
<button type="button" class="btn btn-outline btn-secondary" data-file-upload-clear="">Delete</button>
</div>
</div>
</div>
</div>
Using file upload as a simple file upload.
<div
data-file-upload='{
"url": "/upload",
"maxFiles": 1,
"singleton": true
}'
>
<template data-file-upload-preview="">
<div class="flex w-full items-center">
<span class="grow-0 overflow-hidden truncate" data-file-upload-file-name=""></span>
<span class="grow-0">.</span>
<span class="grow-0" data-file-upload-file-ext=""></span>
</div>
</template>
<button type="button" class="relative flex w-full overflow-hidden rounded-lg border border-base-content/20 text-sm focus:z-10 focus:ring-1 focus:border-primary focus:ring-primary focus:outline-none disabled:pointer-events-none disabled:opacity-50" >
<span class="h-full text-nowrap bg-base-200 rounded-s-lg px-4 py-3">Choose File</span>
<span class="group flex h-full grow overflow-hidden px-4 py-3 text-base-content/90" data-file-upload-previews="">
<span class="group-has-[div]:hidden">No Chosen File</span>
</span>
<span class="absolute left-0 top-0 h-full w-full" data-file-upload-trigger=""></span>
</button>
</div>
Please understand that this component requires the Dropzone.js plugin. Most of the plugin’s options are also available in our wrapper.
PARAMETERS | DESCRIPTION | OPTIONS | DEFAULT VALUE |
---|---|---|---|
data-file-upload | Activate a File Upload by specifying on an element. | - | - |
:extensions | A list of extensions and their corresponding icons will be added to the container with the data-file-upload-file-icon selector if they match the extension name. | object | Includes markup. See the code. |
:autoHideTrigger | If the attribute value is true , then data-file-upload-trigger will disappear if at least one item is added to the upload and will appear if more than one item is not in the upload. | boolean | false |
:singleton | If the attribute value is true , the plugin will remove any previously uploaded files. This is necessary to emulate the behavior of a simple file input. | boolean | false |
Name | Description |
---|---|
data-file-upload-trigger | Specifies which element within the initialized container will serve as the clickable element. |
data-file-upload-previews | Specifies which element within the initialized container will act as a wrapper for uploaded items. |
data-file-upload-clear | Specifies which element within the initialized container will serve as the button to delete all files. |
data-file-upload-preview | Specifies which element within the initialized container will act as a template for the uploading item. This should be an HTML template element. |
data-file-upload-file-icon | Specifies which element within the uploading item will act as a wrapper for the file icon defined in the extensions property. |
data-file-upload-file-name | Specifies which element within the uploading item will act as a wrapper for the file name. |
data-file-upload-file-ext | Specifies which element within the uploading item will act as a wrapper for the file extension. |
data-file-upload-file-size | Specifies which element within the uploading item will act as a wrapper for the file size. |
data-file-upload-remove | Specifies which element within the uploading item will act as the remove button. |
data-file-upload-reload | Specifies which element within the uploading item will act as the re-upload button. |
data-file-upload-progress-bar | Specifies which element within the uploading item will act as the progress bar. |
data-file-upload-progress-bar-pane | Specifies which element within the uploading item will act as the progress bar pane, whose width will dynamically increase during the upload process. |
data-file-upload-progress-bar-value | Specifies which element within the uploading item will display the current progress value, which will dynamically increase during the upload process. |
Please note that this component requires the Dropzone.js plugin. Most events available in the plugin are available in our wrapper.
Example of an event triggered when an item is successfully uploaded to the server.
const { element } = HSFileUpload.getInstance('#file-upload', true);
const { dropzone } = element;
dropzone.on('complete', () => {
console.log('Item uploaded!');
});