@razorpay/blade-mcp
Version:
Model Context Protocol server for Blade
314 lines (254 loc) • 7.75 kB
Markdown
FileUpload
The FileUpload component is used to handle file attachments, including drag-and-drop interactions. It supports both single and multiple file uploads, with built-in validation for file types, sizes, and counts. The component can operate in controlled or uncontrolled modes, making it versatile for various scenarios from simple form inputs to complex upload workflows with progress indicators and previews.
- Custom text props (`actionButtonText`, `dropAreaText`) and dimensions (`height`, `width`) can only be used when `size` is "variable"
The browser throws an error if you don't follow the above rules. Make sure to only follow structure as given in the examples below. Fragments are also not allowed as children in these components.
## TypeScript Types
The following types represent the props that the FileUpload component accepts. These allow you to properly configure the component according to your needs.
```typescript
/**
* Props for the FileUpload component
*/
type FileUploadProps = {
/**
* The upload type - single or multiple files
* @default 'single'
*/
uploadType?: 'single' | 'multiple';
/**
* Label for the upload component
*/
label?: string;
/**
* Additional help text below the component
*/
helpText?: string;
/**
* Error text to display when validation fails
*/
errorText?: string;
/**
* Success text to display after successful upload
*/
successText?: string;
/**
* Accepted file types (e.g., '.jpg, .png, .pdf')
*/
accept?: string;
/**
* Maximum number of files allowed
*/
maxCount?: number;
/**
* Maximum size of each file in bytes
*/
maxSize?: number;
/**
* List of files (for controlled component)
*/
fileList?: BladeFileList;
/**
* Whether to disable the component
* @default false
*/
isDisabled?: boolean;
/**
* Whether the field is required
* @default false
*/
isRequired?: boolean;
/**
* Indicator for required/optional state
* @default 'none'
*/
necessityIndicator?: 'required' | 'optional' | 'none';
/**
* Callback when files are selected through the input or dropped
*/
onChange?: (info: { fileList: BladeFileList }) => void;
/**
* Callback when files are dropped on the dropzone
*/
onDrop?: (info: { fileList: BladeFileList }) => void;
/**
* Callback when the preview button is clicked
*/
onPreview?: (info: { file: BladeFile }) => void;
/**
* Callback when the remove button is clicked
*/
onRemove?: (info: { file: BladeFile; fileList: BladeFileList }) => void;
/**
* Callback when file upload is started
*/
onUpload?: (info: { file: BladeFile; fileList: BladeFileList }) => void;
/**
* Validation state of the component
* @default 'none'
*/
validationState?: 'error' | 'success' | 'none';
/**
* Size variant of the component
* @default 'medium'
*/
size?: 'small' | 'medium' | 'large';
/**
* Position of the label
* @default 'top'
*/
labelPosition?: 'top' | 'left';
} & StyledPropsBlade &
TestID;
/**
* File object for the FileUpload component
*/
type BladeFile = File & {
/**
* Unique identifier for the file
*/
id: string;
/**
* Status of the file upload
*/
status?: 'uploading' | 'success' | 'error';
/**
* Error text to display when upload fails
*/
errorText?: string;
/**
* Upload progress percentage (0-100)
*/
progress?: number;
/**
* Whether to show the file preview
*/
showPreview?: boolean;
/**
* URL for file preview (if available)
*/
previewUrl?: string;
};
/**
* List of BladeFile objects
*/
type BladeFileList = BladeFile[];
```
A basic example of single file upload integrated in a form with validation.
```tsx
import React, { useState } from 'react';
import { FileUpload, TextInput, Button, Box } from '@razorpay/blade/components';
const SingleFileUploadExample = () => {
const [name, setName] = useState('');
const [fileList, setFileList] = useState([]);
const [validationState, setValidationState] = useState('none');
const handleFileChange = ({ fileList }) => {
setFileList(fileList);
// Simple validation based on whether files are selected
if (fileList.length > 0) {
setValidationState('none');
} else {
setValidationState('none');
}
};
const handleSubmit = (e) => {
e.preventDefault();
alert(`Form submitted: Name: ${name}, File: ${fileList[0]?.name || 'None'}`);
};
return (
<Box padding="spacing.4">
<form onSubmit={handleSubmit}>
<TextInput
label="Name"
value={name}
onChange={({ value }) => setName(value)}
marginBottom="spacing.3"
isRequired
/>
<FileUpload
uploadType="single"
label="Profile Image"
helpText="Upload a profile picture (JPEG or PNG, max 2MB)"
accept=".jpg,.jpeg,.png"
maxSize={2 * 1024 * 1024}
isRequired
validationState={validationState}
errorText="Please upload a valid image file"
successText="File uploaded successfully"
fileList={fileList}
onChange={handleFileChange}
onRemove={() => {
setFileList([]);
setValidationState('none');
}}
marginBottom="spacing.3"
/>
<Button type="submit" isDisabled={!name || fileList.length === 0}>
Submit
</Button>
</form>
</Box>
);
};
export default SingleFileUploadExample;
```
An example showing how to use the multiple file upload functionality with progress indicators.
```tsx
import React, { useState } from 'react';
import { FileUpload, Box } from '@razorpay/blade/components';
import type { BladeFile, BladeFileList } from '@razorpay/blade/components';
const MultipleFileUploadExample = () => {
const [fileList, setFileList] = useState<BladeFileList>([]);
// Simulate file upload with progress
const simulateUpload = (file: BladeFile) => {
// Set initial uploading state
setFileList((prevList) =>
prevList.map((f) => (f.id === file.id ? { ...f, status: 'uploading', progress: 0 } : f)),
);
// Simulate progress with intervals
let progress = 0;
const interval = setInterval(() => {
progress += 10;
if (progress <= 100) {
// Update progress
setFileList((prevList) => prevList.map((f) => (f.id === file.id ? { ...f, progress } : f)));
} else {
// Complete the upload
clearInterval(interval);
setFileList((prevList) =>
prevList.map((f) => (f.id === file.id ? { ...f, status: 'success' } : f)),
);
}
}, 500);
};
const handleFileChange = ({ fileList: newFileList }) => {
// Find files that need to be uploaded (no status)
const filesToUpload = newFileList.filter((file) => !file.status);
// Update file list first
setFileList(newFileList);
// Start simulated upload for new files
filesToUpload.forEach(simulateUpload);
};
return (
<Box padding="spacing.4">
<FileUpload
uploadType="multiple"
label="Document Upload"
helpText="Upload up to 3 documents (PDF or DOC, max 5MB each)"
accept=".pdf,.doc,.docx"
maxCount={3}
maxSize={5 * 1024 * 1024}
fileList={fileList}
onChange={handleFileChange}
onRemove={({ file, fileList: updatedList }) => setFileList(updatedList)}
size="medium"
/>
</Box>
);
};
export default MultipleFileUploadExample;
```