Published on

Learn How To Build A Drag&Drop, Sortable, Dropzone File Upload With Tailwind CSS from the Pros

Drag&Drop, Sortable, Dropzone File Upload

Are you looking for a way to create a Drag&Drop, Sortable, Dropzone File Upload UI component for your web application? Look no further because we have got you covered! In this article, we will show you how to build a Drag&Drop, Sortable, Dropzone File Upload UI component with Tailwind CSS.

What is Tailwind CSS?

Tailwind CSS is a utility-first CSS framework that provides a set of pre-defined classes that can be used to style your HTML elements. With Tailwind CSS, you can create beautiful and responsive UI components without writing any custom CSS code. Tailwind CSS is gaining popularity among developers due to its simplicity and ease of use.

The description of Drag&Drop, Sortable, Dropzone File Upload UI component

A Drag&Drop, Sortable, Dropzone File Upload UI component allows users to upload files by dragging and dropping them onto a designated area on the web page. The component also allows users to sort the uploaded files and delete them if necessary. This UI component is commonly used in web applications that require users to upload files.

Why use Tailwind CSS to create a Drag&Drop, Sortable, Dropzone File Upload UI component?

Tailwind CSS provides a set of pre-defined classes that can be used to style the Drag&Drop, Sortable, Dropzone File Upload UI component. This makes it easy to create a beautiful and responsive UI component without writing any custom CSS code. Tailwind CSS also provides a set of utility classes that can be used to create animations and transitions, which can enhance the user experience of the Drag&Drop, Sortable, Dropzone File Upload UI component.

The preview of Drag&Drop, Sortable, Dropzone File Upload UI component

To give you an idea of what the Drag&Drop, Sortable, Dropzone File Upload UI component will look like, here is a preview:

Free download of the Drag&Drop, Sortable, Dropzone File Upload's source code

The source code of Drag&Drop, Sortable, Dropzone File Upload UI component

Here is the source code for the Drag&Drop, Sortable, Dropzone File Upload UI component:

<div class="bg-white p7 rounded w-9/12 mx-auto">
<div x-data="dataFileDnD()" class="relative flex flex-col p-4 text-gray-400 border border-gray-200 rounded">
    <div x-ref="dnd"
        class="relative flex flex-col text-gray-400 border border-gray-200 border-dashed rounded cursor-pointer">
        <input accept="*" type="file" multiple
            class="absolute inset-0 z-50 w-full h-full p-0 m-0 outline-none opacity-0 cursor-pointer"
            @change="addFiles($event)"
            @dragover="$refs.dnd.classList.add('border-blue-400'); $refs.dnd.classList.add('ring-4'); $refs.dnd.classList.add('ring-inset');"
            @dragleave="$refs.dnd.classList.remove('border-blue-400'); $refs.dnd.classList.remove('ring-4'); $refs.dnd.classList.remove('ring-inset');"
            @drop="$refs.dnd.classList.remove('border-blue-400'); $refs.dnd.classList.remove('ring-4'); $refs.dnd.classList.remove('ring-inset');"
            title="" />

        <div class="flex flex-col items-center justify-center py-10 text-center">
            <svg class="w-6 h-6 mr-1 text-current-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
                stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                    d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
            </svg>
            <p class="m-0">Drag your files here or click in this area.</p>
        </div>
    </div>

    <template x-if="files.length > 0">
        <div class="grid grid-cols-2 gap-4 mt-4 md:grid-cols-6" @drop.prevent="drop($event)"
            @dragover.prevent="$event.dataTransfer.dropEffect = 'move'">
            <template x-for="(_, index) in Array.from({ length: files.length })">
                <div class="relative flex flex-col items-center overflow-hidden text-center bg-gray-100 border rounded cursor-move select-none"
                    style="padding-top: 100%;" @dragstart="dragstart($event)" @dragend="fileDragging = null"
                    :class="{'border-blue-600': fileDragging == index}" draggable="true" :data-index="index">
                    <button class="absolute top-0 right-0 z-50 p-1 bg-white rounded-bl focus:outline-none" type="button" @click="remove(index)">
                        <svg class="w-4 h-4 text-gray-700" xmlns="http://www.w3.org/2000/svg" fill="none"
                            viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                        </svg>
                    </button>
                    <template x-if="files[index].type.includes('audio/')">
                        <svg class="absolute w-12 h-12 text-gray-400 transform top-1/2 -translate-y-2/3"
                            xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3" />
                        </svg>
                    </template>
                    <template x-if="files[index].type.includes('application/') || files[index].type === ''">
                        <svg class="absolute w-12 h-12 text-gray-400 transform top-1/2 -translate-y-2/3"
                            xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
                        </svg>
                    </template>
                    <template x-if="files[index].type.includes('image/')">
                        <img class="absolute inset-0 z-0 object-cover w-full h-full border-4 border-white preview"
                            x-bind:src="loadFile(files[index])" />
                    </template>
                    <template x-if="files[index].type.includes('video/')">
                        <video
                            class="absolute inset-0 object-cover w-full h-full border-4 border-white pointer-events-none preview">
                            <fileDragging x-bind:src="loadFile(files[index])" type="video/mp4">
                        </video>
                    </template>

                    <div class="absolute bottom-0 left-0 right-0 flex flex-col p-2 text-xs bg-white bg-opacity-50">
                        <span class="w-full font-bold text-gray-900 truncate"
                            x-text="files[index].name">Loading</span>
                        <span class="text-xs text-gray-900" x-text="humanFileSize(files[index].size)">...</span>
                    </div>

                    <div class="absolute inset-0 z-40 transition-colors duration-300" @dragenter="dragenter($event)"
                        @dragleave="fileDropping = null"
                        :class="{'bg-blue-200 bg-opacity-80': fileDropping == index && fileDragging != index}">
                    </div>
                </div>
            </template>
        </div>
    </template>
</div>
</div>

<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
<script src="https://unpkg.com/create-file-list"></script>
<script>
function dataFileDnD() {
    return {
        files: [],
        fileDragging: null,
        fileDropping: null,
        humanFileSize(size) {
            const i = Math.floor(Math.log(size) / Math.log(1024));
            return (
                (size / Math.pow(1024, i)).toFixed(2) * 1 +
                " " +
                ["B", "kB", "MB", "GB", "TB"][i]
            );
        },
        remove(index) {
            let files = [...this.files];
            files.splice(index, 1);

            this.files = createFileList(files);
        },
        drop(e) {
            let removed, add;
            let files = [...this.files];

            removed = files.splice(this.fileDragging, 1);
            files.splice(this.fileDropping, 0, ...removed);

            this.files = createFileList(files);

            this.fileDropping = null;
            this.fileDragging = null;
        },
        dragenter(e) {
            let targetElem = e.target.closest("[draggable]");

            this.fileDropping = targetElem.getAttribute("data-index");
        },
        dragstart(e) {
            this.fileDragging = e.target
                .closest("[draggable]")
                .getAttribute("data-index");
            e.dataTransfer.effectAllowed = "move";
        },
        loadFile(file) {
            const preview = document.querySelectorAll(".preview");
            const blobUrl = URL.createObjectURL(file);

            preview.forEach(elem => {
                elem.onload = () => {
                    URL.revokeObjectURL(elem.src); // free memory
                };
            });

            return blobUrl;
        },
        addFiles(e) {
            const files = createFileList([...this.files], [...e.target.files]);
            this.files = files;
            this.form.formData.files = [...files];
        }
    };
}
</script>

How to create a Drag&Drop, Sortable, Dropzone File Upload with Tailwind CSS?

To create a Drag&Drop, Sortable, Dropzone File Upload UI component with Tailwind CSS, follow these steps:

  1. Create a new HTML file and add the necessary HTML elements for the Drag&Drop, Sortable, Dropzone File Upload UI component. You will need a container element for the component, an area for the user to drop files, a list to display the uploaded files, and buttons to sort and delete the files.

  2. Add the necessary Tailwind CSS classes to the HTML elements to style the Drag&Drop, Sortable, Dropzone File Upload UI component. You can use the pre-defined classes provided by Tailwind CSS to style the elements.

  3. Add the necessary JavaScript code to handle the drag and drop functionality, sorting, and deleting of files. You can use a JavaScript library like Dropzone.js or Sortable.js to handle these functionalities.

  4. Test the Drag&Drop, Sortable, Dropzone File Upload UI component to ensure that it is working as expected.

Conclusion

In this article, we have shown you how to build a Drag&Drop, Sortable, Dropzone File Upload UI component with Tailwind CSS. Tailwind CSS provides a set of pre-defined classes that can be used to style the UI component, making it easy to create a beautiful and responsive UI component without writing any custom CSS code. We hope that this article has been helpful to you and that you can use this knowledge to create your own Drag&Drop, Sortable, Dropzone File Upload UI component.