Skip to content

Commit

Permalink
feat(slider): BREAKING: Implements m2 slider
Browse files Browse the repository at this point in the history
Upcoming work:

* implement theme
* add component tests

fixes #1885
fixes #2109
fixes #2108
fixes #523
fixes #1028
fixes #1671
fixes #1279

PiperOrigin-RevId: 367260030
  • Loading branch information
e111077 authored and Copybara-Service committed Jul 23, 2021
1 parent fe7cca3 commit dd3fdc5
Show file tree
Hide file tree
Showing 21 changed files with 1,507 additions and 664 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -22,6 +22,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Add `ariaHasPopup` property
- `menu`
- Add `innerAriaLabel` property
- **BREAKING:** `slider`
- Initial implementation of Material 2 slider
- Implementation is vastly different from M1 slider

## [v0.22.1] - 2021-07-14

Expand Down
116 changes: 75 additions & 41 deletions packages/slider/README.md
Expand Up @@ -4,8 +4,6 @@
Sliders allow users to make selections from a range of values.

<img src="images/basic.png" height="48px">

[Material Design Guidelines: sliders](https://material.io/design/components/sliders.html)

[Demo](https://material-components.github.io/material-components-web-components/demos/slider/)
Expand All @@ -24,12 +22,17 @@ npm install @material/mwc-slider
> [here](https://github.com/material-components/material-components-web-components#quick-start)
> for detailed instructions.
## ⚠️🚧 MWC Slider is currently under active development 🚧⚠️

work still to be done:

* enabling theme custom properties
* component testing (and any subsequent changes that result from testing)

## Example usage

### Continuous

<img src="images/basic.png" height="48pxx">

```html
<script type="module">
import '@material/mwc-slider';
Expand All @@ -40,79 +43,110 @@ npm install @material/mwc-slider

### Discrete

<img src="images/discrete.gif" height="80.5px">

```html
<mwc-slider
discrete
withTickMarks
step="5"
pin
markers
max="50"
value="10">
</mwc-slider>
```

### Styled
### Range Continuous

```html
<script type="module">
import '@material/mwc-slider/slider-range.js';
</script>

<mwc-slider-range
min="-20"
max="20"
valueStart="-10"
valueEnd="5">
</mwc-slider-range>
```

<img src="images/styled.gif" height="79px">
### Range Discrete

```html
<style>
mwc-slider {
--mdc-theme-secondary: orange;
--mdc-theme-text-primary-on-dark: green;
}
</style>
<mwc-slider
pin
markers
max="50"
value="10"
step="5">
</mwc-slider>
<mwc-slider-range
discrete
withTickMarks
step="1.5"
min="3"
max="12"
valueStart="4.5"
valueEnd="9">
</mwc-slider-range>
```

## API

### Properties/Attributes

| Name | Type | Default | Description
| --------- | --------- |-------- | -----------
| `value` | `number` | `0` | Current value of the slider.
| `min` | `number` | `0` | Minimum value of the slider.
| `max` | `number` | `100` | Maximum value of the slider.
| `step` | `number` | `0` | When defined, the slider will quantize (round to the nearest multiple) all values to match that step value, except for the minimum and maximum values, which can always be set. When 0, quantization is disabled.<br> **NOTE:** Throws when <0.
| `pin` | `boolean` | `false` | Shows the thumb pin on a discrete slider.<br> **NOTE:** Numbers displayed inside the slider will be rounded to at most 3 decimal digits.
| `markers` | `boolean` | `false` | Shows the tick marks for each step on the track when the slider is discrete.
#### &lt;mwc-slider>

| Name | Type | Default | Description
| --------------- | --------- |-------- | -----------
| `value` | `number` | `0` | Current value of the slider.
| `valueEnd` | `number` | `0` | Proxy of `value`.
| `min` | `number` | `0` | Value representing the minimum allowed value.
| `max` | `number` | `0` | Value representing the maximum allowed value.
| `disabled` | `boolean` | `false` | Disables the slider, preventing interaction.
| `step` | `number` | `1` | Step for value quantization.
| `discrete` | `boolean` | `false` | Displays a numeric value label upon pressing the thumb which allows the user to select an exact value.
| `withTickMarks` | `number` | `0` | Displays tick marks which represent predetermind values to which the user can move the slider. **NOTE:** the slider must be `discrete` to display tick marks, and to function correctly, there must be an integer amount of total steps within the range. i.e. `(max - min) % step === 0`

#### &lt;mwc-slider-range>

| Name | Type | Default | Description
| --------------- | --------- |-------- | -----------
| `valueStart` | `number` | `0` | Current value of the start thumb handle.
| `valueEnd` | `number` | `0` | Current value of the end thumb handle.
| `min` | `number` | `0` | Value representing the minimum allowed value.
| `max` | `number` | `0` | Value representing the maximum allowed value.
| `disabled` | `boolean` | `false` | Disables the slider, preventing interaction.
| `step` | `number` | `1` | Step for value quantization.
| `discrete` | `boolean` | `false` | Displays a numeric value label upon pressing the thumb which allows the user to select an exact value.
| `withTickMarks` | `number` | `0` | Displays tick marks which represent predetermind values to which the user can move the slider. **NOTE:** the slider must be `discrete` to display tick marks, and to function correctly, there must be an integer amount of total steps within the range. i.e. `(max - min) % step === 0`

### Methods

| Name | Description
| -------- | -------------
| `layout() => void` | Recomputes the dimensions and re-lays out the component. This should be called if the dimensions of the slider itself or any of its parent elements change programmatically (it is called automatically on resize and on mousedown / touchstart).
| `valueToValueIndicatorTransform(value: number) => string` | Override this method to transform the value of a given knob to the text that should be displayed in the value indicator of a discrete slider. Additionally, this will set the `aria-valuetext`.
| `layout(skipUpdateUI = false) => Promise<void>` | Recomputes the dimensions and re-lays out the component. This should be called if the dimensions of the slider itself or any of its parent elements change programmatically (it is called automatically on pointerdown). The skipUpdateUI parameter determines whether the UI should be updated alongside the internal clientRect model.

### Events

| Event Name | Target | Detail | Description
| ---------- | ------------ | ------------------ | -----------
| `input` | `mwc-slider` | `Slider` | Fired when the value changes due to user input. Similar to the [`input` event of the native `<input type="range">` element](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event), the `input` event will not fire when `value` is modified via JavaScript.
| `change` | `mwc-slider` | `Slider` | Fired when the value changes and the user has finished interacting with the slider. Similar to the [`change` event of the native `<input type="range">` element](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event), the `change` event will not fire when `value` is modified via JavaScript.
| Event Name | Detail | Description
| ---------- | ------------------ | -----------
| `input` | `{value: number, thumb: Thumb}`* | Fired when the value changes due to user input. Similar to the [`input` event of the native `<input type="range">` element](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event), the `input` event will not fire when `value` is modified via JavaScript.
| `change` | `{value: number, thumb: Thumb}`* | Fired when the value changes and the user has finished interacting with the slider. Similar to the [`change` event of the native `<input type="range">` element](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event), the `change` event will not fire when `value` is modified via JavaScript.

\* `Thumb` is a TypeScript enum exported by this component with types `START` and `END`

### CSS Custom Properties

⚠️🚧 In Progress 🚧⚠️

| Name | Default | Description
| ---------------------------------------- | ------- |------------
| `--mdc-slider-bg-color-behind-component` | ![](images/color_fff.png) `white` | Sets the color of the circle around the knob on the disabled slider to make it seem cut-out. May be necessary when placing a disabled slider on a different-colored background.

#### Global Custom Properties

⚠️🚧 In Progress and subject to change soon 🚧⚠️

This component exposes the following global [theming](https://github.com/material-components/material-components-web-components/blob/master/docs/theming.md)
custom properties.

| Name | Description
| ------------------------------------ | -----------
| `--mdc-theme-secondary` | Sets the color of the knob and filled track when slider is active.
| `--mdc-theme-text-primary-on-dark` | Sets the color of the text in the pin.
| Name | Description
| -------------------------- | -----------
| `--mdc-theme-primary` | Sets the color of the knob and filled track when slider is active.
| `--mdc-theme-on-primary` | Sets the color of the text in the pin.
| `--mdc-theme-on-surface` | Sets the color of the knob and filled track when slider is disabled.
| `--mdc-typography-subtitle2-<PROPERTY>` | Styles the typography of slider's value indicators.


Expand Down
7 changes: 7 additions & 0 deletions packages/slider/_index.scss
@@ -0,0 +1,7 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

@forward './slider-theme';
Empty file.
53 changes: 53 additions & 0 deletions packages/slider/_slider-theme.scss
@@ -0,0 +1,53 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

@use 'sass:map';
@use '@material/slider/slider-theme';
@use '@material/theme/shadow-dom';
@use '@material/theme/keys';
@use '@material/mwc-ripple/ripple-theme';

// stylelint-disable selector-class-pattern --
// Selector '.mdc-*' should only be used in this project.

@mixin theme($theme) {
@include slider-theme.theme-declare-custom-properties($theme);

@if shadow-dom.$css-selector-fallback-declarations {
@include theme-styles($theme);
}
}

@mixin theme-styles($theme) {
.mdc-slider {
@include slider-theme.theme-styles($theme);

.ripple {
$theme: keys.create-theme-properties($theme, $prefix: 'slider');

@include mdc-ripple-theme.theme(
(
hover-state-layer-color:
map.get($theme, hover-thumb-state-layer-color),
focus-state-layer-color:
map.get($theme, focus-thumb-state-layer-color),
pressed-state-layer-color:
map.get($theme, pressed-thumb-state-layer-color),
hover-state-layer-opacity:
map.get($theme, hover-thumb-state-layer-opacity),
focus-state-layer-opacity:
map.get($theme, focus-thumb-state-layer-opacity),
pressed-state-layer-opacity:
map.get($theme, pressed-thumb-state-layer-opacity),
)
);
}
}
}

@mixin theme-declare-custom-properties($theme) {
@include slider-theme.theme-declare-custom-properties($theme);
}
27 changes: 27 additions & 0 deletions packages/slider/_slider.scss
@@ -0,0 +1,27 @@
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

@use '@material/theme/theme';
@use '@material/slider/slider' as mdc-slider;

@mixin core-styles() {
// TODO: Use ripple theme-styles once available.
@include mdc-slider.without-ripple();
@include static-styles();
}

@mixin static-styles() {
:host {
outline: none;
display: block;
-webkit-tap-highlight-color: transparent;
}

.ripple {
// TODO: Use ripple's theme mixin once it actually works with mwc-ripple.
@include theme.property(--mdc-ripple-color, primary);
}
}
Binary file removed packages/slider/images/basic.png
Binary file not shown.
Binary file removed packages/slider/images/color_fff.png
Binary file not shown.
Binary file removed packages/slider/images/discrete.gif
Binary file not shown.
Binary file removed packages/slider/images/styled.gif
Binary file not shown.

0 comments on commit dd3fdc5

Please sign in to comment.