File Upload Demo
Supports 7 image formats. Max size: 4MB.
Installation
Copy and paste the following code into your project.
import { truncate } from 'lodash';
import React, { useCallback, useMemo } from 'react';
import { toast } from 'sonner';
import { Icon } from '../icon';
// constants
const SUPPORTED_IMAGE_FORMATS = [
'image/webp',
'image/jpeg',
'image/png',
'image/gif',
// 'image/svg+xml',
'image/avif',
'image/tiff',
'image/ico',
];
const SUPPORTED_VIDEO_FORMATS = ['video/mpeg', 'video/mp4', 'video/mov', 'video/avi'];
const SUPPORTED_AUDIO_FORMATS = ['audio/mp3', 'audio/wav', 'audio/ogg'];
const SUPPORTED_FILE_FORMATS = [
'application/csv',
'application/zip',
'application/pdf',
'application/xls',
'application/xlsx',
'application/json',
];
export const ALL_SUPPORTED_FORMATS = [
...SUPPORTED_IMAGE_FORMATS,
...SUPPORTED_VIDEO_FORMATS,
...SUPPORTED_AUDIO_FORMATS,
...SUPPORTED_FILE_FORMATS,
];
export const SORTED_SUPPORTED_FORMATS = {
image: SUPPORTED_IMAGE_FORMATS,
video: SUPPORTED_VIDEO_FORMATS,
audio: SUPPORTED_AUDIO_FORMATS,
file: SUPPORTED_FILE_FORMATS,
};
export const MAX_IMAGE_SIZE = 4; //In MegaBytes
// components
const byte2MB = (sizeInBytes: number, decimalsNum = 2) => {
const result = sizeInBytes / (1024 * 1024);
return +result.toFixed(decimalsNum);
};
export interface FileInputProps {
idName: string;
onFileChange: (file: File) => void;
formatType?: keyof typeof SORTED_SUPPORTED_FORMATS;
}
export const FileInput: React.FC<FileInputProps> = ({ idName, onFileChange, formatType }) => {
const formats = useMemo(() => {
return formatType ? SORTED_SUPPORTED_FORMATS[formatType] : ALL_SUPPORTED_FORMATS;
}, [formatType]);
const handleChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
if (byte2MB(file.size) > MAX_IMAGE_SIZE) {
toast.error('File size is too large', {
description: `Max size is ${MAX_IMAGE_SIZE}MB`,
});
return;
}
if (!formats.includes(file.type)) {
toast.error('File type is not supported', {
description: truncate(
`File type is not supported, supported formats are ${formats.join(', ')}`,
{
length: 70,
separator: ' ',
}
),
});
return;
}
onFileChange(file);
},
[formats, onFileChange]
);
return (
<label
htmlFor={'file-' + idName}
className="dark:hover:bg-bray-800 flex h-full w-full cursor-pointer flex-col items-center justify-center rounded-lg border border-dashed border-gray-300 bg-gray-50 hover:bg-gray-100 dark:border-gray-600 dark:bg-gray-700 dark:hover:border-gray-500 dark:hover:bg-gray-600"
>
<div className="flex flex-col items-center justify-center pb-6 pt-5">
<Icon.uploadCloud />
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400">
{/* {t.rich('upload.title', {
span: (chunks) => <span className="font-semibold">{chunks}</span>,
})} */}
<span className="font-semibold">Click to upload</span> or drag and drop
</p>
<p className="text-xs text-gray-500 dark:text-gray-400">PNG, JPG or GIF</p>
</div>
<input
id={'file-' + idName}
type="file"
className="hidden"
onChange={handleChange}
accept={formats.join(',')}
/>
</label>
);
};
Update the import paths to match your project setup.
Usage
import { FileInput } from '@kit/ui/file-upload';
<FileInput
idName="demo"
formatType="image"
onFileChange={(file) => {
console.log('Selected file:', file);
}}
/>
Features
- Validates file type and size
- Configurable accepted formats by category
- Simple API for handling selected file
API Reference
Prop | Type | Default |
---|---|---|
idName* | string | |
onFileChange* | function | |
formatType | "image" | "video" | "audio"... |
Confirm Button
A high level component to handle the AlertDialog component when you need to confirm an action.
Image Dropzone
Drag & drop or click to select an image, with preview support.
How is this guide?
Last updated on 10/17/2025