Skip to contentSkip to navigationSkip to topbar
Figma
Star

File Picker

Peer review pending

A File Picker is a form element used to upload files.

Version 4.1.0
Github
Component preview theme
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 />
)

Guidelines

Guidelines page anchor

About File Picker

About File Picker page anchor

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.(link takes you to an external page) 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 the id 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.
  • 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 the id of the help or error text.

File Uploader vs. File Picker

File Uploader vs. File Picker page anchor

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.
(information)

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.

Component preview theme
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 />
)
Component preview theme
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 />
)
Component preview theme
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.

Component preview theme
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:

RequirementsRecommended phrasing
File typeYou can upload [x], [x] and [x] file formats.
File sizeFiles 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:

StatusRecommended phrasing
Invalid file typeThis file is not an accepted format. You can upload [x], [x] and [x] file formats.
Exceeds file size limitThis 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 timeWe 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.
Component preview theme
<>
<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>
</>