React Dropzone
react-dropzone
is a third-party library. Please refer to its official documentation for more details.
It is essential to ensure that when incorporating the react-dropzone
component into your project, it is correctly wrapped using the AppReactDropzone
component. In scenarios where only a single instance of react-dropzone
is utilized, it should be individually enclosed within the AppReactDropzone
component. Conversely, if multiple instances of react-dropzone
are used in one page, it becomes necessary to wrap the entire page with the AppReactDropzone
component to ensure optimal styles.
Drop files here or click to upload.
Drop files here or click browse thorough your machine
- TSX
- JS
// React Imports
import { useState } from 'react'
// MUI Imports
import List from '@mui/material/List'
import Button from '@mui/material/Button'
import ListItem from '@mui/material/ListItem'
import { styled } from '@mui/material/styles'
import IconButton from '@mui/material/IconButton'
import Typography from '@mui/material/Typography'
import type { TypographyProps } from '@mui/material/Typography'
import { useTheme } from '@mui/material/styles'
// Third-party Imports
import { useDropzone } from 'react-dropzone'
type FileProp = {
name: string
type: string
size: number
}
// Styled component for the upload image inside the dropzone area
const Img = styled('img')(({ theme }) => ({
[theme.breakpoints.up('md')]: {
marginRight: theme.spacing(15.75)
},
[theme.breakpoints.down('md')]: {
marginBottom: theme.spacing(4)
},
[theme.breakpoints.down('sm')]: {
width: 160
}
}))
// Styled component for the heading inside the dropzone area
const HeadingTypography = styled(Typography)<TypographyProps>(({ theme }) => ({
marginBottom: theme.spacing(5),
[theme.breakpoints.down('sm')]: {
marginBottom: theme.spacing(4)
}
}))
const FileUploaderMultiple = () => {
// States
const [files, setFiles] = useState<File[]>([])
// Hooks
const { getRootProps, getInputProps } = useDropzone({
onDrop: (acceptedFiles: File[]) => {
setFiles(acceptedFiles.map((file: File) => Object.assign(file)))
}
})
const renderFilePreview = (file: FileProp) => {
if (file.type.startsWith('image')) {
return <img width={38} height={38} alt={file.name} src={URL.createObjectURL(file as any)} />
} else {
return <i className='ri-file-text-line' />
}
}
const handleRemoveFile = (file: FileProp) => {
const uploadedFiles = files
const filtered = uploadedFiles.filter((i: FileProp) => i.name !== file.name)
setFiles([...filtered])
}
const fileList = files.map((file: FileProp) => (
<ListItem key={file.name}>
<div className='file-details'>
<div className='file-preview'>{renderFilePreview(file)}</div>
<div>
<Typography className='file-name'>{file.name}</Typography>
<Typography className='file-size' variant='body2'>
{Math.round(file.size / 100) / 10 > 1000
? `${(Math.round(file.size / 100) / 10000).toFixed(1)} mb`
: `${(Math.round(file.size / 100) / 10).toFixed(1)} kb`}
</Typography>
</div>
</div>
<IconButton onClick={() => handleRemoveFile(file)}>
<i className='ri-close-line text-xl' />
</IconButton>
</ListItem>
))
const handleRemoveAllFiles = () => {
setFiles([])
}
// Hooks
const theme = useTheme()
return (
<>
<div {...getRootProps({ className: 'dropzone' })}>
<input {...getInputProps()} />
<div className='flex gap-3 items-center flex-col md:flex-row'>
<Img alt='Upload img' src='/images/misc/file-upload.png' className='max-bs-[160px] max-is-full bs-full' />
<div className='flex flex-col md:[text-align:unset] text-center'>
<HeadingTypography variant='h5'>Drop files here or click to upload.</HeadingTypography>
<Typography>
Drop files here or click{' '}
<a href='/' onClick={e => e.preventDefault()} className='text-textPrimary no-underline'>
browse
</a>{' '}
thorough your machine
</Typography>
</div>
</div>
</div>
{files.length ? (
<>
<List>{fileList}</List>
<div className='buttons'>
<Button color='error' variant='outlined' onClick={handleRemoveAllFiles}>
Remove All
</Button>
<Button variant='contained'>Upload Files</Button>
</div>
</>
) : null}
</>
)
}
export default FileUploaderMultiple
// React Imports
import { useState } from 'react'
// MUI Imports
import List from '@mui/material/List'
import Button from '@mui/material/Button'
import ListItem from '@mui/material/ListItem'
import { styled } from '@mui/material/styles'
import IconButton from '@mui/material/IconButton'
import Typography from '@mui/material/Typography'
import { useTheme } from '@mui/material/styles'
// Third-party Imports
import { useDropzone } from 'react-dropzone'
// Styled component for the upload image inside the dropzone area
const Img = styled('img')(({ theme }) => ({
[theme.breakpoints.up('md')]: {
marginRight: theme.spacing(15.75)
},
[theme.breakpoints.down('md')]: {
marginBottom: theme.spacing(4)
},
[theme.breakpoints.down('sm')]: {
width: 160
}
}))
// Styled component for the heading inside the dropzone area
const HeadingTypography = styled(Typography)(({ theme }) => ({
marginBottom: theme.spacing(5),
[theme.breakpoints.down('sm')]: {
marginBottom: theme.spacing(4)
}
}))
const FileUploaderMultiple = () => {
// States
const [files, setFiles] = useState([])
// Hooks
const { getRootProps, getInputProps } = useDropzone({
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file)))
}
})
const renderFilePreview = file => {
if (file.type.startsWith('image')) {
return <img width={38} height={38} alt={file.name} src={URL.createObjectURL(file)} />
} else {
return <i className='ri-file-text-line' />
}
}
const handleRemoveFile = file => {
const uploadedFiles = files
const filtered = uploadedFiles.filter(i => i.name !== file.name)
setFiles([...filtered])
}
const fileList = files.map(file => (
<ListItem key={file.name}>
<div className='file-details'>
<div className='file-preview'>{renderFilePreview(file)}</div>
<div>
<Typography className='file-name'>{file.name}</Typography>
<Typography className='file-size' variant='body2'>
{Math.round(file.size / 100) / 10 > 1000
? `${(Math.round(file.size / 100) / 10000).toFixed(1)} mb`
: `${(Math.round(file.size / 100) / 10).toFixed(1)} kb`}
</Typography>
</div>
</div>
<IconButton onClick={() => handleRemoveFile(file)}>
<i className='ri-close-line text-xl' />
</IconButton>
</ListItem>
))
const handleRemoveAllFiles = () => {
setFiles([])
}
// Hooks
const theme = useTheme()
return (
<>
<div {...getRootProps({ className: 'dropzone' })}>
<input {...getInputProps()} />
<div className='flex gap-3 items-center flex-col md:flex-row'>
<Img alt='Upload img' src='/images/misc/file-upload.png' className='max-bs-[160px] max-is-full bs-full' />
<div className='flex flex-col md:[text-align:unset] text-center'>
<HeadingTypography variant='h5'>Drop files here or click to upload.</HeadingTypography>
<Typography>
Drop files here or click{' '}
<a href='/' onClick={e => e.preventDefault()} className='text-textPrimary no-underline'>
browse
</a>{' '}
thorough your machine
</Typography>
</div>
</div>
</div>
{files.length ? (
<>
<List>{fileList}</List>
<div className='buttons'>
<Button color='error' variant='outlined' onClick={handleRemoveAllFiles}>
Remove All
</Button>
<Button variant='contained'>Upload Files</Button>
</div>
</>
) : null}
</>
)
}
export default FileUploaderMultiple
Drop files here or click to upload.
Drop files here or click browse thorough your machine
- TSX
- JS
// React Imports
import { useState } from 'react'
// MUI Imports
import Box from '@mui/material/Box'
import { styled } from '@mui/material/styles'
import Typography from '@mui/material/Typography'
import type { TypographyProps } from '@mui/material/Typography'
import { useTheme } from '@mui/material/styles'
// Third-party Imports
import { useDropzone } from 'react-dropzone'
type FileProp = {
name: string
type: string
size: number
}
// Styled component for the upload image inside the dropzone area
const Img = styled('img')(({ theme }) => ({
[theme.breakpoints.up('md')]: {
marginRight: theme.spacing(15.75)
},
[theme.breakpoints.down('md')]: {
marginBottom: theme.spacing(4)
},
[theme.breakpoints.down('sm')]: {
width: 160
}
}))
// Styled component for the heading inside the dropzone area
const HeadingTypography = styled(Typography)<TypographyProps>(({ theme }) => ({
marginBottom: theme.spacing(5),
[theme.breakpoints.down('sm')]: {
marginBottom: theme.spacing(4)
}
}))
const FileUploaderSingle = () => {
// States
const [files, setFiles] = useState<File[]>([])
// Hooks
const { getRootProps, getInputProps } = useDropzone({
multiple: false,
accept: {
'image/*': ['.png', '.jpg', '.jpeg', '.gif']
},
onDrop: (acceptedFiles: File[]) => {
setFiles(acceptedFiles.map((file: File) => Object.assign(file)))
}
})
const theme = useTheme()
const img = files.map((file: FileProp) => (
<img key={file.name} alt={file.name} className='single-file-image' src={URL.createObjectURL(file as any)} />
))
return (
<Box {...getRootProps({ className: 'dropzone' })} {...(files.length && { sx: { height: 450 } })}>
<input {...getInputProps()} />
{files.length ? (
img
) : (
<div className='flex items-center flex-col md:flex-row'>
<Img alt='Upload img' src='/images/misc/file-upload.png' className='max-bs-[160px] max-is-full bs-full' />
<div className='flex flex-col md:[text-align:unset] text-center'>
<HeadingTypography variant='h5'>Drop files here or click to upload.</HeadingTypography>
<Typography>
Drop files here or click{' '}
<a href='/' onClick={e => e.preventDefault()} className='text-textPrimary no-underline'>
browse
</a>{' '}
thorough your machine
</Typography>
</div>
</div>
)}
</Box>
)
}
export default FileUploaderSingle
// React Imports
import { useState } from 'react'
// MUI Imports
import Box from '@mui/material/Box'
import { styled } from '@mui/material/styles'
import Typography from '@mui/material/Typography'
import { useTheme } from '@mui/material/styles'
// Third-party Imports
import { useDropzone } from 'react-dropzone'
// Styled component for the upload image inside the dropzone area
const Img = styled('img')(({ theme }) => ({
[theme.breakpoints.up('md')]: {
marginRight: theme.spacing(15.75)
},
[theme.breakpoints.down('md')]: {
marginBottom: theme.spacing(4)
},
[theme.breakpoints.down('sm')]: {
width: 160
}
}))
// Styled component for the heading inside the dropzone area
const HeadingTypography = styled(Typography)(({ theme }) => ({
marginBottom: theme.spacing(5),
[theme.breakpoints.down('sm')]: {
marginBottom: theme.spacing(4)
}
}))
const FileUploaderSingle = () => {
// States
const [files, setFiles] = useState([])
// Hooks
const { getRootProps, getInputProps } = useDropzone({
multiple: false,
accept: {
'image/*': ['.png', '.jpg', '.jpeg', '.gif']
},
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file)))
}
})
const theme = useTheme()
const img = files.map(file => (
<img key={file.name} alt={file.name} className='single-file-image' src={URL.createObjectURL(file)} />
))
return (
<Box {...getRootProps({ className: 'dropzone' })} {...(files.length && { sx: { height: 450 } })}>
<input {...getInputProps()} />
{files.length ? (
img
) : (
<div className='flex items-center flex-col md:flex-row'>
<Img alt='Upload img' src='/images/misc/file-upload.png' className='max-bs-[160px] max-is-full bs-full' />
<div className='flex flex-col md:[text-align:unset] text-center'>
<HeadingTypography variant='h5'>Drop files here or click to upload.</HeadingTypography>
<Typography>
Drop files here or click{' '}
<a href='/' onClick={e => e.preventDefault()} className='text-textPrimary no-underline'>
browse
</a>{' '}
thorough your machine
</Typography>
</div>
</div>
)}
</Box>
)
}
export default FileUploaderSingle
Drop files here or click to upload.
Allowed *.jpeg, *.jpg, *.png, *.gif
Max 2 files and max size of 2 MB
- TSX
- JS
// React Imports
import { useState } from 'react'
// MUI Imports
import List from '@mui/material/List'
import Button from '@mui/material/Button'
import ListItem from '@mui/material/ListItem'
import { styled } from '@mui/material/styles'
import IconButton from '@mui/material/IconButton'
import Typography from '@mui/material/Typography'
import type { TypographyProps } from '@mui/material/Typography'
import { useTheme } from '@mui/material/styles'
// Third-party Imports
import { toast } from 'react-toastify'
// Icon Imports
import { useDropzone } from 'react-dropzone'
type FileProp = {
name: string
type: string
size: number
}
// Styled component for the upload image inside the dropzone area
const Img = styled('img')(({ theme }) => ({
[theme.breakpoints.up('md')]: {
marginRight: theme.spacing(15.75)
},
[theme.breakpoints.down('md')]: {
marginBottom: theme.spacing(4)
},
[theme.breakpoints.down('sm')]: {
width: 160
}
}))
// Styled component for the heading inside the dropzone area
const HeadingTypography = styled(Typography)<TypographyProps>(({ theme }) => ({
marginBottom: theme.spacing(5),
[theme.breakpoints.down('sm')]: {
marginBottom: theme.spacing(4)
}
}))
const FileUploaderRestrictions = () => {
// States
const [files, setFiles] = useState<File[]>([])
// Hooks
const { getRootProps, getInputProps } = useDropzone({
maxFiles: 2,
maxSize: 2000000,
accept: {
'image/*': ['.png', '.jpg', '.jpeg', '.gif']
},
onDrop: (acceptedFiles: File[]) => {
setFiles(acceptedFiles.map((file: File) => Object.assign(file)))
},
onDropRejected: () => {
toast.error('You can only upload 2 files & maximum size of 2 MB.', {
autoClose: 3000
})
}
})
const theme = useTheme()
const renderFilePreview = (file: FileProp) => {
if (file.type.startsWith('image')) {
return <img width={38} height={38} alt={file.name} src={URL.createObjectURL(file as any)} />
} else {
return <i className='ri-file-text-line' />
}
}
const handleRemoveFile = (file: FileProp) => {
const uploadedFiles = files
const filtered = uploadedFiles.filter((i: FileProp) => i.name !== file.name)
setFiles([...filtered])
}
const fileList = files.map((file: FileProp) => (
<ListItem key={file.name}>
<div className='file-details'>
<div className='file-preview'>{renderFilePreview(file)}</div>
<div>
<Typography className='file-name'>{file.name}</Typography>
<Typography className='file-size' variant='body2'>
{Math.round(file.size / 100) / 10 > 1000
? `${(Math.round(file.size / 100) / 10000).toFixed(1)} mb`
: `${(Math.round(file.size / 100) / 10).toFixed(1)} kb`}
</Typography>
</div>
</div>
<IconButton onClick={() => handleRemoveFile(file)}>
<i className='ri-close-line text-xl' />
</IconButton>
</ListItem>
))
const handleRemoveAllFiles = () => {
setFiles([])
}
return (
<>
<div {...getRootProps({ className: 'dropzone' })}>
<input {...getInputProps()} />
<div className='flex items-center flex-col md:flex-row'>
<Img alt='Upload img' src='/images/misc/file-upload.png' className='max-bs-[160px] max-is-full bs-full' />
<div className='flex flex-col md:[text-align:unset] text-center'>
<HeadingTypography variant='h5'>Drop files here or click to upload.</HeadingTypography>
<Typography>Allowed *.jpeg, *.jpg, *.png, *.gif</Typography>
<Typography>Max 2 files and max size of 2 MB</Typography>
</div>
</div>
</div>
{files.length ? (
<>
<List>{fileList}</List>
<div className='buttons'>
<Button color='error' variant='outlined' onClick={handleRemoveAllFiles}>
Remove All
</Button>
<Button variant='contained'>Upload Files</Button>
</div>
</>
) : null}
</>
)
}
export default FileUploaderRestrictions
// React Imports
import { useState } from 'react'
// MUI Imports
import List from '@mui/material/List'
import Button from '@mui/material/Button'
import ListItem from '@mui/material/ListItem'
import { styled } from '@mui/material/styles'
import IconButton from '@mui/material/IconButton'
import Typography from '@mui/material/Typography'
import { useTheme } from '@mui/material/styles'
// Third-party Imports
import { toast } from 'react-toastify'
// Icon Imports
import { useDropzone } from 'react-dropzone'
// Styled component for the upload image inside the dropzone area
const Img = styled('img')(({ theme }) => ({
[theme.breakpoints.up('md')]: {
marginRight: theme.spacing(15.75)
},
[theme.breakpoints.down('md')]: {
marginBottom: theme.spacing(4)
},
[theme.breakpoints.down('sm')]: {
width: 160
}
}))
// Styled component for the heading inside the dropzone area
const HeadingTypography = styled(Typography)(({ theme }) => ({
marginBottom: theme.spacing(5),
[theme.breakpoints.down('sm')]: {
marginBottom: theme.spacing(4)
}
}))
const FileUploaderRestrictions = () => {
// States
const [files, setFiles] = useState([])
// Hooks
const { getRootProps, getInputProps } = useDropzone({
maxFiles: 2,
maxSize: 2000000,
accept: {
'image/*': ['.png', '.jpg', '.jpeg', '.gif']
},
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file)))
},
onDropRejected: () => {
toast.error('You can only upload 2 files & maximum size of 2 MB.', {
autoClose: 3000
})
}
})
const theme = useTheme()
const renderFilePreview = file => {
if (file.type.startsWith('image')) {
return <img width={38} height={38} alt={file.name} src={URL.createObjectURL(file)} />
} else {
return <i className='ri-file-text-line' />
}
}
const handleRemoveFile = file => {
const uploadedFiles = files
const filtered = uploadedFiles.filter(i => i.name !== file.name)
setFiles([...filtered])
}
const fileList = files.map(file => (
<ListItem key={file.name}>
<div className='file-details'>
<div className='file-preview'>{renderFilePreview(file)}</div>
<div>
<Typography className='file-name'>{file.name}</Typography>
<Typography className='file-size' variant='body2'>
{Math.round(file.size / 100) / 10 > 1000
? `${(Math.round(file.size / 100) / 10000).toFixed(1)} mb`
: `${(Math.round(file.size / 100) / 10).toFixed(1)} kb`}
</Typography>
</div>
</div>
<IconButton onClick={() => handleRemoveFile(file)}>
<i className='ri-close-line text-xl' />
</IconButton>
</ListItem>
))
const handleRemoveAllFiles = () => {
setFiles([])
}
return (
<>
<div {...getRootProps({ className: 'dropzone' })}>
<input {...getInputProps()} />
<div className='flex items-center flex-col md:flex-row'>
<Img alt='Upload img' src='/images/misc/file-upload.png' className='max-bs-[160px] max-is-full bs-full' />
<div className='flex flex-col md:[text-align:unset] text-center'>
<HeadingTypography variant='h5'>Drop files here or click to upload.</HeadingTypography>
<Typography>Allowed *.jpeg, *.jpg, *.png, *.gif</Typography>
<Typography>Max 2 files and max size of 2 MB</Typography>
</div>
</div>
</div>
{files.length ? (
<>
<List>{fileList}</List>
<div className='buttons'>
<Button color='error' variant='outlined' onClick={handleRemoveAllFiles}>
Remove All
</Button>
<Button variant='contained'>Upload Files</Button>
</div>
</>
) : null}
</>
)
}
export default FileUploaderRestrictions