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 draft for File input #140

Merged
merged 1 commit into from
Feb 16, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions research/src/components/file-anatomy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* eslint-disable jsx-a11y/label-has-associated-control */
import React from 'react'
import './anatomy.css'

const FileAnatomy = () => {
return (
<div className="component-anatomy-wrapper">
<input type="checkbox" id="show-slots" />
<label htmlFor="show-slots"> Show slots</label>
<div className="component-anatomy">
<host name="openui-file">
<part name="file-selector-button">
<slot name="button"></slot>
</part>
<part name="label">
<slot name="label"></slot>
</part>
</host>
</div>
</div>
)
}

export default FileAnatomy
4 changes: 2 additions & 2 deletions research/src/components/specimens.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ const Specimens = ({ component, conceptName, showDescriptions }) => {

return (
<div style={{ display: 'flex', flexWrap: 'wrap', border: '1px solid #ccc' }}>
{images.map((image) => {
{images.map((image, index) => {
const hasOverrideName = image.name !== image.openUIName

return (
<div
key={image.image}
key={image.image + index}
style={{
display: 'flex',
flex: '0 0 auto',
Expand Down
Binary file added research/src/images/antd-file-default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/antd-file-selection-focus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/antd-file-selection-hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/antd-file-selection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/carbon-file-default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/carbon-file-selection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/chromium-file-default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/chromium-file-multiple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/evergreen-file-default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/evergreen-file-multiple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/github-file-default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/github-file-focus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/github-file-selection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added research/src/images/lightning-file.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
207 changes: 207 additions & 0 deletions research/src/pages/file/file.proposal.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
---
menu: Proposals
name: File (Editor's Draft)
path: /components/file
pathToResearch: /components/file.research
---

import '../../styles/spec.css'
import FileAnatomy from '../../components/file-anatomy'

# File Input Component Specification

## Overview

The `<input type="file">` (or file input) element is a control that provides
the user with the ability to select local files.

### Background

The file input allows users to upload one or multiple files, which may or may
not be part of a form submission.

Currently, this control is the only way access to access a user's filesystem.

### Use Cases

The file input is widely used across the web. Examples include attaching
documents to a job or visa application, and uploading multimedia content to
cloud storage services.

### Non-goals

The file input does not provide a way to programatically invoke access to a
user's filesystem, other than invoking `click()`.

### Features

This control invokes a prompt to the user requesting that the user specify one
or more files to upload. Once selected, the prompt collapses and input is
updated with the selected files.

### Risks and Challenges

There are no risks or challenges presented as a part of this proposal.

### Prior Art/Examples

- [Ant Design](https://ant.design/components/upload/)
- [Bootstrap](https://getbootstrap.com/docs/4.0/components/forms/#form-controls)
- [Carbon](https://www.carbondesignsystem.com/components/file-uploader/usage/)
- [Evergreen](https://evergreen.segment.com/components/filepicker/)
- [Materialise](https://materializecss.com/text-inputs.html)
- [MOJ](https://moj-design-system.herokuapp.com/components/multi-file-upload)

Examples can also be found within platforms like GitHub (attaching binaries to
gregwhitworth marked this conversation as resolved.
Show resolved Hide resolved
a release), along with many government sites.

## Design

The file input consists of two parts: a button, and a label. Clicking the
button invokes the file selection prompt.

### API

## Properties and Attributes

| Attribute Name | Type | Default Value | Description |
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`accept`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept) | `string` | Empty `string` | One or more unique file type specifiers describing file types to allow |
| [`capture`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/capture) | `string` | `null` | What source to use for capturing image or video data (`user` or `environment`) |
| `value` | [`DOMString`](https://developer.mozilla.org/en-US/docs/Web/API/DOMString) | Empty `string` | A `DOMString` that represents the path to the selected file(s). If the user selected multiple files, the value represents the first file in the list of files they selected |
| [`files`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#files) | [`FileList`](https://developer.mozilla.org/en-US/docs/Web/API/FileList) | Empty `FileList` | A `FileList` listing the chosen files |
| [`multiple`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/multiple) | `boolean` | `false` | A `boolean` which, if present, indicates that the user may choose more than one file |

## Methods

N/A

## Events

| Event Name | Detail Type | Bubbles | Composed | Cancellable | Dispatch Behavior |
| ---------- | ----------- | ------- | -------- | ----------- | ------------------------------------------------------- |
| `change` | none | `true` | `true` | `false` | Fired when the input's `value` is commited by the user. |
| `input` | none | `true` | `true` | `false` | Fired when the input's `value` changes. |

### Anatomy

#### Diagram

<FileAnatomy />

#### DOM Structure
gregwhitworth marked this conversation as resolved.
Show resolved Hide resolved

```html
<host>
<div part="file-selector-button">
<slot name="file-selector-button"></slot>
</div>
<div part="label">
<slot name="label"></slot>
</div>
</host>
```

#### Slots

| Slot Name | Description | Fallback Content |
| ---------------------- | ------------------------------------------------------------------------------------- | ----------------------------- |
| `file-selector-button` | Invokes the file selection prompt. | A button element is provided. |
| `label` | Indicates if a file input is waiting for file selection, or if it has selected files. | A label element is provided. |

#### CSS Parts

| Part Name | Description |
| ---------------------- | ----------------------------------------------------- |
| `file-selector-button` | The controls button. |
| `label` | The controls label, indicating file selection status. |

---

## Behavior

### States and Interactions
gregwhitworth marked this conversation as resolved.
Show resolved Hide resolved

When the input is invoked, the file selection prompt will limit the user to
selecting files that match the `accept` attribute, and the user will be limited
to selecting a single file unless the `multiple` attribute is `true`.

When a file are selected, the `label` updates to show the filename. When set to
`multiple`, the number of selected files is shown instead of a filename.

If a user cancels the prompt (choosing not to select a file), the input shows
the default (no selection) state. This also clears any previously selected
files.

#### Drag and drop

Users may also drag and drop files onto the input, where the drop target is the
containing element.

#### Accessibility

The file input should be focusable via keyboard navigation (tab).

#### Keyboard Navigation and Focus

Navigating to the file input control focuses the entire input (inclusive of the
label).

#### Form Input

The file input integrates with forms, accepting the `required` attribute for
validation.

#### Use with Assistive Technology

The `openui-file` component should appear as a `button` (ARIA role) along with
a `label` representing the current selection state.

As with other form controls, a `label` should be used to give context to this
control.

### Globalization

The positions of the button and label should be reversed for languages written
gregwhitworth marked this conversation as resolved.
Show resolved Hide resolved
RTL (right-to-left).

### Security

The `<input type="file">` element doesn't allow applictions access to the
filesystem, and the value is prefixed with a [fake path](https://html.spec.whatwg.org/multipage/input.html#fakepath-srsly).

## Performance

There are no current performance concerns for the file input.

## Dependencies

No third party dependencies are required.

### Platform Requirements

To implement a custom file input, a developer must create a hidden
gregwhitworth marked this conversation as resolved.
Show resolved Hide resolved
`<input type="file">` element, and call `click()` on that element to invoke
that input's behaviour.

The [Native File System API](https://wicg.github.io/native-file-system/)
will allow for implementations of file input controls without the above
workaround.

### Tooling

No additional tooling is required for the file input.

---

## Resources

- [MDN Reference on the current &ltinput type="file"&gt](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file)
- [MDN Reference on the File API](https://developer.mozilla.org/en-US/docs/Web/API/File)
- [WHATWG Living Standard on &ltinput type="file"&gt](<https://html.spec.whatwg.org/multipage/input.html#file-upload-state-(type=file)>)

## Next steps

Some file input implementations list selected files for the user to review,
deselect/remove, and possibly rename. There is not specification for this
behaviour.
36 changes: 36 additions & 0 deletions research/src/pages/file/file.research.examples.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
name: Real-world File Examples
path: /components/file.research.examples
showInMenu: false
---

import Image from '../../components/image'

## Overview

Below are real-world examples of file inputs (outside of libraries).

### GitHub - Attaching binaries to a release

The below demonstrates GitHub's UI for attaching binaries to a release.

#### Default

<Image src="github-file-default.png" alt="GitHub - attaching release binaries - default state" />
<br />
<br />

#### Focus

<Image src="github-file-focus.png" alt="GitHub - attaching release binaries - focus state" />
<br />
<br />

#### With selection

Supports multiple selections, in which case the selections stack at the top.

<Image
src="github-file-selection.png"
alt="GitHub - attaching release binaries - selection state"
/>
24 changes: 24 additions & 0 deletions research/src/pages/file/file.research.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: File
path: /components/file.research
gregwhitworth marked this conversation as resolved.
Show resolved Hide resolved
pathToProposal: /components/file
menu: Analysis
---

import ComponentCoverage from '../../components/component-coverage'
import FileAnatomy from '../../components/file-anatomy'
import Concepts from '../../components/concepts'

<ComponentCoverage component="File" />

## Anatomy

<FileAnatomy />

## Concepts

<Concepts component="File" />

## Related

- [Real-world File Examples](/components/file.research.examples)
29 changes: 28 additions & 1 deletion research/src/sources/antd.json5
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,34 @@
},
{
"name": "Upload",
"url": "https://ant.design/components/upload"
"openUIName": "File",
"url": "https://ant.design/components/upload",
"concepts": [
{
"name": "Default",
"image": "antd-file-default.png"
},
{
"name": "Default (with file selection)",
"image": "antd-file-selection.png"
},
{
"name": "Multiple",
"image": "antd-file-default.png"
},
{
"name": "Multiple (with file selection)",
"image": "antd-file-selection.png"
},
{
"name": "File list (hover)",
"image": "antd-file-selection-hover.png"
},
{
"name": "File list (focus)",
"image": "antd-file-selection-focus.png"
}
]
},
{
"name": "Avatar",
Expand Down
22 changes: 21 additions & 1 deletion research/src/sources/carbon.json5
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,27 @@
},
{
"name": "File uploader",
"url": "https://www.carbondesignsystem.com/components/file-uploader/code"
"openUIName": "File",
"url": "https://www.carbondesignsystem.com/components/file-uploader/code",
"definition": "The file uploader allows a user to transfer a file or submit content of their own.",
"concepts": [
{
"name": "Default",
"image": "carbon-file-default.png"
},
{
"name": "Default (with file selection)",
"image": "carbon-file-selection.png"
},
{
"name": "Multiple",
"image": "carbon-file-default.png"
},
{
"name": "Multiple (with file selection)",
"image": "carbon-file-selection.png"
}
]
},
{
"name": "Form",
Expand Down
Loading