JSFiddle - React, Tailwind, and code Playground

by Spencer Smith

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Custom File Upload</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="upload-container">
        <input type="file" id="file-input" class="file-input" multiple>
        <label for="file-input" class="file-label">
            <div class="dropzone">
                <p>Drag & Drop files here</p>
                <p>or</p>
                <button type="button" class="upload-button">Browse Files</button>
            </div>
        </label>
        <div id="file-list" class="file-list"></div>
    </div>

    <script src="script.js"></script>
</body>
</html>

CSS

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
    font-family: Arial, sans-serif;
}

.upload-container {
    width: 100%;
    max-width: 400px;
    padding: 20px;
    background-color: #fff;
    border-radius: 10px;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    text-align: center;
}

.file-input {
    display: none;
}

.file-label {
    display: block;
    width: 100%;
    height: 100%;
}

.dropzone {
    padding: 20px;
    border: 2px dashed #ccc;
    border-radius: 10px;
    background-color: #fafafa;
    cursor: pointer;
    transition: background-color 0.3s;
}

.dropzone.dragover {
    background-color: #f1f1f1;
}

.upload-button {
    padding: 10px 20px;
    margin-top: 10px;
    background-color: #007bff;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s;
}

.upload-button:hover {
    background-color: #0056b3;
}

.file-list {
    margin-top: 20px;
    text-align: left;
}

.file-list p {
    margin-bottom: 10px;
}

JavaScript

document.addEventListener('DOMContentLoaded', () => {
    const dropzone = document.querySelector('.dropzone');
    const fileInput = document.getElementById('file-input');
    const fileList = document.getElementById('file-list');

    dropzone.addEventListener('dragover', (event) => {
        event.preventDefault();
        dropzone.classList.add('dragover');
    });

    dropzone.addEventListener('dragleave', () => {
        dropzone.classList.remove('dragover');
    });

    dropzone.addEventListener('drop', (event) => {
        event.preventDefault();
        dropzone.classList.remove('dragover');
        const files = event.dataTransfer.files;
        handleFiles(files);
    });

    dropzone.addEventListener('click', () => {
        fileInput.click();
    });

    fileInput.addEventListener('change', () => {
        const files = fileInput.files;
        handleFiles(files);
    });

    function handleFiles(files) {
        fileList.innerHTML = '';
        Array.from(files).forEach((file) => {
            const listItem = document.createElement('p');
            listItem.textContent = file.name;
            fileList.appendChild(listItem);
        });
    }
});