Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add directory support for FileTrigger #5444

Merged
merged 6 commits into from Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/react-aria-components/docs/FileTrigger.mdx
Expand Up @@ -120,6 +120,18 @@ A file trigger can accept multiple files by passsing the `allowsMultiple` proper
</FileTrigger>
```

## Directory selection

To enable selecting directories instead of files, use the `directory` 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.

```tsx example
<FileTrigger directory>
<Button>Select a directory</Button>
</FileTrigger>
```

## 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.
Expand Down
14 changes: 10 additions & 4 deletions packages/react-aria-components/src/FileTrigger.tsx
Expand Up @@ -35,17 +35,21 @@ export interface FileTriggerProps {
/**
* The children of the component.
*/
children?: ReactNode
children?: ReactNode,
/**
* Enables the selection of directories instead of individual files.
*/
directory?: boolean
}

function FileTrigger(props: FileTriggerProps, ref: ForwardedRef<HTMLInputElement>) {
let {onSelect, acceptedFileTypes, allowsMultiple, defaultCamera, children, ...rest} = props;
let {onSelect, acceptedFileTypes, allowsMultiple, defaultCamera, children, directory, ...rest} = props;
let inputRef = useObjectRef(ref);
let domProps = filterDOMProps(rest);

return (
<>
<PressResponder
<PressResponder
onPress={() => {
if (inputRef.current.value) {
inputRef.current.value = '';
Expand All @@ -62,7 +66,9 @@ function FileTrigger(props: FileTriggerProps, ref: ForwardedRef<HTMLInputElement
accept={acceptedFileTypes?.toString()}
onChange={(e) => onSelect?.(e.target.files)}
capture={defaultCamera}
multiple={allowsMultiple} />
multiple={allowsMultiple}
// @ts-expect-error
webkitdirectory={directory ? '' : undefined} />
</>
);
}
Expand Down
10 changes: 10 additions & 0 deletions packages/react-aria-components/stories/index.stories.tsx
Expand Up @@ -1166,6 +1166,16 @@ export const FileTriggerButton = (props) => (
</FileTrigger>
);

export const FileTriggerDirectories = (props) => (
<FileTrigger
directory
onSelect={action('onSelect')}
data-testid="filetrigger-example"
{...props} >
<Button>Upload</Button>
</FileTrigger>
);

export const FileTriggerLinkAllowsMultiple = (props) => (
<FileTrigger
{...props}
Expand Down
12 changes: 12 additions & 0 deletions packages/react-aria-components/test/FileTrigger.test.js
Expand Up @@ -88,4 +88,16 @@ describe('FileTrigger', () => {
let input = getByTestId('foo');
expect(ref.current).toBe(input);
});

it('should allow directory uploads when directory is true', () => {
render(
<FileTrigger directory>
<Button>Upload Directory</Button>
</FileTrigger>
);

let input = document.querySelector('input[type="file"]');
expect(input).toHaveAttribute('webkitdirectory');
});

});