File Uploader
A File Uploader is a form element used to upload multiple files.
A File Uploader is a form element that can trigger a file browser or accept drag-and-drop attachments. It can accept multiple attachments. The package consists of an associated label (FileUploaderLabel
), help text (FileUploaderInfo
), the dropzone (FileUploaderDropzone
), and cards for each uploaded attachment (FileUploaderItem
).
- The File Uploader should always use
FileUploaderLabel
to ensure it has an associated label. - The only tab stop in the File Uploader is the visually hidden input within the dropzone. The “Enter” and “Space” keys open the file selector.
- Use an accessible option for drag and drop implementation. See the Drag and drop section below for more guidance.
File Picker is another form component that, like File Uploader, allows the user to upload an attachment. There are a few key differences between the two components. File Uploader is more dynamic than File Picker – it allows multiple attachments and all of them are removable by the user. File Picker allows the user to upload only one file at a time with no way to clear the selection if a file has already been uploaded (besides selecting a new file). Because File Uploader has the ability to display loading and real-time error states, it’s a safer bet than File Picker for complex or potentially risky user flows.
Visually, File Picker is much more compact than the File Uploader, so it will fit snugly into your form UI, and won’t stand out as much as File Uploader, which takes up more vertical and horizontal space.
The File Uploader doesn’t come with drag and drop functionality built into the dropzone. When implementing drag and drop, please use an option that provides full keyboard, screen reader, and mouse capabilities. One highly recommended option is React Aria.
There are various drag and drop technologies that don’t include accessible solutions (like ReactDnD, for example) so please take the time to ensure the accessibility of your implementation. For more information on drag and drop accessibility, read the WCAG guidelines.
See the example below for an implementation that uses plain JavaScript.
Use a default File Uploader when your user needs to upload any number of files.
Use a disabled File Uploader to show users that they can’t interact with the component.
Use the loading state of FileUploaderItem so the user doesn’t move on before their action is complete or while the upload might still fail.
If an upload fails or doesn’t meet the acceptable criteria, use the File Uploader in its error state. The user will still be able to upload files. Be sure to also display the failed FileUploaderAttachmentItem in its error state so the user knows where to direct their attention. See composition notes below for guidance around error state copy.
Always include a Label with the File Uploader. Labels should clearly describe the file(s) being requested. They should be concise and descriptive, not instructional.
- Use File Uploader Info as help text to provide instruction if needed. For example, don't use "Upload an image in the form of a jpeg or png" as label text. Instead, use "Profile photo" as a label and "Upload an image file" as help text.
- Avoid articles ("a", "the") and punctuation. For example, use "SIM registration code" rather than "The SIM registration code".
File limitations should be communicated to the user up front to help avoid errors, like uploading an incompatible file type or one that’s too large.
Make each limitation its own sentence. Use positive framing to clearly communicate limitations to the user:
Requirements | Recommended phrasing |
---|---|
File type | You can upload [x], [x] and [x] file formats. |
File size | Files can be up to [file limit]. |
Number of files | You can upload up to [max #] files. |
Using the FileUploaderItem
with your File Uploader will allow users to receive instant feedback on progress of the file upload.
Truncate the file name in the middle if it’s too long.
Include description text that communicates when it’s uploading, when it’s successful, or when it fails (and why). If the delete action is destructive, consider using the Delete pattern for communicating the severity.
Requirements | Recommended phrasing |
---|---|
File uploading | Uploading... |
File size | Display the file size (e.g., 15 MB) |
In the case of an upload error, the card displaying the failed file should be in error state and include an error message that clearly communicates why it wasn’t uploaded. These error types may include invalid file type or file over the file size limit. We recommend the following phrasing:
Status | Recommended phrasing |
---|---|
Invalid file type | This file is not an accepted format. You can upload [x], [x] and [x] file formats. |
Exceeds file size limit | This file size is too big. You can upload files up to [file limit]. |
Network errors (internet connection dropped while uploading, request timeout, service is down) | Something went wrong with the network. Check your internet connection, then try again. |
Too many uploads in a certain amount of time | We couldn’t upload so many files so quickly. Try uploading files more slowly, or try again later. |
Generic (encountered an internal error) | Something went wrong. Try uploading your files again. |
Note: be sure to also put the File Uploader in error state and include an error message underneath the FileUploaderDropzone in the case of an upload failure. This will ensure the user notices the failed File Uploader Item, even if it’s at the bottom of a long list of attachments.
Do
Use a File Uploader when you need users to upload multiple files.
Don't
Use File Uploader for a single file upload if you’re tight on UI space – use File Picker instead.
Do
Always include a label with the File Uploader (use the FileUploaderLabel).
Don't
Use FileUploader without FileUploaderLabel.
Do
Be sure to communicate to your user when a file is still uploading using the loading state for the FileUploaderItem.
Don't
Let users remove uploaded files that may be destructive actions without a warning – instead use the Delete Pattern.
Do
Use descriptive help and error text to communicate the types of files that are allowed.
Don't
Display a FileUploaderItem in error state without putting the FileUploader itself into error state and providing a helpful error message.
yarn add @twilio-paste/file-uploader - or - yarn add @twilio-paste/core
import { FileUploader, FileUploaderLabel, FileUploaderHelpText, FileUploaderDropzone, FileUploaderDropzoneText,} from '@twilio-paste/core/file-uploader';const MyFileUploader = () => ( <FileUploader name="Default File Uploader"> <FileUploaderLabel>Upload files</FileUploaderLabel> <FileUploaderHelpText>Files can be up to 50 MB.</FileUploaderHelpText> <FileUploaderDropzone acceptedMimeTypes={['image/*', 'application/pdf']}> <FileUploaderDropzoneText>Click to browse or drag files here.</FileUploaderDropzoneText> </FileUploaderDropzone> </FileUploader>);
Accepts all valid attributes for HTML div elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploader | |
disabled? | boolean | Disables the FileUploader | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER' |
id? | string | The id of the FileUploader. Used to create ids for the elements within the FileUploader. | |
name | string | The name for the input within the FileUploader | |
required? | boolean | If the FileUploader is required. |
Accepts all attributes for HTML input elements.
Prop | Type | Description | Default |
---|---|---|---|
acceptedMimeTypes? | string[] | The allowed mime types for the input. It is convereted to a string and passed to the accept attribute. | |
children? | React.ReactNode | The contents of the FileUploaderDropzone | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_DROPZONE' |
onDragStart? | (event: React.DragEvent<HTMLLabelElement>) => void | A function that runs on drag leave on the label that wraps the FileUploaderDropzone | |
onDragEnd? | (event: React.DragEvent<HTMLLabelElement>) => void | A function that runs on drag leave on the label that wraps the FileUploaderDropzone | |
onDragEnter? | (event: React.DragEvent<HTMLLabelElement>) => void | A function that runs on drag leave on the label that wraps the FileUploaderDropzone | |
onDragLeave? | (event: React.DragEvent<HTMLLabelElement>) => void | A function that runs on drag leave on the label that wraps the FileUploaderDropzone | |
onDragOver? | (event: React.DragEvent<HTMLLabelElement>) => void | A function that runs on drag over on the label that wraps the FileUploaderDropzone | |
onDrop? | (event: React.DragEvent<HTMLLabelElement>) => void | A function that runs on drop on the label that wraps the FileUploaderDropzone | |
onInputChange? | (event: React.ChangeEvent<HTMLInputElement>) => void | A function that runs when the input within the Dropzone is changed |
Accepts all attributes for HTML div elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploaderDropzoneText | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_DROPZONE_TEXT' |
Accepts all attributes for HTML div elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploaderErrorText | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_ERROR_TEXT' |
Accepts all attributes for HTML div elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploaderHelpText | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_HELP_TEXT' |
Accepts all valid attributes for HTML li elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploaderItem | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_ITEM' |
fileIcon? | React.ReactNode | The icon displayed when it is not loading or error variant. | |
i18nButtonText? | string | The hidden text for the dismiss button | 'Remove file' |
i18nErrorText? | string | The hidden text for the error icon | '(error)' |
i18nLoadingText? | string | The hidden text for the loading spinner | '(loading)' |
variant? | 'default' \| 'loading' \| 'error' | The variant of FileUploaderItem | 'default' |
Accepts all attributes for HTML div elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploaderItemDescription | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_ITEM_DESCRIPTION' |
Accepts all attributes for HTML ul elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploaderItemsList | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_ITEMS_LIST' |
Accepts all attributes for HTML div elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploaderItemTitle | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_ITEM_TITLE' |
Accepts all attributes for HTML label elements.
Prop | Type | Description | Default |
---|---|---|---|
children? | React.ReactNode | The contents of the FileUploaderUploaderLabel | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider. | 'FILE_UPLOADER_LABEL' |