---
title: File input (React) - USWDS + Tailwind
description: Let people attach one or more files with a file input. See examples
  for accepted file types and multiple uploads.
---

# File input

Let people attach one or more files with a file input. See examples for accepted file types and multiple uploads.

## Examples

### Default

```tsx
import { FileInput } from '@uswds-tailwind/react'

export default function FileInputDemo() {
  return (
    <FileInput.Root>
      <FileInput.Label>Input accepts a single file</FileInput.Label>
      <FileInput.SrStatus />
      <FileInput.Dropzone>
        <FileInput.ItemGroup>
          {({ acceptedFiles }) => (
            <>
              <FileInput.PreviewHeader>
                <FileInput.PreviewTitle />
                <FileInput.ChangeTrigger />
              </FileInput.PreviewHeader>
              {acceptedFiles.map(file => (
                <FileInput.Item key={file.name} file={file}>
                  <FileInput.ItemPreview>
                    {file.type.startsWith('image/')
                      ? <FileInput.ItemPreviewImage />
                      : <FileInput.ItemPreviewIcon />}
                    <FileInput.ItemName />
                  </FileInput.ItemPreview>
                </FileInput.Item>
              ))}
            </>
          )}
        </FileInput.ItemGroup>
        <FileInput.Instructions />
        <FileInput.ErrorMessage>This is not a valid file type.</FileInput.ErrorMessage>
        <FileInput.Input />
      </FileInput.Dropzone>
    </FileInput.Root>
  )
}
```

### Specific File Types

```tsx
import { FileInput } from '@uswds-tailwind/react'

export default function FileInputSpecificTypesDemo() {
  return (
    <FileInput.Root accept=".pdf,.txt">
      <FileInput.Label>Input accepts only specific file types</FileInput.Label>
      <div id="file-input-types-hint" className="text-gray-50">Select PDF or TXT files</div>
      <FileInput.SrStatus />
      <FileInput.Dropzone>
        <FileInput.ItemGroup>
          {({ acceptedFiles }) => (
            <>
              <FileInput.PreviewHeader>
                <FileInput.PreviewTitle />
                <FileInput.ChangeTrigger />
              </FileInput.PreviewHeader>
              {acceptedFiles.map(file => (
                <FileInput.Item key={file.name} file={file}>
                  <FileInput.ItemPreview>
                    {file.type.startsWith('image/')
                      ? <FileInput.ItemPreviewImage />
                      : <FileInput.ItemPreviewIcon />}
                    <FileInput.ItemName />
                  </FileInput.ItemPreview>
                </FileInput.Item>
              ))}
            </>
          )}
        </FileInput.ItemGroup>
        <FileInput.Instructions />
        <FileInput.ErrorMessage>This is not a valid file type.</FileInput.ErrorMessage>
        <FileInput.Input aria-describedby="file-input-types-hint" />
      </FileInput.Dropzone>
    </FileInput.Root>
  )
}
```

### Accept Multiple Files

```tsx
import { FileInput } from '@uswds-tailwind/react'

export default function FileInputMultipleDemo() {
  return (
    <FileInput.Root multiple>
      <FileInput.Label>Input accepts multiple files</FileInput.Label>
      <FileInput.SrStatus />
      <FileInput.Dropzone>
        <FileInput.ItemGroup>
          {({ acceptedFiles }) => (
            <>
              <FileInput.PreviewHeader>
                <FileInput.PreviewTitle />
                <FileInput.ChangeTrigger />
              </FileInput.PreviewHeader>
              {acceptedFiles.map(file => (
                <FileInput.Item key={file.name} file={file}>
                  <FileInput.ItemPreview>
                    {file.type.startsWith('image/')
                      ? <FileInput.ItemPreviewImage />
                      : <FileInput.ItemPreviewIcon />}
                    <FileInput.ItemName />
                  </FileInput.ItemPreview>
                </FileInput.Item>
              ))}
            </>
          )}
        </FileInput.ItemGroup>
        <FileInput.Instructions />
        <FileInput.ErrorMessage>This is not a valid file type.</FileInput.ErrorMessage>
        <FileInput.Input />
      </FileInput.Dropzone>
    </FileInput.Root>
  )
}
```

## Component API

Root connects the file control, dropzone, instructions, error, and preview parts.

### Root `<div>`

Owns accepted files and rejects the entire selection if any file fails accept validation.

| Prop | Type | Default | Description |
| - | - | - | - |
| `accept` | `string` | `—` | Accepted file types. |
| `multiple` | `boolean` | `false` | Allows more than one file. |
| `disabled` | `boolean` | `false` | Disables selection. |
| `errorText` | `string` | `"Error: This is not a valid file type."` | Message for rejected files. Defaults to "Error: This is not a valid file type." |
| `ariaDisabled` | `boolean` | `false` | Marks the input disabled for assistive technology while keeping it operable. |
| `ids` | `{ root?: string; label?: string; dropzone?: string; box?: string; input?: string; instructions?: string; itemGroup?: string; previewHeading?: string; srStatus?: string; errorText?: string }` | `—` | Overrides generated part IDs. Use Root IDs when a label or external control needs a stable input or trigger target. |

| Attribute | Value | Purpose |
| - | - | - |
| `data-disabled` | `Present when disabled` | Style the disabled state. |

### Label `<label>`

Names the file input.

| Attribute | Value | Purpose |
| - | - | - |
| `data-disabled` | `Present when disabled` | Style the disabled state. |

### SrStatus `<div>`

Announces file selection status after a one-second delay. Initially disabled inputs hide this region.

### Dropzone `<div>`

Displays the drag and drop target.

| Attribute | Value | Purpose |
| - | - | - |
| `data-invalid` | `Present when invalid` | Style the error state. |
| `data-dragging` | `Present while dragging files` | Styles drag feedback. |

### Input `<input>`

Native file input over the dropzone. Pass native name, required, and onChange props here.

### Instructions `<div>`

Explains how to choose files; children replace the default text.

### ErrorMessage `<div>`

Displays rejected-file feedback.

### ItemGroup `<div>`

Contains previews of accepted files.

| Prop | Type | Description |
| - | - | - |
| `children` | `ReactNode \| ({ acceptedFiles: File[] }) => ReactNode` | Can render from accepted files. |

| Attribute | Value | Purpose |
| - | - | - |
| `data-valid` | `Present when files are selected` | Style the populated preview. |

### PreviewHeader `<div>`

Groups the preview heading and change action.

### PreviewTitle `<div>`

Displays the selected-file heading.

### Item `<div>`

Provides one file to the preview parts.

| Prop | Type | Description |
| - | - | - |
| `file` | `File (required)` | The file represented by this item. |

### ItemPreview `<div>`

Arranges the preview icon, image, and file name.

### ItemPreviewIcon `<div>`

Displays a file-type icon.

| Attribute | Value | Purpose |
| - | - | - |
| `data-type` | `pdf \| word \| excel \| video \| generic \| image` | Styles the file icon. |

### ItemPreviewImage `<img>`

Displays an image thumbnail when available.

### ItemName `<div>`

Displays the file name by default.

### ChangeTrigger `<span>`

Displays decorative change-files text. The overlaid native Input opens the file picker.
