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: add new file-input component #6355

Merged
merged 13 commits into from
Dec 13, 2023
Merged

feat: add new file-input component #6355

merged 13 commits into from
Dec 13, 2023

Conversation

robinzigmond
Copy link
Contributor

@robinzigmond robinzigmond commented Oct 9, 2023

Only supports input of a single file at present - multiple mode will follow in the future.

Proposed behaviour

A FileInput component should exist in the Carbon library, matching the Design System designs.

Current behaviour

There is no FileInput component

Checklist

  • Commits follow our style guide
  • Related issues linked in commit messages if required
  • Screenshots are included in the PR if useful
  • All themes are supported if required
  • Unit tests added or updated if required
  • Cypress automation tests added or updated if required
  • Playwright automation tests added or updated if required
  • Storybook added or updated if required
  • Translations added or updated (including creating or amending translation keys table in storybook) if required
  • Typescript d.ts file added or updated if required
  • Related docs have been updated if required

QA

  • Tested in CodeSandbox/storybook
  • Add new Playwright test coverage if required
  • Carbon implementation matches Design System/designs
  • UI Tests GitHub check reviewed if required

Additional context

Testing instructions

The following CodeSandbox is an example of the broken behaviour.
You can see the new behaviour by looking at the version in the comment by codesandbox[bot].

@codesandbox-ci
Copy link

codesandbox-ci bot commented Oct 9, 2023

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit ecbc2fe:

Sandbox Source
carbon-quickstart Configuration
carbon-quickstart-typescript Configuration
carbon-quickstart PR

@robinzigmond robinzigmond marked this pull request as draft October 9, 2023 14:16
@edleeks87 edleeks87 self-requested a review October 10, 2023 14:33
@nineteen88 nineteen88 self-requested a review October 12, 2023 08:56
Copy link
Contributor

@edleeks87 edleeks87 left a comment

Choose a reason for hiding this comment

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

Great work @robinzigmond 👍. I've noticed some potentially minor styling that might need updating but as you have a UX review/ chat with Ds planned I'll leave that stuff up to them as I've confirmed it all functions as I'd expect etc

src/components/file-input/file-input.stories.mdx Outdated Show resolved Hide resolved
src/components/file-input/file-input.component.tsx Outdated Show resolved Hide resolved
src/components/file-input/file-input.style.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@nineteen88 nineteen88 left a comment

Choose a reason for hiding this comment

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

Praise: Looks really good Robin. Top work!

Just a few nitpicky comments more than anything

return <FileInput label="File input" />;
};

export const Margins: ComponentStory<typeof FileInput> = () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion(non-blocking): I'm not sure on the value of this particular story

The other stories you have added make sense in terms of a consumer might be wondering how to do this different approaches with the File Input component, but I think Margins are pretty self explanatory and you can see Margins are supported in the prop table. There are lot of stories to contend with so I think removing bloat is good. Up to you though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair comment. I added it because basically the first several stories I added were "copies" of those in Textbox that still seemed relevant for FileInput. I wasn't even sure whether to have the Margin Props, or whether I should add Padding Props too - I expected quite a discussion on that tbh 😁 I'll hold my hands up and say I just went for consistency with Textbox (which also has this story), without thinking about it too much - that could be the wrong approach as they're obviously pretty different as components!

Having made my excuses, I agree this story isn't really adding much for consumers so happy to remove it 👍

on the client side, resulting in storing the file locally as a `data:` URL. This is a way to show users a preview of their file if you do not intend
to track upload progress on the server, or do not actually send the files to a server until form submission.

Note the use of a `ref` to store the `FileReader` object - this is not essential but avoids having to create a new such object more than once in the
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick (non-blocking): Remove the word such

Suggested change
Note the use of a `ref` to store the `FileReader` object - this is not essential but avoids having to create a new such object more than once in the
Note the use of a `ref` to store the `FileReader` object - this is not essential but avoids having to create a new object more than once in the

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I agree it reads awkwardly with that word in 👍 Not sure if I like just removing it though, as "a new object" isn't really being specific enough imo - the idea was to basically say "a new FileReader object" without repeating myself. I'll have a bit of a play and hopefully come up with a better way of phrasing it.

<Story name="tracking upload status on client side" story={stories.UploadStatusClient} />
</Canvas>

This example mocks an alternative approach where files added to the file input are immediately sent to the server, and the UI tracks the progress of this.
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick (non-blocking): The double this reads a little weird

Suggested change
This example mocks an alternative approach where files added to the file input are immediately sent to the server, and the UI tracks the progress of this.
This example mocks an alternative approach where files added to the file input are immediately sent to the server, and the UI tracks the progress.


This example mocks an alternative approach where files added to the file input are immediately sent to the server, and the UI tracks the progress of this.
This simple example mocks the progress (and the possibility of errors, such as network errors) with random numbers - in a real scenario this would poll an
alternative endpoint for the upload progress, or use WebSocket messages sent from the serber to update progress.
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick (non-blocking): Incorrect spelling

Suggested change
alternative endpoint for the upload progress, or use WebSocket messages sent from the serber to update progress.
alternative endpoint for the upload progress, or use WebSocket messages sent from the server to update progress.

onAction,
...statusProps
}: FileUploadStatusProps) => {
const l = useLocale();
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion(non-blocking): Use semantic variable names

I think we should avoid using non-descriptive variables names as it doesn't mean anything to someone scanning the code. It would typically be flagged as a code smell but I guess we don't have any static code analysis in that form.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

While I completely agree in general, l is what we universally use for this locale object in other components so I was just copying that. I'd be more than happy to change it but I think this needs a wider discussion - not just on what to call it but as to whether I use a different name here or we stick with consistency and perhaps update them all at once in a later piece of work.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree with both of you if that's possible, we should be as descriptive as possible but Robin has followed how we have implemented this elsewhere and how we've documented in our own docs so we should look to update them in separate ticket

}: FileInputProps,
ref: React.ForwardedRef<HTMLInputElement>
) => {
const l = useLocale();
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion(non-blocking): non-descriptive variable name

As mentioned before

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same response as above


const dataTransfer = await page.evaluateHandle(
async ({ bufferData, localFileName, localFileType }) => {
const dt = new DataTransfer();
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion(non-blocking): non-descriptive variable name

As mentioned previously

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll admit this was basically a copy-paste from a solution I found in someone's comment on a Github issue. I'm happy to change the variable name (to something like dataTransferObject I guess?)


import FileInput, { FileUploadStatusProps } from ".";

describe("FileInput component", () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion(non-blocking): superfluous describe block

As mentioned before


export const ErrorBorder = styled.span`
position: absolute;
z-index: 6;
Copy link
Contributor

Choose a reason for hiding this comment

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

question: what is this z-index used for?

It stood out because 6 seems to be a bit random to me, but I've tried removing it on storybook and it doesn't make a difference.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Excellent question that I can't answer 😅 I'll hold my hand up and admit this was copy-pasted from an equivalent styled component elsewhere (almost certainly Textbox but I don't specifically remember). Similar to what @edleeks87 commented on the hint text, that could arguably be moved to a central location (but as I argued there I'd rather not do it in this PR). Most likely the z-index can be removed from the other ones too, or maybe it's specific to that component that I copied it from and just not needed here?

For now I think I'll keep things separate and just remove the z-index from this component after confirming it's not needed. Thanks for spotting it.

align-items: center;
text-align: center;
gap: 12px;
border-radius: 4px;
Copy link
Contributor

Choose a reason for hiding this comment

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

question: could this be a design token?

I'm just wondering if it's possible that there's consistency here that DS want standard rounded corners across components. It's more in case they want to square off corners again it would be easier with a design token... But maybe I'm just worrying about something that won't happen

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question. I grabbed the ones I could from Figma but mostly it's only colours that that seems to show tokens for. I've now had a catch up with Laia from the DS team and she's pointed out a few tokens I missed (in terms of the colour etc actually being wrong, I mean) and has sent me a full list of them all - so absolutely any styles that come from tokens will be done properly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

in fact, similar to Ed's suggestion above with the StyledHintText, I'm just going to remove this entirely and inport this styled component from textbox.style, as several components already do (and pending a later tidy-up that moves these to a common file).

nineteen88
nineteen88 previously approved these changes Oct 17, 2023
edleeks87
edleeks87 previously approved these changes Oct 19, 2023
nineteen88
nineteen88 previously approved these changes Oct 19, 2023
@robinzigmond robinzigmond marked this pull request as ready for review October 19, 2023 10:48
@robinzigmond robinzigmond dismissed stale reviews from nineteen88 and edleeks87 via d838b94 October 23, 2023 10:04
edleeks87
edleeks87 previously approved these changes Oct 23, 2023
nineteen88
nineteen88 previously approved these changes Oct 23, 2023
edleeks87
edleeks87 previously approved these changes Oct 31, 2023
nineteen88
nineteen88 previously approved these changes Oct 31, 2023
@robinzigmond robinzigmond dismissed stale reviews from nineteen88 and edleeks87 via 6339e5e November 10, 2023 09:52
@harpalsingh
Copy link
Member

Had an additional UXQA on this after updates and happy with the work again.

nineteen88
nineteen88 previously approved these changes Nov 20, 2023
edleeks87
edleeks87 previously approved these changes Nov 27, 2023
nineteen88
nineteen88 previously approved these changes Nov 28, 2023
@robinzigmond robinzigmond dismissed stale reviews from nineteen88 and edleeks87 via 9388b8c December 6, 2023 11:35
@robinzigmond robinzigmond merged commit 8e99496 into master Dec 13, 2023
23 checks passed
@robinzigmond robinzigmond deleted the FE-6216-file-input branch December 13, 2023 14:44
@carbonci
Copy link
Collaborator

🎉 This PR is included in version 124.3.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

6 participants