-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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(Dropdown): open to side with most space left #720 #2817
feat(Dropdown): open to side with most space left #720 #2817
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2817 +/- ##
==========================================
+ Coverage 99.66% 99.74% +0.07%
==========================================
Files 161 160 -1
Lines 2722 2785 +63
==========================================
+ Hits 2713 2778 +65
+ Misses 9 7 -2
Continue to review full report at Codecov.
|
Let's make this the default behavior and remove the prop. The current behavior is a bug so it is OK to "break" it. |
src/modules/Dropdown/Dropdown.js
Outdated
} else { | ||
this.setState({ shouldOpenUpward: false }) | ||
} | ||
} |
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.
An if/else which results in true/false statements can be simplified to using the condition as the value:
this.setState({
shouldOpenUpward: spaceAtTheBottom < 0 && spaceAtTheTop > 0,
})
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.
In the case that both top and bottom are blocked, perhaps we should open to the side with the most available space. I think this math is wrong, but something like:
this.setState({ shouldOpenUpward: spaceAtTheBottom > spaceAtTheTop })
src/modules/Dropdown/Dropdown.js
Outdated
if (!menu) return | ||
|
||
const dropdownRect = this.ref.getBoundingClientRect() | ||
const itemsHeight = menu.clientHeight |
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.
nit: Let's keep the naming consistent and use menuHeight
.
src/modules/Dropdown/Dropdown.js
Outdated
@@ -1273,7 +1338,7 @@ export default class Dropdown extends Component { | |||
useKeyOnly(selection, 'selection'), | |||
useKeyOnly(simple, 'simple'), | |||
useKeyOnly(scrolling, 'scrolling'), | |||
useKeyOnly(upward, 'upward'), | |||
useKeyOnly(upward || shouldOpenUpward, 'upward'), |
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.
When we have props that need to be controlled, we move to them to being autoControlledProps
. See Dropdown.js around line 346.
- add
upward
tostatic autoControlledProps = []
- add
defaultUpward
as apropType
(since it is now stateful, we accept a default value for it) - move all usages of
upward
fromthis.props.upward
tothis.state.upward
- to change the value of
upward
usethis.trySetState({ upward: <new value> })
- remove
shouldOpenUpward
as it is no longer needed.
Auto controlled props automatically defer to the user's prop value, if any. Also, this.trySetState()
will not update the state value if the user is using that prop.
Looking great! I've added some feedback for you here. Thanks much for tackling this one. |
Thank you for the feedback. I've done the changes that you've requested. However, there is one unit test failing now: "filters the items based on custom search function" It fails because the search function is now called two times instead of once. I suspect that it's called the first time when the dropdown opens, and a second time after the direction is set. This also points another issue. I don't like the fact that the dropdown needs to rerender after the direction is set. I'm not sure how to get around this though. The content needs to be rendered before we can calculate it's height. I could use some help. |
I've been looking at this too. I think if it doesn't change direction, it should only render once, so the search function will only be called once. Otherwise it will have to render twice (there's not really any way around this) so the search function will be called twice too. |
bf7475e
to
3265024
Compare
Thank you for your input, @samboylett. I've optimized the code so it updates the state only when there is a relevant change. |
This looks great, thanks! The last thing we need here is a test. The test would resize the browser window and assert the dropdown opened upward. We can merge after this update. |
Superb 👍 I've merged master. We can merge this PR once tests pass. |
@mihai-dinculescu You've contributed here before and you've shown care and initiative for ensuring SUIR becomes better. We appreciate this and want to enable you to do more. I've added you as a collaborator. You're now able to manage issues and PRs as well as create branches here in the main repo. You no longer need to work from a fork. Merging to master is the only reserved permission. We are very select about who we add and when, so know that we trust your abilities and your judgment. Please feel free to weigh in on any issues and PRs that you have an opinion about. You have a share of ownership and say here now. Once you accept the invite (see your email), you might want to show the Semantic Org badge publicly on your profile. To do that, navigate to the "people" page and change the "private" dropdown to "public" for your user in the table. Here's a direct link to your user in the table. /cc Please welcome @mihai-dinculescu to our ranks 😄 🎉 |
Thank you @levithomason. I'll do my best to be helpful. |
Released in |
#720
I have added a new prop, "keepInViewPort", so dropdown is consistent to Popup. However, this one is
false
by default, so the current behavior doesn't change.Please let me know your thoughts.