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

feat(slider): Implement continuous slider #487

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions demos/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<li><a href="layout-grid.html">Layout grid</a></li>
<li><a href="list.html">List</a></li>
<li><a href="select.html">Select</a></li>
<li><a href="slider.html">Slider</a></li>
<li><a href="simple-menu.html">Menu (simple)</a></li>
<li><a href="switch.html">Switch</a></li>
<li><a href="radio.html">Radio</a></li>
Expand Down
99 changes: 99 additions & 0 deletions demos/slider.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<!DOCTYPE html>
<!--
Copyright 2016 Google Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
-->
<html class="mdc-typography">

<head>
<meta charset="utf-8">
<title>MDC Slider Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="assets/material-components-web.css.js" charset="utf-8"></script>
<style type="text/css">
.mdc-theme--dark {
background-color: #303030;
}

.demo-container {
max-width: 500px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

#demo-wrapper {
padding: 4px;
padding-left: 0;
}
/* Hack to work around style-loader asynchronously loading styles. */
/* Equivalent to using mdc-typography's subheading2, which is used in the sass file. */

.mdc-slider {
font-family: Roboto, sans-serif;
font-size: 1rem;
font-weight: 400;
letter-spacing: .04em;
}
</style>
</head>

<body>
<main>
<h1>MDC slider</h1>

<section class="demo-container">
<h2>Continuous slider</h2>
<div class="mdc-slider" id="mdc-slider-default">
<input type="range" min="0" max="100" value="25" class="mdc-slider__input">
<div class="mdc-slider__background">
<div class="mdc-slider__background-lower"></div>
<div class="mdc-slider__background-upper"></div>
</div>
</div>
<p>Value <span id="slider-value"></span></p>
</section>

<section class="demo-container">
<h2>Continuous slider (accent color)</h2>
<div class="mdc-slider mdc-slider--accent" id="mdc-slider-accent">
<input type="range" min="0" max="100" value="25" class="mdc-slider__input">
<div class="mdc-slider__background">
<div class="mdc-slider__background-lower"></div>
<div class="mdc-slider__background-upper"></div>
</div>
</div>
</section>
</main>
<script src="assets/material-components-web.js"></script>
<script>
(function() {
mdc.slider.MDCSlider.attachTo(document.querySelector('#mdc-slider-default'));
mdc.slider.MDCSlider.attachTo(document.querySelector('#mdc-slider-accent'));

var slider = document.querySelector('#mdc-slider-default');
var continuousSlider = document.querySelector('#mdc-slider-default .mdc-slider__input');
var sliderValue = document.getElementById('slider-value');

sliderValue.textContent = continuousSlider.value;

slider.addEventListener('MDCSlider:change', function(evt) {
sliderValue.textContent = evt.detail.value;
});
})();
</script>
</body>

</html>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
"ripple",
"rtl",
"select",
"slider",
"snackbar",
"switch",
"textfield",
Expand Down
3 changes: 3 additions & 0 deletions packages/material-components-web/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import * as textfield from '@material/textfield';
import * as snackbar from '@material/snackbar';
import * as menu from '@material/menu';
import * as select from '@material/select';
import * as slider from '@material/slider';
import autoInit from '@material/auto-init';

// Register all components
Expand All @@ -41,6 +42,7 @@ autoInit.register('MDCSnackbar', snackbar.MDCSnackbar);
autoInit.register('MDCTextfield', textfield.MDCTextfield);
autoInit.register('MDCSimpleMenu', menu.MDCSimpleMenu);
autoInit.register('MDCSelect', select.MDCSelect);
// autoInit.register('MDCSelect', select.MDCSelect);

// Export all components.
export {
Expand All @@ -57,5 +59,6 @@ export {
textfield,
menu,
select,
slider,
autoInit,
};
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
@import "@material/radio/mdc-radio";
@import "@material/ripple/mdc-ripple";
@import "@material/select/mdc-select";
@import "@material/slider/mdc-slider";
@import "@material/snackbar/mdc-snackbar";
@import "@material/switch/mdc-switch";
@import "@material/textfield/mdc-textfield";
Expand Down
1 change: 1 addition & 0 deletions packages/material-components-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@material/radio": "^0.1.6",
"@material/ripple": "^0.5.0",
"@material/select": "^0.3.1",
"@material/slider": "^0.1.0",
"@material/snackbar": "^0.1.6",
"@material/switch": "^0.1.3",
"@material/textfield": "^0.2.4",
Expand Down
173 changes: 173 additions & 0 deletions packages/mdc-slider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# MDC Slider

The MDC Slider component provides a range input field adhering to the [Material Design Specification]( https://material.google.com/components/sliders.html).

It handles cross-browser differences in how the native input[range] element is styled and handles mouse and touch events.
It provides an `MDCSlider:change` custom event giving access to the current range value in a uniform event.
It requires JavaScript to handle the lower and upper track shading but includes a degraded version that does
not require any javascript for basic operation.

## Installation

```
npm install --save @material/slider
```

## Continuous slider usage

```html
<div class="mdc-slider" id="mdc-slider-default">
<input type="range" min="0" max="100" value="25" class="mdc-slider__input">
<div class="mdc-slider__background">
<div class="mdc-slider__background-lower"></div>
<div class="mdc-slider__background-upper"></div>
</div>
</div>
```

The slider component is driven by an underlying native input[range] element. This element is sized and positioned the same way as the slider component itself, allowing for proper behavior of assistive devices.

CSS classes:

| Class | Description |
| -------------------------------------- | -------------------------------------------------------------------------- |
| `mdc-slider` | Mandatory. Needs to be set on the root element of the component. |
| `mdc-mdc-slider__input` | Mandatory. Needs to be set on the input element. |
| `mdc-mdc-slider__background` | Mandatory. Needs to be set on the background div element. |
| `mdc-mdc-slider__background-lower` | Mandatory. Needs to be set on the background lower track div element. |
| `mdc-mdc-slider__background-upper` | Mandatory. Needs to be set on the background upper track div element. |
| `mdc-slider--accent` | Optional. Colors the slider with the theme accent color. |


> _NOTE_: _if you plan on using CSS-only_. The slider will not shade the lower and upper parts
> of the track on most browsers except IE.

### Using the JS component

MDC Slider ships with Component / Foundation classes which are used to provide a full-fidelity
Material Design text field component.

#### Including in code

##### ES2015

```javascript
import {MDCSlider, MDCSliderFoundation} from 'mdc-slider';
```

##### CommonJS

```javascript
const MDCSlider = require('mdc-slider');
const MDCSlider = MDCSlider.MDCSlider;
const MDCSliderFoundation = MDCSlider.MDCSliderFoundation;
```

##### AMD

```javascript
require(['path/to/mdc-slider'], MDCSlider => {
const MDCSlider = MDCSlider.MDCSlider;
const MDCSliderFoundation = MDCSlider.MDCSliderFoundation;
});
```

##### Global

```javascript
const MDCSlider = mdc.slider.MDCSlider;
const MDCSliderFoundation = mdc.slider.MDCSliderFoundation;
```

#### Automatic Instantiation

```javascript
mdc.slider.MDCSlider.attachTo(document.querySelector('.mdc-slider'));
```

#### Manual Instantiation

```javascript
import {MDCSlider} from 'mdc-slider';

const slider = new MDCSlider(document.querySelector('.mdc-slider'));
```


#### Using the slider component
```js
var slider = new mdc.slider.MDCSlider(document.querySelector('#mdc-slider-default'));

slider.listen('MDCSlider:change', function(evt) {
console.log(`value: {evt.detail.value}`);
})
```

### Slider component API

##### MDCSlider.disabled

Boolean. Proxies to the foundation's `isDisabled/setDisabled` methods when retrieved/set
respectively.

#### MDCSlider.destroy() => void

Cleans up handlers when slider is destroyed

##### MDCCheckbox.value

String. Returns the slider's value. Setting this property will update the underlying input control.
element.


### Slider Events

#### MDCSlider:change

Broadcast when a user actions on the `.mdc-slider__input` element.


### Using the foundation class


| Method Signature | Description |
| --- | --- |
| addClass(className: string) => void | Adds a class to the root element |
| removeClass(className: string) => void | Removes a class from the root element |
| `hasClass(className: string) => boolean` | Returns boolean indicating whether element has a given class. |
| addInputClass(className: string) => void | Adds a class to the input element |
| removeInputClass(className: string) => void | Removes a class from the inp[ut] element |
| setAttr(name: string, value: string) => void | Sets an attribute on the input element |
| registerHandler(type: string, handler: EventListener) => void | Registers an event listener on the native input element for the type |
| deregisterHandler(type: string, handler: EventListener) => void | Un-registers an event listener on the native input element for the type |
| registerRootHandler(type: string, handler: EventListener) => void | Registers an event listener on the root element for the type |
| deregisterRootHandler(type: string, handler: EventListener) => void | Un-registers an event listener on the root element for the type |
| getNativeInput() => {value: string, disabled: boolean} | Returns an object representing the native input element, with a similar API shape. The object returned should include the `value` and `disabled` properties. We _never_ alter the value within our code, however we _do_ update the disabled property, so if you choose to duck-type the return value for this method in your implementation it's important to keep this in mind. Also note that this method can return null, which the foundation will handle gracefully. |
| `hasNecessaryDom() => boolean` | Returns boolean indicating whether the necessary DOM is present (namely, the `mdc-slider__background` container). |
| `setLowerStyle(name: string, value: string) => void` | Sets the style `name` to `value` on the background-lower element. |
| `setUpperStyle(name: string, value: string) => void` | Sets the style `name` to `value` on the background-upper element. |
| `notifyChange(evtData: {value: number}) => void` | Broadcasts a change notification, passing along the `evtData` to the environment's event handling system. In our vanilla implementation, Custom Events are used for this. |

#### The full foundation API

##### MDCSliderFoundation.isDisabled() => boolean

Returns a boolean specifying whether or not the input is disabled.

##### MDCSliderFoundation.setDisabled(disabled: boolean)

Updates the input's disabled state.

##### MDCCheckboxFoundation.getValue() => string

Returns the value of `adapter.getNativeControl().value`. Returns `null` if `getNativeControl()`
does not return an object.

##### MDCCheckboxFoundation.setValue(value: string) => void

Sets the value of `adapter.getNativeControl().value`. Does nothing if `getNativeControl()` does
not return an object.

### Theming

MDC Slider components use the configured theme's primary color for its thumb and track.
31 changes: 31 additions & 0 deletions packages/mdc-slider/continuous/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

const ROOT = 'mdc-slider';

export const cssClasses = {
ROOT,
LOWEST_VALUE: `${ROOT}--lowest-value`,
UPGRADED: `${ROOT}--upgraded`,
};

export const strings = {
INPUT_SELECTOR: `.${ROOT}__input`,
BACKGROUND_SELECTOR: `.${ROOT}__background`,
BACKGROUND_LOWER_SELECTOR: `.${ROOT}__background-lower`,
BACKGROUND_UPPER_SELECTOR: `.${ROOT}__background-upper`,
ARIA_VALUENOW: 'aria-valuenow',
};
Loading