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

feat: File Input component #900

Merged
merged 13 commits into from
Feb 26, 2021
Merged

feat: File Input component #900

merged 13 commits into from
Feb 26, 2021

Conversation

suzubara
Copy link
Contributor

@suzubara suzubara commented Feb 16, 2021

Summary

Implements the USWDS File Input component.

There are some tests that aren't 100% accurate, because simulating a drop event doesn't seem to accurately trigger the onChange handler for a file input. I left outstanding comments in those cases and maybe they can be improved upon in the future.

Related Issues or PRs

Closes #341

How To Test

Note: The FileInput requires updating to USWDS 2.8.1, which is included in this PR. Please make sure you run yarn install before testing after you check out this branch.

Test that you can use the input in a multipart form to upload file(s), and the file type validation works as expected.

If you want to handle uploading async on the change event, there is an onChange prop exposed you can use to pass in a custom handler. Note that the FileInput component will still display dropped files, and you may want to force a re-render to clear the value after uploading.

Screenshots (optional)

image

image

image

image

const imageId = makeSafeForID(files[i].name)
const key = `filePreview_${imageId}`
filePreviews.push(
<FilePreview key={key} imageId={imageId} file={files[i]} />
Copy link
Contributor

@haworku haworku Feb 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should surface an optional prop for FilePreview (defaulting to this component) so people could build their own.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this feels like an enhancement that goes beyond the USWDS implementation, mind adding as a new feature request?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point #957

className={imageClasses}
onError={onImageError}
/>
{name}
Copy link
Contributor

@haworku haworku Feb 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screen Shot 2021-02-18 at 10 57 24 AM
Got into this weird state when I had a file (screenshot) which had a long name.

Heres USWDS version
Screen Shot 2021-02-18 at 2 55 04 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I believe this is a result of needing to update to USWDS 2.8.1 (this update included some changes to the File Input CSS classes). I get the same result if I was on another branch with 2.8.0, and view the FileInput without running yarn install

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ha! looks like github deployments is just on time for me over here 😄

const expectedSrc = 'data:text/plain;base64,VGVzdCBGaWxlIENvbnRlbnRz'

const imageEl = getByTestId('file-input-preview-image')
await waitFor(() => expect(imageEl).not.toHaveClass('is-loading'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice. I haven't used waitFor before TIL.

@suzubara suzubara marked this pull request as ready for review February 23, 2021 19:18
@suzubara
Copy link
Contributor Author

@haworku I believe for your use case, we'll want to make it so you can programmatically clear/reset the value of the FileInput, which I think requires the same forwardRef change mentioned in this thread: https://trussworks.slack.com/archives/C0122MPMXL3/p1613073894012000

This might be a good component to try this out first on, since it will be tested in a real world app right away, and then we'll have a better idea of how to roll out this change to other JS input components as needed. How does that sound?

@suzubara suzubara added the type: feature New feature or request label Feb 23, 2021
@suzubara suzubara added this to the USWDS 2.8.0 milestone Feb 23, 2021
Copy link
Contributor

@brandonlenz brandonlenz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just approved the Happo diffs. There were a lot of very subtle changes to form labels (whitespace and font size), beyond what is mentioned specifically in the 2.8.1 patch notes. I suspect these changes were simply not mentioned, but its perfectly reasonable to presume that's where the diffs came from.

@haworku
Copy link
Contributor

haworku commented Feb 25, 2021

I believe for your use case, we'll want to make it so you can programmatically clear/reset the value of the FileInput, which I think requires the same forwardRef change

@suzubara Yep. Sound good. This is a good idea to use to experiment with the pattern here. agree we probably need to clear input pretty soon after each drop while the async upload happens and is displayed through our other list component.

name: string
disabled?: boolean
multiple?: boolean
accept?: string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice for the type of accept? to be string | string[] to make it more obvious how to pass multiple options and avoid needing to split on a string inside the component. I can imagine these use cases:

<FileInput accepts="pdf" ... />
<FileInput accepts={["pdf", "docx", "png"]} ... />

The second one needs a little more syntax than the current accept="pdf,docx,png", but I think having the type system help a developer provide the options correctly outweighs that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, I think the default string syntax is due to this attribute being passed to the <input /> (and that's the syntax for the native accept attr) but I could see allowing an array of strings being a nice enhancement. In that case we'd also need to join them into a single string to pass into the <input /> so there's some extra handling either way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't realize that input had an accept attribute natively. In that case it's probably fine as-is, at least in terms of being consistent with how we handle other things in the library. Thanks for the thoughtful response!

@trussworks-infra-zz trussworks-infra-zz temporarily deployed to storybook February 25, 2021 21:20 Inactive
Copy link
Contributor

@haworku haworku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I like having the custom handlers sb example as well.

@suzubara suzubara merged commit e1ccbcd into main Feb 26, 2021
@suzubara suzubara deleted the sr-file-input-component-341 branch February 26, 2021 19:16
@suzubara suzubara mentioned this pull request Feb 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New Component: File Input
5 participants