Live code
Storybook
Usage
FileUploader
The FileUploader implementation is used to select files either by selecting files from the device itself, or by drag and drop if the device supports it. React package extends web package.
Usage
Basic
const { fileQueue, addToQueue, clearQueue, onDismiss } = useFileQueue();
<FileUploader
id="fileUploaderExample"
onDismiss={onDismiss}
fileQueue={fileQueue}
addToQueue={addToQueue}
clearQueue={clearQueue}
>
<FileUploaderInput
id="fileUploaderExampleInput"
name="attachments"
label="Label"
linkText="Upload your file(s)"
labelText="or drag and drop here"
helperText="Max file size is 10 MB"
/>
<FileUploaderList
id="fileUploaderExampleList"
label="Attachments"
inputName="attachments"
attachmentComponent={(props) => <FileUploaderAttachment key={props.id} {...props} />}
/>
</FileUploader>;
Multiple and Queue Limit
const { fileQueue, addToQueue, clearQueue, onDismiss } = useFileQueue();
<FileUploader
id="fileUploaderExample"
onDismiss={onDismiss}
fileQueue={fileQueue}
addToQueue={addToQueue}
clearQueue={clearQueue}
>
<FileUploaderInput
id="fileUploaderExampleInput"
name="attachments"
label="Label"
linkText="Upload your file(s)"
labelText="or drag and drop here"
helperText="Max file size is 10 MB"
validationText="Validation message"
maxUploadedFiles={5}
isMultiple
/>
<FileUploaderList
id="fileUploaderExampleList"
label="Attachments"
inputName="attachments"
attachmentComponent={(props) => <FileUploaderAttachment key={props.id} {...props} />}
/>
</FileUploader>;
List with image previews
<FileUploaderList
id="fileUploaderExampleList"
label="Attachments"
inputName="attachments"
attachmentComponent={attachmentComponent}
hasImagePreview
/>
Editable Attachment
<FileUploaderAttachment key={id} id={id} onEdit={(event, file) => console.log(event, file)} {...props} />
Validation State
<FileUploader>
<FileUploaderInput isRequired validationState="success" validationText="Validation message" />
<FileUploaderList />
</FileUploader>
<FileUploader>
<FileUploaderInput isRequired validationState="success" validationText={["Validation message", "Second validation message"]} />
<FileUploaderList />
</FileUploader>
Input behavior when the queue is filled
FileUploaderInput will disappear or disable after reaching the limit for files in the queue.
<FileUploader>
<FileUploaderInput
isRequired
validationState="success"
validationText="Validation message"
maxUploadedFiles={3}
queueLimitBehavior="hide"
/>
<FileUploaderList />
</FileUploader>
Error Callback
<FileUploader>
<FileUploaderInput onError={(error) => console.error('My error log', error)} />
<FileUploaderList />
</FileUploader>
Uncontrolled
<UncontrolledFileUploader
attachmentComponent={(props) => <FileUploaderAttachment key={props.id} {...props} />}
id="fileUploaderUncontrolled"
inputId="fileUploaderUncontrolledInput"
inputName="attachments"
inputProps={{
accept: '*',
}}
listId="fileUploaderUncontrolledList"
listProps={{
label: 'Attachments',
}}
onInputError={(error) => console.error('My error log', error)}
/>
Controlled Example with Form Submit
const [submitting, setSubmitting] = useState < boolean > false;
const [submitted, setSubmitted] = useState < boolean > false;
const [validationText, setValidationText] = (useState < string) | (undefined > undefined);
const [validationState, setValidationState] = (useState < ValidationState) | (undefined > undefined);
const { fileQueue, addToQueue, clearQueue, onDismiss } = useFileQueue();
const submitHandler = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const master = new Map(fileQueue);
setSubmitting(true);
// Callback after submit
setSubmitting(false);
setSubmitted(true);
clearQueue();
};
const errorHandler = (error: string | Error) => {
setValidationState('error');
setValidationText(String(error));
setTimeout(() => {
setValidationState(undefined);
setValidationText(undefined);
}, 5000);
};
const resetStateHandler = () => {
setValidationState(undefined);
setValidationText(undefined);
setSubmitted(false);
};
<form onSubmit={submitHandler}>
<FileUploader
id="fileUploaderFormExample"
onDismiss={onDismiss}
fileQueue={fileQueue}
addToQueue={addToQueue}
clearQueue={clearQueue}
>
<FileUploaderInput
id="fileUploaderFormExampleInput"
name="attachments"
label="Label"
linkText="Upload your file(s)"
labelText="or drag and drop here"
helperText="Max file size is 10 MB"
validationText={validationText}
validationState={validationState}
maxUploadedFiles={2}
onError={errorHandler}
isMultiple
/>
<FileUploaderList
id="fileUploaderFormExampleList"
label="Attachments"
inputName="attachments"
attachmentComponent={(props) => <FileUploaderAttachment key={props.id} {...props} />}
/>
</FileUploader>
<div style={{ paddingTop: '1rem' }}>
<Button type="submit" color="primary" isDisabled={submitting || submitted}>
Submit form
</Button>
{submitted && (
<Button color="secondary" onClick={resetStateHandler} UNSAFE_style={{ marginLeft: '.5rem' }}>
Reset state
</Button>
)}
</div>
</form>;
Uncontrolled Example with Form Submit
const [submitting, setSubmitting] = useState < boolean > false;
const [submitted, setSubmitted] = useState < boolean > false;
const [validationText, setValidationText] = (useState < string) | (undefined > undefined);
const [validationState, setValidationState] = (useState < ValidationState) | (undefined > undefined);
const [queue, setQueue] = useState < FileQueueMapType > new Map();
const attachmentComponent = ({ id, ...props }: SpiritFileUploaderAttachmentProps) => (
<FileUploaderAttachment key={id} id={id} {...props} />
);
const changeHandler = (fileQueue: FileQueueMapType) => {
setQueue(fileQueue);
};
const submitHandler = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const master = new Map(queue);
setSubmitting(true);
// Callback after submit
setSubmitting(false);
setSubmitted(true);
queue.clear();
setQueue(new Map(queue));
};
const errorHandler = (error: string | Error) => {
setValidationState('error');
setValidationText(String(error));
setTimeout(() => {
setValidationState(undefined);
setValidationText(undefined);
}, 5000);
};
const resetStateHandler = () => {
setValidationState(undefined);
setValidationText(undefined);
setSubmitted(false);
};
<form onSubmit={submitHandler}>
<UncontrolledFileUploader
attachmentComponent={attachmentComponent}
id="fileUploaderUncontrolled"
inputId="fileUploaderUncontrolledInput"
inputName="attachments"
inputLabel="Input label"
listId="fileUploaderUncontrolledList"
linkText="Upload your file(s)"
labelText="or drag and drop here"
helperText="Max file size is 10 MB"
onChange={changeHandler}
onInputError={errorHandler}
validationState={validationState}
validationText={validationText}
isMultiple
/>
<div style={{ paddingTop: '1rem' }}>
<Button type="submit" color="primary" isDisabled={submitting || submitted}>
Submit form to show data
</Button>
{submitted && (
<Button color="secondary" onClick={resetStateHandler} UNSAFE_style={{ marginLeft: '.5rem' }}>
Reset state
</Button>
)}
</div>
</form>;
Passing additional metadata
When you need to send additional data along with the image you can do it with the meta argument on addToQueue and updateQueue callbacks. If any data in meta option will be present, the FileUploader adds an additional hidden input with JSON stringified data to the form. The identification of this input (name) will be the name of the file. Thus you can pass to the server any additional text data you need.
const customAddToQueue = (key: string, file: File) => {
// passing additional data using the `meta` argument
return addToQueue(key, file, { fileDescription: 'custom file description' });
};
const customUpdate = (_event: MouseEvent, file: File) => {
return updateQueue(file.name, file, { fileDescription: 'changing the custom description' });
};
// …
<FileUploader
addToQueue={customAddToQueue}
// …
updateQueue={updateQueue}
>
// …
</FileUploader>;
// …
Updating Image Preview with cropped image
When you are using FileUploader with some kind of image cropper you want to also update the image preview on FileUploaderAttachment when image changes. You can do this by passing a specific object in shape of coordinates ({ x: number, y: number, cropWidth: number, cropHeight: number, originalWidth: number, originalHeight: number }) to the meta argument. Then the coordinates will be applied to the preview image in the attachment.
// …
const customUpdate = (_event: MouseEvent, file: File) => {
const meta = { x: 30, y: 30, cropWidth: 150, cropHeight: 150, originalWidth: 560, originalHeight: 330 };
return updateQueue(file.name, file, meta);
};
// …
FileUploader Props
Name | Type | Default | Required | Description |
---|---|---|---|---|
addToQueue | (key: string, file: File, meta?: FileMetadata) => FileQueueMapType | — | ✔ | Callback to add an item to the queue |
clearQueue | () => void | — | ✔ | Callback to clear the queue |
errorMessages.errorFileDuplicity | string | — | ✕ | Translation for the error message: Duplicate file in queue |
errorMessages.errorMaxFileSize | string | — | ✕ | Translation for the error message: Maximum file size |
errorMessages.errorMaxUploadedFiles | string | — | ✕ | Translation for the error message: Maximum number of uploaded files |
fileQueue | FileQueueMapType | — | ✔ | Queue of items to upload |
findInQueue | (key: string) => FileQueueMapType | — | ✔ | A callback to find a particular item in the queue |
id | string | — | ✔ | FileUploader id |
isFluid | bool | — | ✕ | When the field is supposed to be fluid |
onDismiss | (key: string) => FileQueueMapType | — | ✔ | A callback to delete a particular item from the queue |
updateQueue | (key: string, file: File, meta?: FileMetadata) => FileQueueMapType | — | ✔ | A callback to update a particular item in the queue |
The rest of the properties are created from the default <div> element. More about the element
On top of the API options, the components accept additional attributes. If you need more control over the styling of a component, you can use style props and escape hatches.
FileUploaderInput Props
Name | Type | Default | Required | Description |
---|---|---|---|---|
accept | string | — | ✕ | The accept attribute takes as its value a comma-separated list of one or more file types, or unique file type specifiers, describing which file types to allow. |
dropZoneRef | MutableRefObject<HTMLDivElement> | — | ✕ | Drop zone element reference |
helperText | string | — | ✕ | Custom helper text |
iconName | string | upload | ✕ | Icon used in the drop zone |
id | string | — | ✔ | FileUploaderInput id |
inputRef | MutableRefObject<HTMLInputElement> | — | ✕ | Input element reference |
isDisabled | bool | — | ✕ | Whether is field disabled |
isLabelHidden | bool | — | ✕ | Whether is input label hidden |
isMultiple | bool | — | ✕ | When multiple files can be selected at once |
isRequired | bool | — | ✕ | Whether is field required |
label | string | — | ✕ | Field label |
labelText | string | — | ✕ | Label for input in Drop zone |
linkText | string | — | ✕ | Link text in input in Drop zone |
maxFileSize | number | 1000000 | ✕ | The maximum size of the uploaded file in bytes |
maxUploadedFiles | number | 10 | ✕ | Maximum file upload queue size |
name | string | — | ✔ | Field name, will be used for each attachment in the queue |
onError | FileUploaderErrorCallbackType | — | ✕ | Callback on error condition |
queueLimitBehavior | [hide | disable | none] | none | ✕ | Input behavior when the file queue is filled |
validationState | ValidationState | — | ✕ | Validation state |
validationText | [string | string[]] | — | ✕ | Validation status text |
The rest of the properties are created from the default <input> element. More about the element
On top of the API options, the components accept additional attributes. If you need more control over the styling of a component, you can use style props and escape hatches.
FileUploaderList Props
Name | Type | Default | Required | Description |
---|---|---|---|---|
attachmentComponent | string | — | ✔ | A component for rendering a single attachment |
hasImagePreview | bool | false | ✕ | Show image preview in the list |
id | string | — | ✔ | FileUploaderList id |
inputName | string | — | ✔ | The name of the input field |
label | string | — | ✕ | Label for the list |
The rest of the properties are created from the default <ul> element. More about the element
On top of the API options, the components accept additional attributes. If you need more control over the styling of a component, you can use style props and escape hatches.
FileUploaderAttachment Props
Name | Type | Default | Required | Description |
---|---|---|---|---|
buttonLabel | string | Remove | ✕ | DEPRECATED in favor of removeText; Dismiss button label |
editButtonLabel | string | Edit | ✕ | DEPRECATED in favor of editText; Edit button label |
editText | string | Edit | ✕ | Edit button label |
file | File | — | ✔ | Attachment file object |
hasImagePreview | bool | false | ✕ | Show image preview |
iconName | string | file | ✕ | Icon shown along the file |
id | string | — | ✔ | FileUploaderAttachment id |
imageObjectFit | [cover | contain] | cover | ✕ | Defines FileUploaderAttachment image fit in container |
label | string | — | ✔ | File name |
name | string | — | ✔ | Input field name |
onDismiss | (key: string) => FileQueueMapType | — | ✔ | Callback to delete an item from the queue |
onEdit | (event: Event, file: File) => void | — | ✕ | Show and add function to edit button |
onError | FileUploaderErrorCallbackType | — | ✕ | Callback on error condition |
removeText | string | Remove | ✕ | Dismiss button label |
The rest of the properties are created from the default <li> element. More about the element
On top of the API options, the components accept additional attributes. If you need more control over the styling of a component, you can use style props and escape hatches.
AttachmentActionButton Props
Name | Type | Default | Required | Description |
---|---|---|---|---|
onClick | MouseEventHandler<HTMLButtonElement> | — | ✕ | Button click handler |
The rest of the properties are created from the default <button> element. More about the element
On top of the API options, the components accept additional attributes. If you need more control over the styling of a component, you can use style props and escape hatches.
AttachmentDismissButton Props
Name | Type | Default | Required | Description |
---|---|---|---|---|
onClick | MouseEventHandler<HTMLButtonElement> | — | ✕ | Button click handler |
The rest of the properties are created from the default <button> element. More about the element
On top of the API options, the components accept additional attributes. If you need more control over the styling of a component, you can use style props and escape hatches.
UncontrolledFileUploader Props
The uncontrolled variant contains the composition <FileUploaderInput> and <FileUploaderList> and a collection of props selected above for easier implementation. Other props are passed via inputProps and listProps. UncontrolledFileUploaderBaseProps extends FileUploaderBaseProps.
Name | Type | Default | Required | Description |
---|---|---|---|---|
attachmentComponent | string | — | ✔ | A component for rendering a single attachment |
helperText | string | — | ✕ | Custom helper text |
iconName | string | upload | ✔ | Icon used in the UncontrolledFileUploader drop zone |
id | string | — | ✔ | UncontrolledFileUploader id |
inputId | string | — | ✔ | FileUploaderInput id |
inputLabel | string | — | ✔ | FileUploaderInput label |
inputName | string | — | ✔ | FileUploaderInput name |
inputProps | Partial<FileUploaderInputBaseProps> | — | ✕ | Rest of FileUploaderInput props |
isDisabled | bool | — | ✕ | Whether is field disabled |
isFluid | bool | — | ✕ | When the field is supposed to be fluid |
isLabelHidden | bool | — | ✕ | Whether is input label hidden |
isMultiple | bool | — | ✕ | When multiple files can be selected at once |
isRequired | bool | — | ✕ | Whether is field required |
labelText | string | — | ✕ | Label for input in Drop zone |
linkText | string | — | ✕ | Link text in input in Drop zone |
listId | string | — | ✔ | FileUploaderList id |
listProps | Partial<FileUploaderListBaseProps> | — | ✕ | Rest of FileUploaderList props |
maxFileSize | number | 1000000 | ✕ | The maximum size of the uploaded file in bytes |
maxUploadedFiles | number | 10 | ✕ | Maximum file upload queue size |
onChange | (fileQueue: FileQueueMapType) => void | — | ✕ | Callback on change in fileQueue |
onInputError | FileUploaderErrorCallbackType | — | ✕ | Callback on error condition |
queueLimitBehavior | [hide | disable | none] | none | ✕ | Input behavior when the file queue is filled |
validationState | ValidationState | — | ✕ | Validation state |
validationText | [string | string[]] | — | ✕ | Validation status text |
On top of the API options, the components accept additional attributes. If you need more control over the styling of a component, you can use style props and escape hatches.
For detailed information see FileUploader component.