{/* Copyright 2023 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:react-aria-components';
import typesDocs from 'docs:@react-types/shared/src/events.d.ts';
import {PropTable, HeaderInfo, TypeLink, PageDescription, StateTable} from '@react-spectrum/docs';
import styles from '@react-spectrum/docs/src/docs.css';
import packageData from 'react-aria-components/package.json';
import Anatomy from '/packages/react-aria/docs/datepicker/daterangepicker-anatomy.svg';
import ChevronRight from '@spectrum-icons/workflow/ChevronRight';
import {Divider} from '@react-spectrum/divider';
import {ExampleCard} from '@react-spectrum/docs/src/ExampleCard';
import {Keyboard} from '@react-spectrum/text';
import Button from '@react-spectrum/docs/pages/assets/component-illustrations/ActionButton.svg';
import Link from '@react-spectrum/docs/pages/assets/component-illustrations/Link.svg';

---
category: Buttons
keywords: [filetrigger, input, aria]
type: component
---

# FileTrigger

<PageDescription>{docs.exports.FileTrigger.description}</PageDescription>

<HeaderInfo
  packageData={packageData}
  componentNames={['FileTrigger']} />

## Example

```tsx example
import {FileTrigger, Button} from 'react-aria-components';

function Example(){
  let [file, setFile] = React.useState(null);

  return (
    <>
      <FileTrigger
        onSelect={(e) => {
          let files = e ? Array.from(e) : [];
          let filenames = files.map((file) => file.name);
          setFile(filenames);
        }}>
        <Button>Select a file</Button>
      </FileTrigger>
      {file && file}
    </>
  )
}
```

```css hidden
@import "@react-aria/example-theme";
@import './Button.mdx' layer(button);
```

## Features

A file input can be created with an `<input type=“file”>` element, but this supports limited styling options and may not integrate well with the overall design of a website or application. To overcome this, `FileTrigger` extends the functionality of the standard file input element by working with a pressable child such as a `Button` to create accessible file inputs that can be styled as needed.

* **Customizable** – Works with any pressable React Aria or React Spectrum component, and custom components built with [usePress](https://react-spectrum.adobe.com/react-aria/usePress.html).

## Anatomy

A `FileTrigger` wraps around a pressable child such as a button, and includes a visually hidden input element that allows the user to select files from their device.

```tsx
import {FileTrigger, Button} from 'react-aria-components';

<FileTrigger>
  <Button />
</FileTrigger>
```

If a visual label is not provided on the pressable child, then an `aria-label` or `aria-labelledby` prop must be passed to identify the file trigger to assistive technology.

### Composed Components
A `FileTrigger` can use the following components, which may also be used standalone or reused in other components.

<section className={styles.cardGroup} data-size="small">

<ExampleCard
  url="Button.html"
  title="Button"
  description="A button allows a user to perform an action with a mouse, touch, or keyboard.">
  <Button />
</ExampleCard>

</section>

## Accepted file types

By default, the file trigger will accept any file type. To support only certain file types, pass an array of the [mime type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) of files via the `acceptedFileTypes` prop.

```tsx example
<FileTrigger acceptedFileTypes={['image/png']}>
  <Button>Select files</Button>
</FileTrigger>
```

## Multiple files

A file trigger can accept multiple files by passing the `allowsMultiple` property.

```tsx example
<FileTrigger allowsMultiple>
  <Button>Upload your files</Button>
</FileTrigger>
```

## Directory selection

To enable selecting directories instead of files, use the `acceptDirectory` property. 

This reflects the [webkitdirectory](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory) HTML attribute and allows users to select directories and their contents. Please note that support for this feature varies from browser to browser. 


```tsx example
function Example () {
  let [files, setFiles] = React.useState([]);

  return (
    <>
      <FileTrigger
        acceptDirectory
        onSelect={(e) => {
          if (e) {
            let fileList = [...e].map(file => file.webkitRelativePath !== "" ? file.webkitRelativePath : file.name);
            setFiles(fileList);
          }
        }} >
        <Button>Upload</Button>
      </FileTrigger>
      {files && <ul>
        {files.map((file, index) => (
          <li key={index}>{file}</li>
        ))}
      </ul>}
    </>
  );
}
```

## Media capture

To specify the media capture mechanism to capture media on the spot, pass `user` for the user-facing camera or `environment` for the outward-facing camera via the `defaultCamera` prop.

This behavior only works on mobile devices. On desktop devices, it will open the file system like normal. [Read more about capture](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/capture).

```tsx example
<FileTrigger defaultCamera="environment">
  <Button>Open Camera</Button>
</FileTrigger>
````

## Props

<PropTable component={docs.exports.FileTrigger} links={docs.links} />

## Styling

### FileTrigger

The `FileTrigger` component does not render any element of its own so it does not support styling.

### Button

A [Button](Button.html) can be targeted with the `.react-aria-Button` CSS selector, or by overriding with a custom `className`. It supports the following states:

<StateTable properties={docs.exports.ButtonRenderProps.properties} />
