-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
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
[Slider] Port component #11040
[Slider] Port component #11040
Conversation
Thank @mbrookes for this, when can we expect this merge? |
@mbrookes what about this pull request? |
@epodivilov My task for this weekend. |
Okay, this is starting to take shape! Keyboard input in the basic slider is 💯👌 , however mouse / touch input has the same granularity (1% step) as keyboard input, rather than being continuous, which gives a course feel to the movement. v0 had the same issue, so it would be good to address that here. It isn't a show-stopper, but I fear if we don't fix it now, it might get left like this. Since you're using The vertical slider seems backwards - I think the default should be from bottom-to-top, with @Pajn pointed out that the use of The testsh ave been renamed from Once we get these last bits sorted, we can dig into code review (I have been focussing mostly on functionality). Thanks for all your hard work! 👏 |
@mbrookes Thanks for review. About mouse / touch behavior I have a question. Right now I round value to step. if you do not do this, then which sign is worth rounding? For example: I clicked roughly in the middle of the slider and got value 0.5987654321. Now I will return the value 0.59. But it same value, which you can get by keyboard. |
@epodivilov You're right, no ripple in the spec, or the MCW (or other) implementations. I'm a little surprised at that, as the ripple is designed as a visual affordance to make the focused component more obvious. Regarding rounding the value - MCW don't round the value returned, so the developer can decide what precision to apply: https://material-components-web.appspot.com/slider.html However unlike MCW, I believe we should round |
One other thing you can do as part of this PR is to update the Supported Components page. You can follow the SpeedDial example, but I think it would be a good idea to add the checkmark to both Slider and SpeedDial. |
@epodivilov are you still working on this? It feels like we're very close to final review. |
@mbrookes Yes, I still working on this PR. I had a small vacation. I'll try to fix it this weekend. |
Thanks @epodivilov Hope you had a nice break! |
@mbrookes I fixed rounding of values and updated the Supported Components page. Please, review last updates |
@epodivilov Looks like something's gone wrong with the branch. You don't need to create a new PR, just clean up the brach and force push. |
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 looking great! Thanks for working on it.
import classNames from 'classnames'; | ||
import withStyles from '../../../material-ui/src/styles/withStyles'; | ||
import ButtonBase from '../../../material-ui/src/ButtonBase'; | ||
import { fade } from '../../../material-ui/src/styles/colorManipulator'; |
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.
These should be imported as:
import withStyles from 'material-ui/styles/withStyles';
etc.
Thought we fixed this already, but hey! 😄
import withStyles from '../../../material-ui/src/styles/withStyles'; | ||
import ButtonBase from '../../../material-ui/src/ButtonBase'; | ||
import { fade } from '../../../material-ui/src/styles/colorManipulator'; | ||
import clamp from '../utils/clamp'; |
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 meant for this to be in the core material-ui
so we can reuse it there, but I can fix it up later.
@mbrookes What does you mean "clean up the branch"? Like this https://stackoverflow.com/a/25357146 ? |
I would personally rebase and squash but that is of coursee up to you what you are most comfortable with. The end result is a nice simple commit on top of the current |
@epodivilov it wasn't about squashing (we can do that at merge), but there were somehow a bunch of unrelated commits in the PR. I wasn't sure if a rebase would be sufficient, or whether you'd have to cherry-pick your commits back onto a clean branch so "clean up" meaning whatever it needed to get it back into a reviewable, mergeable state. |
import PropTypes from 'prop-types'; | ||
import classNames from 'classnames'; | ||
import withStyles from '@material-ui/core/styles/withStyles'; | ||
import ButtonBase from '@material-ui/core//ButtonBase'; |
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.
core//ButtonBase
→ core/ButtonBase
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.
Thanks.
onMouseDown={this.handleMouseDown} | ||
onTouchStartCapture={this.handleTouchStart} | ||
onTouchMove={this.handleMouseMove} | ||
onKeyboardFocus={this.handleFocus} |
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.
onKeyboardFocus
was renamed to onFocusVisible
in #11188
Just tried this again with |
@goto-bus-stop Great news. Should I fix something in my code, or do you fix it yourself? And when you plan to merge the PR? |
Oh I don't know, I'm not a maintainer, just a user excited for this PR 😛 |
@epodivilov Yes please, if you could rename that prop as @goto-bus-stop pointed out, that would be great! Sorry I missed it. |
…aterial-ui into slider-v2
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 just had a look at the source code. Thanks for taking the time to work on i!
@@ -0,0 +1,3 @@ | |||
export default function clamp(value, min = 0, max = 100) { |
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.
Can potentially be shared at some point with colorManipulator.
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.
That was the original intention - we have a clamp function in a couple of places. I plan to consolidate them once this is merged.
vertical, | ||
reverse, | ||
disabled, | ||
} = this.props; |
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.
It would be great to spread the other properties on the root element.
onBlur={this.handleBlur} | ||
onKeyDown={this.handleKeyDown} | ||
onMouseDown={this.handleMouseDown} | ||
onTouchStartCapture={this.handleTouchStart} |
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.
Why do we need to trigger the event during the capture phase? It's the first time we do such.
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 need to prevent page scrolling when moving the slider (function preventPageScrolling).I should catch event before preventing, so I use capture phase.
aria-orientation={vertical ? 'vertical' : 'horizontal'} | ||
onClick={this.handleClick} | ||
ref={node => { | ||
this.container = findDOMNode(node); |
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 default component is a div
. I don't think that you need to call findDOMNode
.
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.
To prevent page scrolling, I need to catch touch events and prevent them from entering outside of the container. So I need get a link to container component.
}; | ||
}; | ||
|
||
const KEY_CODES = { |
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 already packages into the keycode
dependency. No need for duplicating it.
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.
You can find many examples in the codebase.
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.
Replaced that code to keycode library
}; | ||
|
||
return { | ||
/* Styles for wrapper container */ |
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 wish we will be able to extra these comments and add it to the API documentation automatically 💯 at some point.
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'm not understand, should I remove this comments?
margin: '10px 0', | ||
padding: '6px 0', | ||
cursor: 'pointer', | ||
'-webkit-tap-highlight-color': 'transparent', |
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.
WebkitTapHighlightColor: 'transparent',
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.
For consistency, like we need everywhere else.
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.
Fixed it
ARROW_DOWN: 40, | ||
}; | ||
|
||
function addEventListener(node, event, handler, capture) { |
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 capture
argument is never used.
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.
By the way. I'm not sure you need this helper 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.
This function is used to detect movement of the mouse outside the component, as well as to detect the termination of interaction with the component. So I can remove unused argument, but I think is not a problem. If this function move to all helpers function somebody might need this parameter.
}; | ||
} | ||
|
||
const calculatePercent = (node, event, isVertical, isReverted) => { |
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.
You are using a function
with the other helpers, not an arrow, maybe we should be consistent.
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.
Fixed it
@oliviertassinari Any last comments? |
this.globalMouseUpListener = addEventListener(document, 'touchend', this.handleMouseUp); | ||
|
||
if (typeof this.props.onDragEnd === 'function') { | ||
this.props.onDragStart(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.
Do you mean to test for onDragEnd here? Or onDragStart?
this.globalMouseMoveListener = addEventListener(document, 'mousemove', this.handleMouseMove); | ||
|
||
if (typeof this.props.onDragEnd === 'function') { | ||
this.props.onDragStart(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.
Do you mean to test for onDragEnd here? Or onDragStart?
@mbrookes None :) |
@epodivilov Thanks for all your hard work, and sticking with it! An amazing contribution for your first! |
Added implementation of the Slider component according to the Google guidelines
PS: Something happened to my previous PR so I created a new one.
Closes #4793