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

fix(Dropdown): fix multiple problems #1795

Merged
merged 12 commits into from
Jul 29, 2017
Merged

Conversation

layershifter
Copy link
Member

@layershifter layershifter commented Jun 24, 2017

Fixes #1787.
Fixes #1858.
Codepen

Single select, placeholder

Click on placeholder doesn't capture the search input focus.

Expected behaviour

e2ccbe57b3b7cb9527222b1be5b67634

Single select, arrows

Click on up or down arrows resets current search value.

Current behaviour

ec2e512c71c23889349a691a9051554c

Expected behaviour

335f2250d304c78a79e0e88003d3122a

Single select

Click on dropdown icon should always open the dropdown.

Current behaviour

d9561f84b192b3556bda9120caf92cf4

Expected behaviour

d84572e673d80f22ce2d665812a8b33d

Multi select, click

Click the dropdown (doesn't matter where) doesn't make anything.

Expected behaviour

38461b54e548206f3304e657c6e66f37

@codecov-io
Copy link

codecov-io commented Jun 24, 2017

Codecov Report

Merging #1795 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1795      +/-   ##
==========================================
+ Coverage   99.75%   99.75%   +<.01%     
==========================================
  Files         145      145              
  Lines        2477     2488      +11     
==========================================
+ Hits         2471     2482      +11     
  Misses          6        6
Impacted Files Coverage Δ
src/modules/Dropdown/Dropdown.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 14fa291...21ec3cf. Read the comment docs.

this.open(e)
return
}
if (this.searchRef) this.searchRef.focus()
Copy link
Member Author

Choose a reason for hiding this comment

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

@levithomason this method does not make me happy, do you have ideas how we can refactor it?

Copy link
Member

Choose a reason for hiding this comment

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

Hm, I don't think so. React has no focus mechanism so we'll have to use a ref or querySelector here. Since this section of logic is only reachable if this is a closed search dropdown, I think it makes sense.

What specifically are you not happy with and perhaps I can recommend better?

Copy link
Member Author

Choose a reason for hiding this comment

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

Too many conditions for one method as I think.

_.invoke(this.props, 'onClick', e, this.props)
// prevent handleClick()
e.stopPropagation()
this.toggle(e)
Copy link
Member Author

Choose a reason for hiding this comment

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

I don't want to split this to separate method, however I don't see any other way. The initial idea was to compare e.target in handleClick this the Icon's ref, but the Icon component is stateless and doesn't have refs.

Copy link
Member

Choose a reason for hiding this comment

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

Yep, I'd much rather have a separate explicit click handler here. This is OK. We are doing something entirely different when the icon is clicked.

@@ -848,12 +861,12 @@ export default class Dropdown extends Component {
// Setters
// ----------------------------------------

setValue = (value) => {
setValue = (value, resetQuery = true) => {
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure that the idea with resetQuery is the best possible, hovewer I don't see another path, as I see in all other cases searchQuery should be reset.

Copy link
Member

Choose a reason for hiding this comment

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

I think we should split this into two methods. setValue only sets the value and clearSearchQuery only clears the query. It is easier to test and reason about complex interactions when the methods are small and explicit.

There are also enough use cases to warrant seprating them I think:

componentWillMount

This calls setValue, however, it calls it with this.state.value. This is a redundant operation. It seems the only reason we call it is for the other logic in setValue, clearing the search query and setting the selected index.

We don't need to clear the query on mount, but we do need to set the selected index. I think this is duplicating work, but at the least, we don't need to clear the query on mount.

componentWillReceiveProps

This calls setValue when a new value is received. Though this is correct, I also don't think we want to clear the user's query when this happens. If a new value comes down while a query is entered, I think it should only change the value, not the query.

makeSelectedItemActive

This method currently takes a resetQuery argument and passes it down to setValue. I think this method should only make the selected item active and not do anything else. The call sites for this method should be responsible for also deciding to clear the query or not:

  • moveSelectionOnKeyDown - should never clear the query
  • selectItemOnEnter - should only clear query when !multiple
  • handleBlur - should clear the query (it is already only called when !multiple)

removeItemOnBackspace

Currently resets the query but is not necessary, there is no query at this point. Also, if the user enters a query and moves the cursor to the begining of the query and then presses backspace, we wouldn't want to clear the query either:

[ LabelA x ] [ LabelB x ] | My query
                          ^ cursor, backspace should not clear the query

I know we don't support this yet, but we technically could/should in the future.

handleItemClick

This currently resets the query when an menu item is made active, however, I have always found this to be a usability issue with multiple dropdowns. When there are lots of items, it is often more helpful to keep the query while clicking items. Otherwise, the user has to enter the same query over and over for every item. Example, selecting all states that start with ma:

http://g.recordit.co/OqqnZDHR5u.gif

If we separate setValue and clearSearchQuery, then we can call only setValue in the multiple condition in this method. The other branch (not multiple) we can safely clear the query becuase we know the user is done making selections.

handleLabelRemove

This will currently clear the query also but probably never should have done so. Here I'm again selecting states with ma. I "accidentally" select Alabama and continue making selections. I then remove Alabama while I have a query entered and my query gets removed :/

http://g.recordit.co/IqdAPXNVrQ.gif

Copy link
Member Author

Choose a reason for hiding this comment

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

@levithomason Thanks for a detailed feedback, I'm fully agree with your suggestions. Will make a changes soon

Copy link
Member Author

Choose a reason for hiding this comment

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

I think that we should extract behaviour of removeItemOnBackspace to separate issue, I fully agree that we need to impliment it.

@layershifter
Copy link
Member Author

I performed required changes, in most cases the Dropdown is working as expected, but there are there some behaviours whose destiny should be solved before I will fix tests and add new.

@levithomason your review is very necessary, also I will be happy to hear @klerkendev there.

@layershifter
Copy link
Member Author

I extracted RFCs to separate issues: #1806 and #1807.

@layershifter layershifter changed the title WIP(Dropdown): fix multiple problems with minCharacters fix(Dropdown): fix multiple problems Jun 29, 2017

handleIconOverrides = predefinedProps => ({
onClick: (e) => {
_.invoke(predefinedProps, 'onClick', e, predefinedProps)
Copy link
Member Author

Choose a reason for hiding this comment

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

Please take an attention to this line, Icon component doesn't have onClick handler, so it doesn't have second argument. There are two possible solutions: remove the second argument or add onClick hanlder to the Icon component.

Copy link
Member

Choose a reason for hiding this comment

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

I see the issue here, however, I think this is going to be rare enough of an edge case to leave as-is for now. We shall see :)

requiredProps = {},
} = options
const { assertRequired } = helpers('implementsShorthandProp', Component)
const assertMethod = strictAssert ? 'contain' : 'containMatchingElement'
Copy link
Member Author

Choose a reason for hiding this comment

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

Why? contains is too strict while I added onClick handler to the Icon it was real pain. I think it's a quite elegant solution, as I remember we had same problem with the Input component.

Copy link
Member Author

@layershifter layershifter left a comment

Choose a reason for hiding this comment

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

@levithomason we're ready for review there.

@layershifter
Copy link
Member Author

Requires #1845.

Alexander Fedyashov added 2 commits July 17, 2017 11:07
…React into fix/dropdown-min-characters

# Conflicts:
#	test/specs/modules/Dropdown/Dropdown-test.js
@levithomason
Copy link
Member

@layershifter #1845 has been merged, should be unblocked here.

Copy link
Member

@levithomason levithomason left a comment

Choose a reason for hiding this comment

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

I've left some notes regarding splitting setValue, clearSearchQuery, and makeSelectedItemActive.

Copy link
Member Author

@layershifter layershifter left a comment

Choose a reason for hiding this comment

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

@levithomason I've performed requested changes

@levithomason
Copy link
Member

This looks great, thanks for pressing through on this!

@levithomason levithomason merged commit 62507c2 into master Jul 29, 2017
@levithomason levithomason deleted the fix/dropdown-min-characters branch July 29, 2017 17:21
@levithomason
Copy link
Member

Released in semantic-ui-react@0.71.3

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

Successfully merging this pull request may close these issues.

3 participants