Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

feat(slider): Implement continuous slider component #781

Merged
merged 1 commit into from
Jun 8, 2017

Conversation

traviskaufman
Copy link
Contributor

  • Add continuous slider component
  • Check in package-lock.json, part of npm5/node8
  • Disable stylelint for demos.css

Part of #25

@traviskaufman traviskaufman requested review from amsheehan, lynnmercier and yeelan0319 and removed request for lynnmercier June 2, 2017 20:56
@traviskaufman traviskaufman force-pushed the feat/continuous-slider branch from 8449e9d to 9e35bd6 Compare June 2, 2017 22:58
@codecov-io
Copy link

codecov-io commented Jun 2, 2017

Codecov Report

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

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #781      +/-   ##
==========================================
+ Coverage   99.92%   99.93%   +<.01%     
==========================================
  Files          65       68       +3     
  Lines        2776     3119     +343     
  Branches      323      383      +60     
==========================================
+ Hits         2774     3117     +343     
  Misses          2        2
Impacted Files Coverage Δ
packages/mdc-slider/constants.js 100% <100%> (ø)
packages/mdc-slider/index.js 100% <100%> (ø)
packages/mdc-slider/foundation.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 ef44d3d...0fc9ca9. Read the comment docs.

Copy link
Contributor

@yeelan0319 yeelan0319 left a comment

Choose a reason for hiding this comment

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

Overall looks really good!
I will took another pass for the test files early tomorrow morning.

<div class="mdc-toolbar__row">
<section class="mdc-toolbar__section mdc-toolbar__section--align-start">
<span class="catalog-back">
<a href="/"><i class="material-icons">&#xE5C4;</i></a>
Copy link
Contributor

Choose a reason for hiding this comment

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

The new toolbar need a link to be wrapped around mdc-toolbar__icon--menu like the following:

<span class="catalog-back">
    <a href="/" class="mdc-toolbar__icon--menu"><i class="material-icons">&#xE5C4;</i></a>
</span>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah I see. I believe other demo code needs to be updated as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

...nvm!


```js
// CommonJS
const {MDCSlider} = require('@material/slider/dist/mdc.slider');
Copy link
Contributor

Choose a reason for hiding this comment

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

Correct me if I am wrong, but I think const MDCSlider = require('mdc-slider') works?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It actually doesn't, since in package.json we specify the package name as @material/slider

@yeelan0319
Copy link
Contributor

Also there is a noticeable flash in thumb when user set value of slider to 0 (or they provide no value), which I don't feel it is a good UX experience.

The reason causing that is because we always add mdc-slider--off in the constructor if there are needed and that may be executed after the slider is fully rendered.

I think there are potentially 2 strategies here.

  1. Thumbs are set to display:none before the constructor is completed and we only show it after we fully understand how it would be rendered.
  2. In the document, we suggest the users of mdc-slider to manually add mdc-slider--off in their mark up if they know the slider have value==0 in the first place.

IMHO, I prefer we handle the logic if that is not too much of overhead. WDYT?

});

slider.listen('MDCSlider:change', function() {
committedValue.textContent = slider.value;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: would demonstrate that the event come with mdc-slider instance be more informative?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry but I'm not sure what you mean here...

assert.equal(foundation.getStep(), 0);
});

test('#constructor sets the disabled state to enabled', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

super nit: the default disabled state

foundation.layout();
foundation.layout();

assert.equal(numComputations, 2);
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe use td.verify(mockAdapter.computeBoundingRect(), {times: 2}); and remove the counter instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you try and td.verify a method that's been mocked out, testdouble will emit a warning (rightfully so). Added an explanation as to why we need to stub and verify , thus use this method, in a comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

Works for me. I didn't noticed that warning message, good testdouble!

raf.restore();
});

test('#getMax/#setMax basic functionality', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

super nit: feel the test description should be more descriptive.

How about "Slider Max getter and setter work correctly"?

Copy link
Contributor Author

@traviskaufman traviskaufman Jun 8, 2017

Choose a reason for hiding this comment

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

I think "correctly" is equally as vague, if not more. What is "correctly"? How many aspects of the functionality does "correctly" cover? How about something like #setMax/#getMax sets/retrieves the maximum value, respectively. It's more verbose but also more descriptive, plus it's precise and accurate as to what it's testing.

raf.restore();
});

test('#getMin/#setMin basic functionality', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Super nit: same thing here.

raf.restore();
});

test('#getStep/#setStep basic functionality', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Super nit: and here

raf.restore();
});

test('#isDisabled/#setDisabled basic functionality', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Super nit: and here.

Copy link
Contributor

@amsheehan amsheehan left a comment

Choose a reason for hiding this comment

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

Just a few changes requested from me. This is really great work. 👍 🏆 💯 🥇

</a>
</div>-->

> **Status**:
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a very novel way to document the development state of components that have multiple permutations.

> - [ ] Discrete Sliders

MDC Slider provides an implementation of the Material Design slider component. It is modeled after
the browser's `<input type="range">` element. Sliders are fully RTL-aware, and conforms to the
Copy link
Contributor

Choose a reason for hiding this comment

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

"...fully RTL-aware, and conform to the..."

Note that **vertical sliders and range (multi-thumb) sliders are not supported, due to their absence
from the material design spec**.

Also note that we have taken certain deviations from the UX within the spec, so there may be some
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we can be more concrete in our language here. What specifically changed? What should I expect?

<section class="hero">
<div id="hero-slider-wrapper">
<div id="hero-slider" class="mdc-slider" tabindex="0"
role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"
Copy link
Contributor

Choose a reason for hiding this comment

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

It may be an improvement to set aria-valuenow to something ~30. I think it speaks more clearly as to what the track and thumb are used for if we have some non-zero value set on page load. Just my opinion.

}

.mdc-theme--dark {
background-color: #333;
Copy link
Contributor

Choose a reason for hiding this comment

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

I noticed that we handle the contrast of component/dark background by applying the accent color to the component. I feel this would be useful in other demos as well (mdc-switch comes to mind).

Copy link
Contributor Author

@traviskaufman traviskaufman Jun 8, 2017

Choose a reason for hiding this comment

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

Agreed and noted. Should I file an issue? Should we do this within demos.scss and make a general note somewhere?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think an issue is appropriate. That way we can toss up a help-wanted label and see if anyone bites.

deregisterThumbContainerInteractionHandler: (type, handler) => {
this.thumbContainer_.removeEventListener(type, handler);
},
registerBodyInteractionHandler: (type, handler) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel we are using document.addEventListener(type, handler) in a few components. We should be attaching them to the body because

  1. If we want to check any attributes/classnames/etc... of an EventTarget, it doesn't make sense to develop against the document since it doesn't share any properties with an HTMLElement.
  2. For the same reason as above, testing aforementioned checks via domEvents.emit(document, 'click') is impossible. e.g.:
// something that gets called in response to _either_ an element 
// click or a document click event
function eventHandler(evt) {
  if (someAdapterMethodThatChecksForAnAttr(evt.target)) {
    doSomething();
  }
}

function eventHandlerTest() {
  ...
  domEvents.emit(document, 'click');
  domEvents.emit(someElement, 'click');
  ...
  // Results in event targets with completely different properties.
  // This makes it very kludgy to check for event target properties in 
  // our foundations/components 
}

Also, a person browsing a website can't technically click on the document.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 techdebt issue?

}

.mdc-slider--active {
&:not(.mdc-slider--disabled) .mdc-slider__thumb {
Copy link
Contributor

Choose a reason for hiding this comment

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

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah dunno why I did that...removing :not(.mdc-slider--disabled) since the slider can't ever be active if also disabled


suite('MDCSliderFoundation - keyboard events');

function createFakeEvent(info = {}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This would be useful in a lot of places. Consider pulling it out into one of the helper files?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are there places you can identify currently where this would be useful? Otherwise I'm skeptical hesitant to prematurely refactor it.

raf.restore();
});

test('on any other keydown does nothing', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I mean... kind of. This really just tests if any other key is the Enter key.

this.adapter_.deregisterResizeHandler(this.resizeHandler_);
}

layout() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This updates UI, but does nothing to alert the user of the value change. e.g.: If a user programmatically changes the step value, we see the slider move to the closest step. However, we don't get an event for the value change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that's fine. When you update an HTMLInputElement's value prop programmatically you don't get an event either, so this keeps our behavior consistent with the way the DOM API behaves.

@traviskaufman
Copy link
Contributor Author

traviskaufman commented Jun 8, 2017

@yeelan0319

Also there is a noticeable flash in thumb when user set value of slider to 0 (or they provide no value), which I don't feel it is a good UX experience...IMHO, I prefer we handle the logic if that is not too much of overhead. WDYT?

I'm not sure we can handle this overhead automatically. Because the slider programmatically sets all of its values, we have to wait for the script to execute for those styles to automatically be applied, thus there's always a potential for FOUC. I think your suggestion regarding manually adding the class for the off state is a good one; I'll go ahead and add that to the README.

- Add continuous slider component
- Check in `package-lock.json`, part of npm5/node8
- Disable stylelint for `demos.css`

Part of #25
@traviskaufman traviskaufman force-pushed the feat/continuous-slider branch from 9e35bd6 to 0fc9ca9 Compare June 8, 2017 19:10
@traviskaufman
Copy link
Contributor Author

All comments addressed. PTAL!

@yeelan0319
Copy link
Contributor

Agree to your concern about the racing condition in initialization, also noticed you changed the initial value of the demo. 👍

PR looks all good to me.

@traviskaufman
Copy link
Contributor Author

Spoke with @amsheehan offline who said LGTM.

@traviskaufman traviskaufman merged commit a9d46ab into master Jun 8, 2017
@traviskaufman traviskaufman deleted the feat/continuous-slider branch June 8, 2017 21:07
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants