# File input

Utility component that allows users to select a file from their device.

Tabs: [Guidelines](/components/web/file-input/file-input.guidelines.md) · [Code](/components/web/file-input/file-input.code.md)

## Basic usage

`FileInput` renders a visually hidden native file input over its children, so the children act as the visible trigger. Pass `maxFilesize` in bytes, which is the only required prop, and handle the selected file in `onChange`.

```tsx
import {Button, FileInput, ACCEPTED_IMAGE_TYPES} from '@pleo-io/telescope'

const ReceiptUpload = ({onUpload}: {onUpload: (file: File) => void}) => (
    <FileInput
        name="receipt"
        maxFilesize={10 * 1024 * 1024}
        accept={ACCEPTED_IMAGE_TYPES}
        onChange={onUpload}
    >
        <Button variant="primary">Browse</Button>
    </FileInput>
)
```

Children are optional. Without them, the file input fills the area of the wrapper and needs its own `aria-label`.

## Validation

`FileInput` checks each selected file before calling `onChange`:

- **Size**: files larger than `maxFilesize` are rejected. `onFileTooLarge` receives a message such as "Maximum file size is 10 MB.", and a negative toast explains the file size.
- **Type**: when `accept` is set, files whose MIME type is not listed are rejected with a negative toast. `ACCEPTED_IMAGE_TYPES` covers common image formats and PDF.
- **Count**: with `multipleFileSelection` and `maximumNumberOfFiles`, selecting more files than allowed shows a negative toast and does not call `onChange`.

The toasts are shown with `useToaster`, so the page needs a `ToasterProvider` and a `Toaster` in the tree. `Filedrop` uses the same validation for drag and drop, and is documented in the file drop guidelines.

## Localisation

The messages come from the `TelescopeProvider` translations under `FileInput`: `Or`, `MaxFileSize`, `MaxFileSizeMessage`, `FileTooLargeTitle`, `FileTooLarge`, `WrongFileTypeTitle`, `WrongFileType`, `TooManyFilesTitle` and `TooManyFiles`.

## Accessibility

- The native file input stays in the tab order, so keyboard users can open the file dialog with Enter or Space.
- When the file input wraps children, it is named after them. Pass `aria-label` to name it explicitly, which takes precedence.
- `isRequired`, `isInvalid` and `aria-describedby` are forwarded to the file input.
- The focus ring is shown on the children when the file input has keyboard focus.

## API reference

#### `accept`

Type: `string | undefined`

Default: -

No description available

#### `aria-describedby`

Type: `string | undefined`

Default: -

No description available

#### `aria-label`

Type: `string | undefined`

Default: -

No description available

#### `className`

Type: `string | undefined`

Default: -

No description available

#### `disabled`

Type: `boolean`

Default: -

No description available

#### `id`

Type: `string | undefined`

Default: -

No description available

#### `isInvalid`

Type: `boolean`

Default: -

No description available

#### `isRequired`

Type: `boolean`

Default: -

No description available

#### `maxFilesize` (required)

Type: `number`

Default: -

No description available

#### `maximumNumberOfFiles`

Type: `number | undefined`

Default: -

No description available

#### `multipleFileSelection`

Type: `boolean`

Default: -

No description available

#### `name`

Type: `string | undefined`

Default: -

No description available

#### `onChange`

Type: `((file: File) => void) | undefined`

##### Allowed values

- `(file: File) => void`

Default: -

No description available

#### `onFileTooLarge`

Type: `((message: string) => void) | undefined`

##### Allowed values

- `(message: string) => void`

Default: -

No description available

#### `onUploadButtonClick`

Type: `(() => void) | undefined`

##### Allowed values

- `() => void`

Default: -

No description available
