Skip to content

Commit

Permalink
[Slider] Add a custom scale support (#19158)
Browse files Browse the repository at this point in the history
  • Loading branch information
netochaves authored and oliviertassinari committed Jan 17, 2020
1 parent aa61ced commit 2373c22
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/pages/api/slider.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ You can learn more about the difference by [reading this guide](/guides/minimizi
| <span class="prop-name">onChange</span> | <span class="prop-type">func</span> | | Callback function that is fired when the slider's value changed.<br><br>**Signature:**<br>`function(event: object, value: any) => void`<br>*event:* The event source of the callback.<br>*value:* The new value. |
| <span class="prop-name">onChangeCommitted</span> | <span class="prop-type">func</span> | | Callback function that is fired when the `mouseup` is triggered.<br><br>**Signature:**<br>`function(event: object, value: any) => void`<br>*event:* The event source of the callback.<br>*value:* The new value. |
| <span class="prop-name">orientation</span> | <span class="prop-type">'horizontal'<br>&#124;&nbsp;'vertical'</span> | <span class="prop-default">'horizontal'</span> | The slider orientation. |
| <span class="prop-name">scale</span> | <span class="prop-type">func</span> | <span class="prop-default">x => x</span> | A transformation function, to change the scale of the slider. |
| <span class="prop-name">step</span> | <span class="prop-type">number</span> | <span class="prop-default">1</span> | The granularity with which the slider can step through values. (A "discrete" slider.) The `min` prop serves as the origin for the valid values. We recommend (max - min) to be evenly divisible by the step.<br>When step is `null`, the thumb can only be slid onto marks provided with the `marks` prop. |
| <span class="prop-name">ThumbComponent</span> | <span class="prop-type">elementType</span> | <span class="prop-default">'span'</span> | The component used to display the value label. |
| <span class="prop-name">track</span> | <span class="prop-type">'normal'<br>&#124;&nbsp;false<br>&#124;&nbsp;'inverted'</span> | <span class="prop-default">'normal'</span> | The track presentation:<br>- `normal` the track will render a bar representing the slider value. - `inverted` the track will render a bar representing the remaining slider value. - `false` the track will render without a bar. |
Expand Down
39 changes: 39 additions & 0 deletions docs/src/pages/components/slider/NonLinearSlider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import Typography from '@material-ui/core/Typography';
import Slider from '@material-ui/core/Slider';

function valueLabelFormat(value) {
const [coefficient, exponent] = value
.toExponential()
.split('e')
.map(item => Number(item));
return `${Math.round(coefficient)}e^${exponent}`;
}

export default function NonLinearSlider() {
const [value, setValue] = React.useState(1);

const handleChange = (event, newValue) => {
setValue(newValue);
};

return (
<div>
<Typography id="non-linear-slider" gutterBottom>
Temperature range
</Typography>
<Slider
value={value}
min={0}
step={0.1}
max={6}
scale={x => x ** 10}
getAriaValueText={valueLabelFormat}
valueLabelFormat={valueLabelFormat}
onChange={handleChange}
valueLabelDisplay="auto"
aria-labelledby="non-linear-slider"
/>
</div>
);
}
39 changes: 39 additions & 0 deletions docs/src/pages/components/slider/NonLinearSlider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import Typography from '@material-ui/core/Typography';
import Slider from '@material-ui/core/Slider';

function valueLabelFormat(value: number) {
const [coefficient, exponent] = value
.toExponential()
.split('e')
.map(item => Number(item));
return `${Math.round(coefficient)}e^${exponent}`;
}

export default function NonLinearSlider() {
const [value, setValue] = React.useState<number | number[]>(1);

const handleChange = (event: any, newValue: number | number[]) => {
setValue(newValue);
};

return (
<div>
<Typography id="non-linear-slider" gutterBottom>
Temperature range
</Typography>
<Slider
value={value}
min={0}
step={0.1}
max={6}
scale={x => x ** 10}
getAriaValueText={valueLabelFormat}
valueLabelFormat={valueLabelFormat}
onChange={handleChange}
valueLabelDisplay="auto"
aria-labelledby="non-linear-slider"
/>
</div>
);
}
7 changes: 7 additions & 0 deletions docs/src/pages/components/slider/slider.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ The track can be inverted with `track="inverted"`.

{{"demo": "pages/components/slider/TrackInvertedSlider.js"}}

## Non-linear scale

You can use the `scale` prop to represent the `value` on a different scale.
For instance, in the following demo, the value *x* represents the power of *10^x*.

{{"demo": "pages/components/slider/NonLinearSlider.js"}}

## Accessibility

(WAI-ARIA: https://www.w3.org/TR/wai-aria-practices/#slider)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/pages/components/steppers/steppers.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ determine when all steps are completed (or even if they need to be completed).

{{"demo": "pages/components/steppers/HorizontalNonLinearStepper.js", "bg": true}}

### Non Linear - Alternative Label
### Non-linear - Alternative Label

Labels can be placed below the step icon by setting the `alternativeLabel` prop on the `Stepper` component.

{{"demo": "pages/components/steppers/HorizontalNonLinearAlternativeLabelStepper.js", "bg": true}}

### Non Linear - Error Step
### Non-linear - Error Step

{{"demo": "pages/components/steppers/HorizontalNonLinearStepperWithError.js", "bg": true}}

Expand Down
1 change: 1 addition & 0 deletions packages/material-ui/src/Slider/Slider.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface SliderProps
onChangeCommitted?: (event: React.ChangeEvent<{}>, value: number | number[]) => void;
orientation?: 'horizontal' | 'vertical';
step?: number | null;
scale?: (value: number) => number;
ThumbComponent?: React.ElementType<React.HTMLAttributes<HTMLSpanElement>>;
track?: 'normal' | false | 'inverted';
value?: number | number[];
Expand Down
17 changes: 12 additions & 5 deletions packages/material-ui/src/Slider/Slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ const Slider = React.forwardRef(function Slider(props, ref) {
onChangeCommitted,
onMouseDown,
orientation = 'horizontal',
scale = Identity,
step = 1,
ThumbComponent = 'span',
track = 'normal',
Expand Down Expand Up @@ -742,7 +743,7 @@ const Slider = React.forwardRef(function Slider(props, ref) {
className={classes.valueLabel}
value={
typeof valueLabelFormat === 'function'
? valueLabelFormat(value, index)
? valueLabelFormat(scale(value), index)
: valueLabelFormat
}
index={index}
Expand All @@ -762,10 +763,12 @@ const Slider = React.forwardRef(function Slider(props, ref) {
aria-label={getAriaLabel ? getAriaLabel(index) : ariaLabel}
aria-labelledby={ariaLabelledby}
aria-orientation={orientation}
aria-valuemax={max}
aria-valuemin={min}
aria-valuenow={value}
aria-valuetext={getAriaValueText ? getAriaValueText(value, index) : ariaValuetext}
aria-valuemax={scale(max)}
aria-valuemin={scale(min)}
aria-valuenow={scale(value)}
aria-valuetext={
getAriaValueText ? getAriaValueText(scale(value), index) : ariaValuetext
}
onKeyDown={handleKeyDown}
onFocus={handleFocus}
onBlur={handleBlur}
Expand Down Expand Up @@ -895,6 +898,10 @@ Slider.propTypes = {
* The slider orientation.
*/
orientation: PropTypes.oneOf(['horizontal', 'vertical']),
/**
* A transformation function, to change the scale of the slider.
*/
scale: PropTypes.func,
/**
* The granularity with which the slider can step through values. (A "discrete" slider.)
* The `min` prop serves as the origin for the valid values.
Expand Down

0 comments on commit 2373c22

Please sign in to comment.