Skip to content

[slider] Port component#11040

Merged
mbrookes merged 13 commits into
mui:masterfrom
epodivilov:slider-v2
May 25, 2018
Merged

[slider] Port component#11040
mbrookes merged 13 commits into
mui:masterfrom
epodivilov:slider-v2

Conversation

@epodivilov

@epodivilov epodivilov commented Apr 16, 2018

Copy link
Copy Markdown
Contributor

Added implementation of the Slider component according to the Google guidelines

image

PS: Something happened to my previous PR so I created a new one.

Closes #4793

@oliviertassinari oliviertassinari added scope: slider Changes related to the slider. package: lab Specific to the lab. labels Apr 16, 2018
@mbrookes
mbrookes self-requested a review April 16, 2018 21:44
@NayanSrivastav

Copy link
Copy Markdown

Thank @mbrookes for this, when can we expect this merge?

@epodivilov

Copy link
Copy Markdown
Contributor Author

@mbrookes what about this pull request?

@mbrookes

Copy link
Copy Markdown
Member

@epodivilov My task for this weekend.

@mbrookes

Copy link
Copy Markdown
Member

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 ButtonBase for the thumb, it would be preferable to use the focus ripple when keyboard focussed rather than a custom style.

The vertical slider seems backwards - I think the default should be from bottom-to-top, with reverse being top-to-bottom.

@Pajn pointed out that the use of top, left etc. for positioning is causing a performance hit. Did you have an opportunity to look at using transform: translate() and transform: scale()?

The testsh ave been renamed from .spec.js to .test.js

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! 👏

@epodivilov

Copy link
Copy Markdown
Contributor Author

@mbrookes Thanks for review.
First of all I would like to note that the ripple effect is not according to the google guidelines.
About performance issue I will try to check.

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.

@mbrookes

Copy link
Copy Markdown
Member

@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 aria-valuenow to a sensible level of precision (3 digits?), so that a screen-reader user isn't potentially faced with an unending list of spoken digits if the screen-reader doesn't truncate it.

@mbrookes

mbrookes commented Apr 29, 2018

Copy link
Copy Markdown
Member

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.

@mbrookes

mbrookes commented May 9, 2018

Copy link
Copy Markdown
Member

@epodivilov are you still working on this? It feels like we're very close to final review.

@epodivilov

Copy link
Copy Markdown
Contributor Author

@mbrookes Yes, I still working on this PR. I had a small vacation. I'll try to fix it this weekend.

@mbrookes

Copy link
Copy Markdown
Member

Thanks @epodivilov Hope you had a nice break! ☺️

@epodivilov

Copy link
Copy Markdown
Contributor Author

@mbrookes I fixed rounding of values and updated the Supported Components page. Please, review last updates

@mbrookes

Copy link
Copy Markdown
Member

@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.

@mbrookes mbrookes left a comment

Copy link
Copy Markdown
Member

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';

Copy link
Copy Markdown
Member

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';

Copy link
Copy Markdown
Member

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.

@epodivilov

Copy link
Copy Markdown
Contributor Author

@Pajn

Pajn commented May 12, 2018

Copy link
Copy Markdown
Contributor

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 v1-beta in both cases :)

@mbrookes

mbrookes commented May 12, 2018

Copy link
Copy Markdown
Member

@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.

@oliviertassinari
oliviertassinari changed the base branch from v1-beta to master May 12, 2018 18:20
@mbrookes
mbrookes requested a review from oliviertassinari May 13, 2018 10:07
import PropTypes from 'prop-types';
import classNames from 'classnames';
import withStyles from '@material-ui/core/styles/withStyles';
import ButtonBase from '@material-ui/core//ButtonBase';

@goto-bus-stop goto-bus-stop May 13, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

core//ButtonBasecore/ButtonBase

Copy link
Copy Markdown
Member

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}

Copy link
Copy Markdown
Contributor

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

@goto-bus-stop

Copy link
Copy Markdown
Contributor

Just tried this again with @material-ui/[email protected], works great! (except for the onKeyboardFocus thing) Thanks for the work!

@epodivilov

Copy link
Copy Markdown
Contributor Author

@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?

@goto-bus-stop

Copy link
Copy Markdown
Contributor

Oh I don't know, I'm not a maintainer, just a user excited for this PR 😛

@mbrookes

Copy link
Copy Markdown
Member

@epodivilov Yes please, if you could rename that prop as @goto-bus-stop pointed out, that would be great! Sorry I missed it.

@oliviertassinari oliviertassinari left a comment

Copy link
Copy Markdown
Member

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) {

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Member

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;

Copy link
Copy Markdown
Member

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}

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Contributor Author

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);

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Contributor Author

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 = {

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Contributor Author

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 */

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Contributor Author

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',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

WebkitTapHighlightColor: 'transparent',

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Contributor Author

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) {

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Contributor Author

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) => {

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed it

@mbrookes

Copy link
Copy Markdown
Member

@oliviertassinari Any last comments?

this.globalMouseUpListener = addEventListener(document, 'touchend', this.handleMouseUp);

if (typeof this.props.onDragEnd === 'function') {
this.props.onDragStart(event);

Copy link
Copy Markdown

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);

Copy link
Copy Markdown

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?

@oliviertassinari

Copy link
Copy Markdown
Member

@mbrookes None :)

@mbrookes
mbrookes merged commit 0b63c30 into mui:master May 25, 2018
@mbrookes

Copy link
Copy Markdown
Member

@epodivilov Thanks for all your hard work, and sticking with it! An amazing contribution for your first!

@acroyear

This comment has been minimized.

@oliviertassinari oliviertassinari added type: new feature Expand the scope of the product to solve a new problem. and removed package: lab Specific to the lab. labels Jan 9, 2021
@oliviertassinari oliviertassinari changed the title [Slider] Port component [slider] Port component May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: slider Changes related to the slider. type: new feature Expand the scope of the product to solve a new problem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[slider] Port component

8 participants