-
Notifications
You must be signed in to change notification settings - Fork 7
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
Introduce custom design of FileInputField
(#244)
#601
base: master
Are you sure you want to change the base?
Conversation
3137de8
to
17e8a64
Compare
id={id} | ||
onChange={handleFileChange} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we touch a prop explicitly, it should be listed in the props table.
Also onChange(event);
must be called in the handleFileChange()
. This will fix the functionality test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also onChange(event); must be called in the handleFileChange(). This will fix the functionality test.
I don't understand this part. How can I put onChange(event)
inside the handleFileChange
function? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The component accepts the onChange
prop which is a function. This is just a normal prop, that is just a function that can be called or not.
The problem is that as it is now this function never gets called. I guess it should have been passed via transferProps
, but it is not because you set onChange
attribute on the <input />
explicitely and that takes preference.
So we need to call the onChange
function originating from prop manually in the handler.
I'm not so sure if I explained it clearly. Feel free to call me if not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I get what you mean. How about now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due tu undergoing transformation from Jest to Playwright, I would not spend time on Jest tests if not necessary. If we agree that it is not solvable within minutes, I would leave comment that it will be fixed in #603 that I created for this purpose.
|
||
const handleFileChange = (event) => { | ||
const file = event.target.files[0]; | ||
setSelectedFileName(file.name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have example in README.md
where multiple
prop is used. However, if I select multiple files, only the first name is shown. With @mbohal, we agreed that for now, we would suggest:
- For 1 file: show file name
- For >1 files: show something like " files selected"
In future, we can improve it e.g. by Popover that could show list of selected files. But there could be problem with keyboard interaction, so we would stick to simple solution and can talk about further improvements later.
Technically, we would change selectedFileName
to array selectedFileNames
. From peformance point of view, it would be easier to hold single string that would contain name or string " files selected". But it would not work in case that user switches languages, so that's why we recommend using array of names for it.
@@ -2,6 +2,10 @@ export default { | |||
Alert: { | |||
close: 'Close', | |||
}, | |||
FileInputField: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not related to this PR, but @mbohal, if I see this and my another suggestion to display number of selected files, I think we need more robust approach for translations. For English it is OK, but I guess there can be languages that can have such language rules for which this approach would not work.
const handleDragOver = (event) => { | ||
event.preventDefault(); | ||
setIsDragging(true); | ||
|
||
if (props?.onDragOver) { | ||
props.onDragOver(event); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suspicion is this function is evaluated many times per second (which corresponds to how often the dragover
event is being fired). Is it OK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how onDragOver
is supposed to behave.
I think that setIsDragging
is handleDragOver
is not necessary. We should be able to solve it without it just using onDragEnter
and onDragLeave
. We only have to solve problem that onDragLeave
is called when dragging over child element.
This can be solved with change in FileInputField.module.scss
:
// 2. Prevent pointer events on all children of the root element to not to trigger drag events on children.
@layer components.file-input-field {
// Foundation
.root {
@include foundation.root();
* {
pointer-events: none; // 2.
}
}
Then setIsDragging(true);
can be removed from handleDragOver
.
CAUTION: handleDragOver
must be present here to prevent default behaviour. See https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop#prevent_the_browsers_default_drag_behavior
ref={ref} | ||
required={required} | ||
type="file" | ||
/> | ||
<div className={styles.dropZone}> | ||
<Text lines={1}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why but dragleave
is fired when this element is hovered during dragging. It doesn't happen in Spirit. That's why I double-check the isDragging
state is on by calling the hook (repeatedly) on the dragover
event. I'm certainly open to any improvements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is due to pointer events, see my comment: https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop#prevent_the_browsers_default_drag_behavior
# Conflicts: # src/components/FileInputField/FileInputField.jsx
67dd040
to
c779f4f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During our call with @mbohal, we agreed on several things:
- Change of
onDragOver
is described here: Introduce custom design ofFileInputField
(#244) #601 (comment) - Due to complexity, we do not want to use synthetic events but rather custom prop that would cover input change and file drop at one place, something like
onFilesChanged
and document it. This is missing in the documentation yet. Due to its complexity, this can't be omitted. - We do not want to make drag props available as we do not see benefits now and while do not want to use synthetic event.
onChange
, it would follow the same approach. - We are not sure about transferProps. Currently, input is hidden and logic is provided through button and droppable area. While we do not want to provide traditional synthetic event
onChange
and input is hidden, are transfer props placed on correct element? Is input where all aria attributes should be placed? We frankly do not know yet.
Closes #244.