← Components/Inputs & Forms

FileUpload

fileupload-1779394025632.tsx
'use client'
import { useState, useRef } from 'react'

export default function FileUpload() {
  const [files, setFiles] = useState([])
  const [dragging, setDragging] = useState(false)
  const inputRef = useRef(null)
  const addFiles = (newFiles) => {
    const arr = Array.from(newFiles).map(f => ({ name:f.name, size:f.size, progress:0 }))
    setFiles(prev => [...prev, ...arr])
    arr.forEach((_, i) => {
      let p = 0
      const t = setInterval(() => {
        p += Math.random() * 20
        if (p >= 100) { p = 100; clearInterval(t) }
        setFiles(prev => prev.map((f, j) => j === prev.length - arr.length + i ? { ...f, progress:Math.round(p) } : f))
      }, 200)
    })
  }
  const fmt = (bytes) => bytes < 1024 ? bytes + 'B' : bytes < 1048576 ? (bytes/1024).toFixed(1) + 'KB' : (bytes/1048576).toFixed(1) + 'MB'
  return (
    <div style={{ maxWidth:'400px' }}>
      <div
        onDragOver={e => { e.preventDefault(); setDragging(true) }}
        onDragLeave={() => setDragging(false)}
        onDrop={e => { e.preventDefault(); setDragging(false); addFiles(e.dataTransfer.files) }}
        onClick={() => inputRef.current?.click()}
        style={{
          border:'2px dashed ' + (dragging ? '#6d28d9' : '#cbd5e1'),
          borderRadius:'14px', padding:'32px 20px', textAlign:'center',
          background:dragging ? '#f5f3ff' : '#f8fafc', cursor:'pointer', transition:'all 0.2s',
        }}
      >
        <div style={{ fontSize:'36px', marginBottom:'8px' }}>📁</div>
        <div style={{ fontWeight:600, color:'#374151', marginBottom:'4px' }}>Drop files here</div>
        <div style={{ fontSize:'13px', color:'#94a3b8' }}>or click to browse</div>
        <input ref={inputRef} type="file" multiple hidden onChange={e => addFiles(e.target.files)} />
      </div>
      {files.length > 0 && (
        <div style={{ marginTop:'12px', display:'flex', flexDirection:'column', gap:'8px' }}>
          {files.map((f, i) => (
            <div key={i} style={{ background:'#fff', borderRadius:'10px', padding:'10px 14px', boxShadow:'0 1px 6px rgba(0,0,0,0.06)' }}>
              <div style={{ display:'flex', justifyContent:'space-between', marginBottom:'6px' }}>
                <span style={{ fontSize:'13px', fontWeight:500, color:'#1e293b' }}>{f.name}</span>
                <span style={{ fontSize:'12px', color:'#94a3b8' }}>{f.progress}%</span>
              </div>
              <div style={{ height:'4px', background:'#e2e8f0', borderRadius:'2px' }}>
                <div style={{ height:'100%', borderRadius:'2px', background:'#6d28d9', width:f.progress+'%', transition:'width 0.2s' }} />
              </div>
              <div style={{ fontSize:'11px', color:'#94a3b8', marginTop:'4px' }}>{fmt(f.size)}</div>
            </div>
          ))}
        </div>
      )}
    </div>
  )
}

Component info

CategoryInputs & Forms
Frameworkreact
TierFREE
Views0
Copies0

About

Drag-and-drop file upload zone with progress and file list

More from Inputs & Forms

'use client';

import { useState, useEffect } from 'react';

interface Tag {
  id: number;
  name: string;
}

const TagInput = () => {
  const [tags, setTags] = useState<Tag[]>([]);
  const [inputValue, setInputValue] = useState('');
  const [suggest
TagInput
Inputs & Forms
'use client';

import React, { useState } from 'react';

interface File {
  name: string;
  size: number;
  progress: number;
}

const FileUpload = () => {
  const [dragOver, setDragOver] = useState(false);
  const [files, setFiles] = useState<File[]
FileUpload
Inputs & Forms
import React, { useState } from 'react';

const OTPInput = () => {
  const [otp, setOtp] = useState(new Array(6).fill(''));
  const [activeIndex, setActiveIndex] = useState(0);

  const handleChange = (e, index) => {
    const value = e.target.value;
OTPInput
Inputs & Forms
'use client';

import React, { useState } from 'react';

interface RangeSliderProps {
  min: number;
  max: number;
  defaultValue: [number, number];
}

const RangeSlider: React.FC<RangeSliderProps> = ({ min, max, defaultValue }) => {
  const [minVal
RangeSlider
Inputs & Forms