FileInput
Examples
(7)Properties
(69)Playground
Basic
Loading demo…
import
{
useState
}
from
'react'
;
import
{
Block
,
FileInput
,
Text
}
from
'@platform-blocks/react-ui-library'
;
import
type
{
FileInputFile
}
from
'@platform-blocks/react-ui-library'
;
export
function
Demo
(
)
{
const
[
files
,
setFiles
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
return
(
<Block
fullWidth
>
<FileInput
label
=
"Upload files"
helperText
=
"Choose files from your device"
onFilesChange
=
{
setFiles
}
multiple
fullWidth
/>
{
files
.
length
>
0
&&
(
<Text
size
=
"xs"
color
=
"secondary"
>
Selected
:
{
files
.
map
(
(
file
)
=>
file
.
name
)
.
join
(
', '
)
}
</Text
>
)
}
</Block
>
)
;
}
Dropzone
Loading demo…
import
{
useState
}
from
'react'
;
import
{
Platform
}
from
'react-native'
;
import
{
Block
,
FileInput
,
Text
}
from
'@platform-blocks/react-ui-library'
;
import
type
{
FileInputFile
}
from
'@platform-blocks/react-ui-library'
;
export
function
Demo
(
)
{
const
[
files
,
setFiles
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
const
instructions
=
Platform
.
OS
===
'web'
?
'Drag files into the dropzone or click Browse files to pick from your desktop.'
:
'Tap the dropzone to open the native file picker on touch devices.'
;
return
(
<Block
fullWidth
>
<Text
size
=
"sm"
color
=
"secondary"
>
{
instructions
}
</Text
>
<FileInput
variant
=
"dropzone"
multiple
accept
=
{
[
'image/*'
,
'.pdf'
,
'.txt'
]
}
helperText
=
"Drag & drop on desktop or tap to browse on mobile"
onFilesChange
=
{
setFiles
}
showFileList
fullWidth
/>
{
files
.
length
>
0
&&
(
<Block
>
<Text
size
=
"xs"
weight
=
"semibold"
>
Selected
files
(
{
files
.
length
}
)
</Text
>
<Block
>
{
files
.
map
(
(
file
)
=>
(
<Text
key
=
{
file
.
id
}
size
=
"xs"
color
=
"secondary"
>
{
file
.
name
}
</Text
>
)
)
}
</Block
>
</Block
>
)
}
</Block
>
)
;
}
File Type Restrictions
Loading demo…
import
{
useState
}
from
'react'
;
import
{
Block
,
FileInput
,
Text
}
from
'@platform-blocks/react-ui-library'
;
import
type
{
FileInputFile
}
from
'@platform-blocks/react-ui-library'
;
export
function
Demo
(
)
{
const
[
imageFiles
,
setImageFiles
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
const
[
documentFiles
,
setDocumentFiles
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
const
[
videoFiles
,
setVideoFiles
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
return
(
<Block
fullWidth
>
<Block
>
<Text
weight
=
"semibold"
>
File
type
restrictions
</Text
>
<Text
size
=
"sm"
color
=
"secondary"
>
Limit
accepted file types per uploader using
MIME
types
,
extensions
,
and size caps
.
</Text
>
</Block
>
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Images
only
</Text
>
<FileInput
accept
=
{
[
'image/*'
]
}
helperText
=
"Only image files are allowed"
onFilesChange
=
{
setImageFiles
}
multiple
fullWidth
/>
{
imageFiles
.
length
>
0
&&
(
<Text
size
=
"xs"
color
=
"secondary"
>
Selected
:
{
imageFiles
.
map
(
(
file
)
=>
file
.
name
)
.
join
(
', '
)
}
</Text
>
)
}
</Block
>
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Documents
only
</Text
>
<FileInput
accept
=
{
[
'.pdf'
,
'.doc'
,
'.docx'
,
'.txt'
]
}
helperText
=
"PDF, Word documents, and text files only"
onFilesChange
=
{
setDocumentFiles
}
multiple
fullWidth
/>
{
documentFiles
.
length
>
0
&&
(
<Text
size
=
"xs"
color
=
"secondary"
>
Selected
:
{
documentFiles
.
map
(
(
file
)
=>
file
.
name
)
.
join
(
', '
)
}
</Text
>
)
}
</Block
>
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Videos
(
max 50MB
)
</Text
>
<FileInput
accept
=
{
[
'video/*'
]
}
maxSize
=
{
50
*
1024
*
1024
}
helperText
=
"Video files up to 50MB"
onFilesChange
=
{
setVideoFiles
}
fullWidth
/>
{
videoFiles
.
length
>
0
&&
(
<Text
size
=
"xs"
color
=
"secondary"
>
Selected
:
{
videoFiles
.
map
(
(
file
)
=>
file
.
name
)
.
join
(
', '
)
}
</Text
>
)
}
</Block
>
</Block
>
)
;
}
Image Preview
Loading demo…
import
{
useState
}
from
'react'
;
import
{
Block
,
Button
,
Card
,
FileInput
,
Flex
,
Text
}
from
'@platform-blocks/react-ui-library'
;
import
type
{
FileInputFile
}
from
'@platform-blocks/react-ui-library'
;
export
function
Demo
(
)
{
const
[
images
,
setImages
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
const
handleRemoveFile
=
(
index
:
number
)
=>
{
setImages
(
(
prev
)
=>
prev
.
filter
(
(
_
,
itemIndex
)
=>
itemIndex
!==
index
)
)
;
}
;
return
(
<Block
fullWidth
>
<FileInput
label
=
"Upload images"
accept
=
{
[
'image/*'
]
}
helperText
=
"Add images to see inline previews"
onFilesChange
=
{
setImages
}
multiple
fullWidth
/>
{
images
.
length
>
0
&&
(
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Selected
images
(
{
images
.
length
}
)
</Text
>
<Flex
direction
=
"row"
gap
=
{
12
}
wrap
=
"wrap"
>
{
images
.
map
(
(
file
,
index
)
=>
(
<Card
key
=
{
file
.
id
??
file
.
name
}
p
=
{
8
}
variant
=
"outline"
style
=
{
{
width
:
150
}
}
>
<Block
>
{
file
.
previewUrl
&&
(
<
img
src
=
{
file
.
previewUrl
}
alt
=
{
file
.
name
}
style
=
{
{
width
:
'100%'
,
height
:
100
,
objectFit
:
'cover'
,
borderRadius
:
4
}
}
/>
)
}
<Text
size
=
"xs"
weight
=
"medium"
align
=
"center"
>
{
file
.
name
}
</Text
>
<Button
size
=
"xs"
variant
=
"outline"
onPress
=
{
(
)
=>
handleRemoveFile
(
index
)
}
>
Remove
</Button
>
</Block
>
</Card
>
)
)
}
</Flex
>
</Block
>
)
}
</Block
>
)
;
}
Size Variants
Loading demo…
import
{
useState
}
from
'react'
;
import
{
Block
,
FileInput
,
Text
}
from
'@platform-blocks/react-ui-library'
;
import
type
{
FileInputFile
}
from
'@platform-blocks/react-ui-library'
;
const
sizes
=
[
{
label
:
'Small'
,
size
:
'sm'
as
const
}
,
{
label
:
'Medium (default)'
,
size
:
'md'
as
const
}
,
{
label
:
'Large'
,
size
:
'lg'
as
const
}
,
]
;
export
function
Demo
(
)
{
const
[
files
,
setFiles
]
=
useState
<Record
<
string
,
FileInputFile
[
]
>>
(
{
}
)
;
const
handleChange
=
(
key
:
string
)
=>
(
next
:
FileInputFile
[
]
)
=>
{
setFiles
(
(
prev
)
=>
(
{
.
.
.
prev
,
[
key
]
:
next
}
)
)
;
}
;
return
(
<Block
fullWidth
>
{
sizes
.
map
(
(
{
label
,
size
}
)
=>
(
<Block
key
=
{
label
}
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
{
label
}
</Text
>
<FileInput
label
=
{
`${label} input`
}
helperText
=
{
`${label} size example`
}
onFilesChange
=
{
handleChange
(
label
)
}
size
=
{
size
}
multiple
=
{
size
===
'lg'
}
fullWidth
/>
{
files
[
label
]
?
.
length
?
(
<Text
size
=
"xs"
color
=
"secondary"
>
Selected
:
{
files
[
label
]
.
length
}
</Text
>
)
:
null
}
</Block
>
)
)
}
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Custom
placeholder
</Text
>
<FileInput
placeholder
=
"Click to select your files"
helperText
=
"Demonstrates placeholder overrides"
onFilesChange
=
{
handleChange
(
'custom'
)
}
fullWidth
/>
</Block
>
</Block
>
)
;
}
Upload Progress
Loading demo…
import
{
useState
}
from
'react'
;
import
{
Block
,
Button
,
FileInput
,
Flex
,
Text
}
from
'@platform-blocks/react-ui-library'
;
import
type
{
FileInputFile
}
from
'@platform-blocks/react-ui-library'
;
export
function
Demo
(
)
{
const
[
files
,
setFiles
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
const
[
isUploading
,
setIsUploading
]
=
useState
(
false
)
;
const
[
uploadProgress
,
setUploadProgress
]
=
useState
<
{
[
key
:
string
]
:
number
}
>
(
{
}
)
;
const
handleUpload
=
async
(
)
=>
{
if
(
files
.
length
===
0
)
return
;
setIsUploading
(
true
)
;
// Simulate upload process for each file
for
(
const
file of files
)
{
// Simulate progress updates
for
(
let
progress
=
0
;
progress
<=
100
;
progress
+=
25
)
{
setUploadProgress
(
prev
=>
(
{
.
.
.
prev
,
[
file
.
name
]
:
progress
}
)
)
;
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
300
)
)
;
}
}
setIsUploading
(
false
)
;
alert
(
'Files uploaded successfully!'
)
;
setFiles
(
[
]
)
;
setUploadProgress
(
{
}
)
;
}
;
const
handleRemove
=
(
index
:
number
)
=>
{
setFiles
(
prev
=>
prev
.
filter
(
(
_
,
i
)
=>
i
!==
index
)
)
;
}
;
return
(
<Block
fullWidth
>
<FileInput
label
=
"Select files to upload"
helperText
=
"Choose files and click upload to simulate progress"
onFilesChange
=
{
setFiles
}
multiple
maxFiles
=
{
5
}
maxSize
=
{
10
*
1024
*
1024
}
fullWidth
/>
{
files
.
length
>
0
&&
(
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Selected
files
</Text
>
<Block
>
{
files
.
map
(
(
file
,
index
)
=>
(
<Flex
key
=
{
file
.
id
??
file
.
name
}
direction
=
"row"
justify
=
"space-between"
align
=
"center"
p
=
{
8
}
style
=
{
{
borderWidth
:
1
,
borderColor
:
'#e0e0e0'
,
borderRadius
:
4
}
}
>
<Block
>
<Text
size
=
"sm"
weight
=
"medium"
>
{
file
.
name
}
</Text
>
<Text
size
=
"xs"
color
=
"secondary"
>
{
(
file
.
size
/
1024
)
.
toFixed
(
1
)
}
KB
</Text
>
{
uploadProgress
[
file
.
name
]
!==
undefined
&&
(
<Text
size
=
"xs"
color
=
"primary"
>
Progress
:
{
uploadProgress
[
file
.
name
]
}
%
</Text
>
)
}
</Block
>
<Button
size
=
"xs"
variant
=
"outline"
onPress
=
{
(
)
=>
handleRemove
(
index
)
}
disabled
=
{
isUploading
}
>
Remove
</Button
>
</Flex
>
)
)
}
</Block
>
<Flex
direction
=
"row"
gap
=
{
12
}
wrap
=
"wrap"
>
<Button
variant
=
"gradient"
onPress
=
{
handleUpload
}
disabled
=
{
isUploading
||
files
.
length
===
0
}
loading
=
{
isUploading
}
>
{
isUploading
?
'Uploading…'
:
'Upload files'
}
</Button
>
<Button
variant
=
"outline"
onPress
=
{
(
)
=>
{
setFiles
(
[
]
)
;
setUploadProgress
(
{
}
)
;
}
}
disabled
=
{
isUploading
}
>
Clear
all
</Button
>
</Flex
>
</Block
>
)
}
</Block
>
)
;
}
Validation & States
Loading demo…
import
{
useState
}
from
'react'
;
import
{
Block
,
FileInput
,
Text
}
from
'@platform-blocks/react-ui-library'
;
import
type
{
FileInputFile
}
from
'@platform-blocks/react-ui-library'
;
export
function
Demo
(
)
{
const
[
validatedFiles
,
setValidatedFiles
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
const
[
singleFile
,
setSingleFile
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
const
[
limitedFiles
,
setLimitedFiles
]
=
useState
<FileInputFile
[
]
>
(
[
]
)
;
return
(
<Block
fullWidth
>
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Size
validation
(
max 2MB
)
</Text
>
<FileInput
label
=
"Upload small files"
helperText
=
"Files must be below 2MB"
onFilesChange
=
{
setValidatedFiles
}
maxSize
=
{
2
*
1024
*
1024
}
multiple
fullWidth
/>
{
validatedFiles
.
length
>
0
&&
(
<Text
size
=
"xs"
color
=
"secondary"
>
Selected
:
{
validatedFiles
.
length
}
</Text
>
)
}
</Block
>
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Single
file only
</Text
>
<FileInput
label
=
"Upload one file"
helperText
=
"Select a single file"
onFilesChange
=
{
setSingleFile
}
multiple
=
{
false
}
fullWidth
/>
{
singleFile
[
0
]
&&
(
<Text
size
=
"xs"
color
=
"secondary"
>
Selected
:
{
singleFile
[
0
]
.
name
}
</Text
>
)
}
</Block
>
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Limited
file count
</Text
>
<FileInput
label
=
"Upload up to 3 files"
helperText
=
"Selecting more will show a validation error"
onFilesChange
=
{
setLimitedFiles
}
multiple
maxFiles
=
{
3
}
fullWidth
/>
{
limitedFiles
.
length
>
0
&&
(
<Text
size
=
"xs"
color
=
"secondary"
>
Selected
:
{
limitedFiles
.
length
}
</Text
>
)
}
</Block
>
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
With
error state
</Text
>
<FileInput
label
=
"Required upload"
helperText
=
"This field is required"
onFilesChange
=
{
(
)
=>
{
}
}
error
=
"Please select at least one file"
required
fullWidth
/>
</Block
>
<Block
fullWidth
>
<Text
size
=
"sm"
weight
=
"semibold"
>
Disabled
state
</Text
>
<FileInput
label
=
"Disabled upload"
helperText
=
"The uploader is unavailable"
onFilesChange
=
{
(
)
=>
{
}
}
disabled
fullWidth
/>
</Block
>
</Block
>
)
;
}
</>
react-ui-library
100+ accessible, themeable components that work seamlessly across iOS, Android, and Web.
A Platform Blocks product.
Quick Links
Resources