alpha

FileTrigger

A FileTrigger allows a user to access the file system with either a Button or Link.

installyarn add react-aria-components
version1.0.0-alpha.5
usageimport {FileTrigger} from 'react-aria-components'

Example#


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

<FileTrigger>
  <Button>Select a file</Button>
</FileTrigger>
import {FileTrigger} from 'react-aria-components';
import {Button} from 'react-aria-components';

<FileTrigger>
  <Button>Select a file</Button>
</FileTrigger>
import {FileTrigger} from 'react-aria-components';
import {Button} from 'react-aria-components';

<FileTrigger>
  <Button>
    Select a file
  </Button>
</FileTrigger>
Show CSS
.react-aria-Button {
  --border-color: var(--spectrum-alias-border-color);
  --border-color-pressed: var(--spectrum-alias-border-color-down);
  --border-color-disabled: var(--spectrum-alias-border-color-disabled);
  --background-color: var(--spectrum-global-color-gray-50);
  --background-color-pressed: var(--spectrum-global-color-gray-100);
  --text-color: var(--spectrum-alias-text-color);
  --text-color-disabled: var(--spectrum-alias-text-color-disabled);
  --focus-ring-color: slateblue;

  color: var(--text-color);
  background: var(--background-color);
  border: 1px solid var(--border-color);
  border-radius: 4px;
  appearance: none;
  vertical-align: middle;
  font-size: 1.2rem;
  text-align: center;
  margin: 0;
  outline: none;
  padding: 4px 12px;

  &[data-pressed] {
    box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1);
    background: var(--background-color-pressed);
    border-color: var(--border-color-pressed);
  }

  &[data-focus-visible] {
    border-color: var(--focus-ring-color);
    box-shadow: 0 0 0 1px var(--focus-ring-color);
  }

  &:disabled {
    border-color: var(--border-color-disabled);
    color: var(--text-color-disabled);
  }
}

@media (forced-colors: active) {
  .react-aria-Button {
    forced-color-adjust: none;
    --border-color: ButtonBorder;
    --border-color-pressed: ButtonBorder;
    --border-color-disabled: GrayText;
    --background-color: ButtonFace;
    --background-color-pressed: ButtonFace;
    --text-color: ButtonText;
    --text-color-disabled: GrayText;
    --focus-ring-color: Highlight;
  }
}
.react-aria-Button {
  --border-color: var(--spectrum-alias-border-color);
  --border-color-pressed: var(--spectrum-alias-border-color-down);
  --border-color-disabled: var(--spectrum-alias-border-color-disabled);
  --background-color: var(--spectrum-global-color-gray-50);
  --background-color-pressed: var(--spectrum-global-color-gray-100);
  --text-color: var(--spectrum-alias-text-color);
  --text-color-disabled: var(--spectrum-alias-text-color-disabled);
  --focus-ring-color: slateblue;

  color: var(--text-color);
  background: var(--background-color);
  border: 1px solid var(--border-color);
  border-radius: 4px;
  appearance: none;
  vertical-align: middle;
  font-size: 1.2rem;
  text-align: center;
  margin: 0;
  outline: none;
  padding: 4px 12px;

  &[data-pressed] {
    box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1);
    background: var(--background-color-pressed);
    border-color: var(--border-color-pressed);
  }

  &[data-focus-visible] {
    border-color: var(--focus-ring-color);
    box-shadow: 0 0 0 1px var(--focus-ring-color);
  }

  &:disabled {
    border-color: var(--border-color-disabled);
    color: var(--text-color-disabled);
  }
}

@media (forced-colors: active) {
  .react-aria-Button {
    forced-color-adjust: none;
    --border-color: ButtonBorder;
    --border-color-pressed: ButtonBorder;
    --border-color-disabled: GrayText;
    --background-color: ButtonFace;
    --background-color-pressed: ButtonFace;
    --text-color: ButtonText;
    --text-color-disabled: GrayText;
    --focus-ring-color: Highlight;
  }
}
.react-aria-Button {
  --border-color: var(--spectrum-alias-border-color);
  --border-color-pressed: var(--spectrum-alias-border-color-down);
  --border-color-disabled: var(--spectrum-alias-border-color-disabled);
  --background-color: var(--spectrum-global-color-gray-50);
  --background-color-pressed: var(--spectrum-global-color-gray-100);
  --text-color: var(--spectrum-alias-text-color);
  --text-color-disabled: var(--spectrum-alias-text-color-disabled);
  --focus-ring-color: slateblue;

  color: var(--text-color);
  background: var(--background-color);
  border: 1px solid var(--border-color);
  border-radius: 4px;
  appearance: none;
  vertical-align: middle;
  font-size: 1.2rem;
  text-align: center;
  margin: 0;
  outline: none;
  padding: 4px 12px;

  &[data-pressed] {
    box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1);
    background: var(--background-color-pressed);
    border-color: var(--border-color-pressed);
  }

  &[data-focus-visible] {
    border-color: var(--focus-ring-color);
    box-shadow: 0 0 0 1px var(--focus-ring-color);
  }

  &:disabled {
    border-color: var(--border-color-disabled);
    color: var(--text-color-disabled);
  }
}

@media (forced-colors: active) {
  .react-aria-Button {
    forced-color-adjust: none;
    --border-color: ButtonBorder;
    --border-color-pressed: ButtonBorder;
    --border-color-disabled: GrayText;
    --background-color: ButtonFace;
    --background-color-pressed: ButtonFace;
    --text-color: ButtonText;
    --text-color-disabled: GrayText;
    --focus-ring-color: Highlight;
  }
}

Features#


Access to a computer’s file system can be created in HTML with the <input> element with a file type attribute. FileTrigger sets up the configuration between the input element and pressable child for a customizable file upload.

  • Flexible – Works with any pressable component, meaning that it is compatible with both React Aria Components and React Spectrum Components.

Anatomy#


A FileTrigger wraps around an input element and a pressable child, usually a link or button, that allows the user to upload files. The input element is not displayed and has no effect on the layout.

If a visual label is not provided (e.g. an icon only button/link, or image only link), then an aria-label or aria-labelledby prop must be passed to identify the link to assistive technology.

Composed Components#

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

Button
A button allows a user to perform an action with a mouse, touch, or keyboard.
Link
A link allows a user to navigate to another page.

Props#


NameTypeDefaultDescription
acceptedFileTypesArray<string>Specifies what mime type of files are allowed.
allowsMultiplebooleanWhether multiple files can be selected.
defaultCamera'user''environment'Specifies the use of a media capture mechanism to capture the media on the spot.
childrenReactNodeThe children of the component.
classNamestringThe CSS className for the element.
styleCSSPropertiesThe inline style for the element.
Events
NameTypeDefaultDescription
onChange( (files: FileListnull )) => voidHandler when a user selects a file.
Layout
NameTypeDefaultDescription
slotstringA slot name for the component. Slots allow the component to receive props from a parent component.
Accessibility
NameTypeDefaultDescription
aria-labelstringDefines a string value that labels the current element.
aria-labelledbystringIdentifies the element (or elements) that labels the current element.
aria-describedbystringIdentifies the element (or elements) that describes the object.
aria-detailsstringIdentifies the element (or elements) that provide a detailed, extended description for the object.

Styling#


React Aria components can be styled in many ways, including using CSS classes, inline styles, utility classes (e.g. Tailwind), CSS-in-JS (e.g. Styled Components), etc. By default, all components include a builtin className attribute which can be targeted using CSS selectors. These follow the react-aria-ComponentName naming convention.

.react-aria-FileTrigger {
  /* ... */
}
.react-aria-FileTrigger {
  /* ... */
}
.react-aria-FileTrigger {
  /* ... */
}

A custom className can also be specified on any component. This overrides the default className provided by React Aria with your own.

<FileTrigger className="my-filetrigger">
  {/* ... */}
</FileTrigger>
<FileTrigger className="my-filetrigger">
  {/* ... */}
</FileTrigger>
<FileTrigger className="my-filetrigger">
  {/* ... */}
</FileTrigger>

The states and selectors for each component used in a FileTrigger are documented below.

Button#

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

NameCSS SelectorDescription
isHovered[data-hovered]Whether the button is currently hovered with a mouse.
isPressed[data-pressed]Whether the button is currently in a pressed state.
isFocused:focusWhether the button is focused, either via a mouse or keyboard.
isFocusVisible[data-focus-visible]Whether the button is keyboard focused.
isDisabled:disabledWhether the button is disabled.

A Link can be targeted with the .react-aria-Link CSS selector, or by overriding with a custom className. It supports the following states:

NameCSS SelectorDescription
isCurrent[aria-current]Whether the link is the current item within a list.
isHovered[data-hovered]Whether the link is currently hovered with a mouse.
isPressed[data-pressed]Whether the link is currently in a pressed state.
isFocused:focusWhether the link is focused, either via a mouse or keyboard.
isFocusVisible[data-focus-visible]Whether the link is keyboard focused.
isDisabled[aria-disabled]Whether the link is disabled.

Usage#


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 of files via the acceptedFileTypes prop.

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

Multiple files#

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

<FileTrigger allowsMultiple>
  <Button>Upload your files</Button>
</FileTrigger>
<FileTrigger allowsMultiple>
  <Button>Upload your files</Button>
</FileTrigger>
<FileTrigger
  allowsMultiple
>
  <Button>
    Upload your files
  </Button>
</FileTrigger>

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 about capture.

<FileTrigger defaultCamera="environment">
  <Button>Open Camera</Button>
</FileTrigger>
<FileTrigger defaultCamera="environment">
  <Button>Open Camera</Button>
</FileTrigger>
<FileTrigger defaultCamera="environment">
  <Button>
    Open Camera
  </Button>
</FileTrigger>