File Picker
A File Picker is a form element used to upload files.
const FilePickerExample = () => {const id = useUID();const helpText = useUID();const [files, setFiles] = React.useState([])return (<><Label htmlFor={id}>Profile picture</Label><FilePicker id={id} accept="image/*" aria-describedby={helpText} onChange={(evt)=>{setFiles(evt.currentTarget.files)}}><FilePickerButton variant="secondary">Upload a file</FilePickerButton></FilePicker><HelpText id={helpText}>Please upload an image</HelpText></>);}render(<FilePickerExample />)
Use a File Picker when users need to upload a document in a form flow. The File Picker allows any type of file by default, but the desired file type can be specified using the accept
prop. This is a native HTML file picker, <input type="file" />
, so there's currently no drag-and-drop or multiple attachments functionality. Read more about the native file picker on MDN. The input is hidden visually, but still appears in the DOM, so that we're able to apply custom styles in an accessible way.
- Include a visible Label on all form fields.
- Each label must use the
htmlFor
prop that equals theid
of the associated input. - Provide clear identification of required fields in the label or at the start of a form. If you use the required field indicator, include the form key at the start of the form.
- Use the
required
prop to programatically indicate they are required to browsers.
- Use the
- Include inline error text with the error icon on any field that errors to make it visually clear that the field changed. You can also use the "error" variant of Help Text.
- If the File Picker has associated help text or error text, include the
aria-describedby
prop on the File Picker. This should match theid
of the help or error text.
File Uploader is another form component that, like File Picker, 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 Picker component should include the base File Picker, along with supporting elements to compose an input field that gives users the context they need to successfully complete it.
- Label — A label should be included for every form field and provide a short title for its associated input.
- Required field indicator — In a form where there are fewer or as many required fields as optional, use a required indicator to show users which fields are required to be filled out.
- Help text — Text that's placed below the field to help users prevent an error and describe what makes the form field successful. If you're using the
accept
prop, specify the file type using Help Text.
Accessibility insight
Make sure to connect the Label
to the File Picker
. This is done with the htmlFor
prop on the label, and the id
prop on the File Picker. Those two need to match.
If the File Picker has any associated help text, it should also use the aria-describedby
prop that equals the id
of the help text. This ensures screen readers know the help text ties directly to the File Picker.
const FilePickerExample = () => {const id = useUID();const helpText = useUID();const [files, setFiles] = React.useState([])return (<><Label htmlFor={id}>Profile picture</Label><FilePicker id={id} accept="image/*" aria-describedby={helpText} onChange={(evt)=>{setFiles(evt.currentTarget.files)}}><FilePickerButton variant="secondary">Upload a file</FilePickerButton></FilePicker><HelpText id={helpText}>Please upload an image</HelpText></>);}render(<FilePickerExample />)
const FilePickerExample = () => {const id = useUID();const [files, setFiles] = React.useState([])return (<><Label disabled htmlFor={id}>Receipt to expense</Label><FilePicker id={id} accept=".pdf" disabled onChange={(evt)=>{setFiles(evt.currentTarget.files)}}><FilePickerButton variant="secondary">Upload a file</FilePickerButton></FilePicker></>);}render(<FilePickerExample />)
const FilePickerExample = () => {const id = useUID();const helpText = useUID();const [files, setFiles] = React.useState([])return (<><Label htmlFor={id} required>Proof of employment</Label><FilePicker id={id} aria-describedby={helpText} required onChange={(evt)=>{setFiles(evt.currentTarget.files)}}><FilePickerButton variant="secondary">Upload a file</FilePickerButton></FilePicker><HelpText id={helpText}>Acceptable formats include W2, I9, or latest pay stub.</HelpText></>);}render(<FilePickerExample />)
To internationalize a File Picker, simply pass the i18nNoSelectionText
prop with the translated string. Because the FilePickerButton
is compositional, you already pass the button text as children.
const FilePickerExample = () => {const id = useUID();return (<><Label htmlFor={id}>Foto de perfil</Label><FilePicker id={id} accept="image/*" i18nNoSelectionText="Ningún archivo seleccionado"><FilePickerButton variant="secondary">Seleccione un archivo</FilePickerButton></FilePicker></>);}render(<FilePickerExample />)
Labels should clearly describe the object being requested. They should be concise and descriptive, not instructional. To do this:
- Use 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]. |
Validate form fields on form submission.
Validating a form field when the user leaves the current field (on blur) can be helpful to check for syntax errors. However, this can be frustrating to users who tab through controls to navigate a page, and to screen reader users, who might not be able to detect that an error occurred on blur.
Don't prevent form submission by disabling the submit button. A disabled button cannot be detected by assistive technologies. Use error messages to explain what information is missing or incorrect.
Use Help Text to show inline error text that explains how to fix an error.
Help text should have enough information to help users prevent errors. If HelpText
is already on a form field, change it to variant=“error”
and add error copy before the original help text copy.
Recommended phrasing for File Picker error copy:
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. |
<><Label htmlFor='error'>Profile picture</Label><FilePicker id='error' accept="image/*" aria-describedby='error-ht'><FilePickerButton variant="secondary">Upload a file</FilePickerButton></FilePicker><HelpText variant="error" id='error-ht'>This file is not an accepted format. You can upload .png and .jpeg file formats.</HelpText></>