Skip to content

Commit 62ae1c5

Browse files
feat(component): new Slider component (#144)
* Add slider component (WIP) * Refactor and update slider * Add test coverage * Refactor code, update styling and snapshots * Fix .stylelintrc file * Fix comment * Refactor scss file * Refactor scss file, add knobs * Refactor code * Revert story changes * Revert lock file changes * Merge master
1 parent b7a8250 commit 62ae1c5

11 files changed

Lines changed: 655 additions & 86 deletions

File tree

.stylelintrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
"indentation": 4,
1212
"no-missing-end-of-source-newline": true,
1313
"selector-attribute-brackets-space-inside": "never",
14+
"selector-pseudo-class-no-unknown": [true, {
15+
ignorePseudoClasses: ["global"]
16+
}],
1417
"selector-attribute-quotes": "always",
1518
"selector-max-id": 0,
1619
"unit-case": "lower",

package-lock.json

Lines changed: 368 additions & 85 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@
4747
"dependencies": {
4848
"@babel/polyfill": "7.0.0",
4949
"css-vars-ponyfill": "1.16.4",
50+
"prop-types": "^15.7.2",
51+
"rc-slider": "8.6.13",
5052
"downshift": "3.2.10",
5153
"fast-memoize": "2.5.1",
52-
"prop-types": "^15.7.2",
5354
"react-modal": "3.9.1"
5455
},
5556
"peerDependencies": {

src/components/Slider/Slider.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import RCSlider from 'rc-slider/lib/Slider';
4+
import './Slider.scss';
5+
6+
const Slider = React.forwardRef((props, ref) => <RCSlider {...props} ref={ref} />);
7+
8+
Slider.displayName = 'Slider';
9+
10+
Slider.propTypes = {
11+
/** Set initial value of slider */
12+
initialValue: PropTypes.number,
13+
/** The minimum value of the slider */
14+
min: PropTypes.number,
15+
/** The maximum value of the slider */
16+
max: PropTypes.number,
17+
/**
18+
* Value to be added or subtracted on each step the slider makes.
19+
* Must be greater than zero, and max - min should be evenly divisible by the step value.
20+
*/
21+
step: PropTypes.number
22+
};
23+
24+
Slider.defaultProps = {
25+
initialValue: 0,
26+
min: 0,
27+
max: 100,
28+
step: 1
29+
};
30+
31+
export default Slider;

src/components/Slider/Slider.scss

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Definition of basic slider variables
2+
$slider-rail-height: 8px;
3+
$slider-handle-size: 24px;
4+
$slider-handle-border-width: 6px;
5+
6+
// Centering adjustments of the handle on the rail
7+
$slider-handle-adjust-left: -($slider-handle-size / 2);
8+
$slider-handle-adjust-top: -(($slider-handle-size / 2) - ($slider-rail-height / 2));
9+
10+
// Definitions of variables for paddings, shadows, etc.
11+
$slider-padding: 5px 0;
12+
$slider-box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, .2);
13+
$slider-handle-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5);
14+
15+
:global .rc-slider-track {
16+
position: absolute;
17+
height: $slider-rail-height;
18+
border-radius: $slider-rail-height / 2;
19+
background-color: var(--color-brand);
20+
transition: background-color var(--transition-duration) ease;
21+
box-shadow: $slider-box-shadow
22+
}
23+
24+
:global .rc-slider-handle {
25+
position: absolute;
26+
width: $slider-handle-size;
27+
height: $slider-handle-size;
28+
margin-left: $slider-handle-adjust-left;
29+
margin-top: $slider-handle-adjust-top;
30+
border: solid $slider-handle-border-width white;
31+
border-radius: 50%;
32+
transition: background-color var(--transition-duration) ease;
33+
background-color: var(--color-brand);
34+
box-shadow: $slider-handle-box-shadow;
35+
36+
&:focus {
37+
outline: none;
38+
}
39+
}
40+
41+
:global .rc-slider {
42+
position: relative;
43+
height: $slider-rail-height;
44+
padding: $slider-padding;
45+
width: 100%;
46+
47+
&:hover .rc-slider-track {
48+
background-color: var(--color-brand-40);
49+
}
50+
51+
&:hover .rc-slider-handle {
52+
background-color: var(--color-primary);
53+
}
54+
55+
* {
56+
box-sizing: border-box;
57+
}
58+
}
59+
60+
:global .rc-slider-rail {
61+
position: absolute;
62+
width: 100%;
63+
background-color: white;
64+
height: $slider-rail-height;
65+
border-radius: $slider-rail-height / 2;
66+
box-shadow: $slider-box-shadow
67+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import toJson from 'enzyme-to-json';
3+
import Slider from '../Slider';
4+
5+
describe('Slider component', () => {
6+
it('should render component correctly', () => {
7+
const wrapper = mount(<Slider />);
8+
expect(toJson(wrapper)).toMatchSnapshot();
9+
});
10+
it('should render correctly with ref', () => {
11+
const ref = React.createRef();
12+
mount(<Slider ref={ref} />);
13+
14+
expect(ref.current.props.Component.displayName).toEqual('Slider');
15+
});
16+
});
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Slider component should render component correctly 1`] = `
4+
<Slider
5+
initialValue={0}
6+
max={100}
7+
min={0}
8+
step={1}
9+
>
10+
<ComponentEnhancer(undefined)
11+
activeDotStyle={Object {}}
12+
className=""
13+
disabled={false}
14+
dotStyle={Object {}}
15+
dots={false}
16+
handle={[Function]}
17+
handleStyle={
18+
Array [
19+
Object {},
20+
]
21+
}
22+
included={true}
23+
initialValue={0}
24+
marks={Object {}}
25+
max={100}
26+
min={0}
27+
onAfterChange={[Function]}
28+
onBeforeChange={[Function]}
29+
onChange={[Function]}
30+
prefixCls="rc-slider"
31+
railStyle={Object {}}
32+
step={1}
33+
trackStyle={
34+
Array [
35+
Object {},
36+
]
37+
}
38+
vertical={false}
39+
>
40+
<div
41+
className="rc-slider"
42+
onBlur={[Function]}
43+
onFocus={[Function]}
44+
onKeyDown={[Function]}
45+
onMouseDown={[Function]}
46+
onMouseUp={[Function]}
47+
onTouchStart={[Function]}
48+
>
49+
<div
50+
className="rc-slider-rail"
51+
style={Object {}}
52+
/>
53+
<Track
54+
className="rc-slider-track"
55+
included={true}
56+
length={0}
57+
offset={0}
58+
style={Object {}}
59+
vertical={false}
60+
>
61+
<div
62+
className="rc-slider-track"
63+
style={
64+
Object {
65+
"left": "0%",
66+
"width": "0%",
67+
}
68+
}
69+
/>
70+
</Track>
71+
<Steps
72+
activeDotStyle={Object {}}
73+
dotStyle={Object {}}
74+
dots={false}
75+
included={true}
76+
lowerBound={0}
77+
marks={Object {}}
78+
max={100}
79+
min={0}
80+
prefixCls="rc-slider"
81+
step={1}
82+
upperBound={0}
83+
vertical={false}
84+
>
85+
<div
86+
className="rc-slider-step"
87+
/>
88+
</Steps>
89+
<Handle
90+
className="rc-slider-handle"
91+
disabled={false}
92+
key="0"
93+
max={100}
94+
min={0}
95+
offset={0}
96+
prefixCls="rc-slider"
97+
style={Object {}}
98+
value={0}
99+
vertical={false}
100+
>
101+
<div
102+
aria-disabled={false}
103+
aria-valuemax={100}
104+
aria-valuemin={0}
105+
aria-valuenow={0}
106+
className="rc-slider-handle"
107+
onBlur={[Function]}
108+
onKeyDown={[Function]}
109+
onMouseDown={[Function]}
110+
role="slider"
111+
style={
112+
Object {
113+
"left": "0%",
114+
}
115+
}
116+
tabIndex={0}
117+
/>
118+
</Handle>
119+
<Marks
120+
className="rc-slider-mark"
121+
included={true}
122+
lowerBound={0}
123+
marks={Object {}}
124+
max={100}
125+
min={0}
126+
onClickLabel={[Function]}
127+
upperBound={0}
128+
vertical={false}
129+
>
130+
<div
131+
className="rc-slider-mark"
132+
/>
133+
</Marks>
134+
</div>
135+
</ComponentEnhancer(undefined)>
136+
</Slider>
137+
`;

src/components/Slider/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './Slider';

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ export { Tabs, Tab, TabContent, TabItem, TabMenu } from './components/Tabs';
2525
export { default as Teaser } from './components/Teaser';
2626
export { Text, MarkedText } from './components/Text';
2727
export { default as TextArea } from './components/TextArea';
28+
export { default as Slider } from './components/Slider';
2829
export { default } from './utils/OneUI';

stories/Slider.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import { storiesOf } from '@storybook/react';
3+
import { Slider } from '@textkernel/oneui';
4+
import { number, withKnobs } from '@storybook/addon-knobs';
5+
6+
storiesOf('Slider', module)
7+
.addDecorator(withKnobs)
8+
.add(
9+
'Slider',
10+
() => (
11+
<Slider
12+
min={number('Min value', 0)}
13+
max={number('Max value', 100)}
14+
step={number('Step', 1)}
15+
defaultValue={10}
16+
onChange={value => console.log(value)}
17+
/>
18+
),
19+
{
20+
info: {
21+
text: `
22+
## Usage information
23+
This component is a wrapper around [rc-slider](https://github.com/react-component/slider).
24+
25+
Full list of props available to pass you can find [here](https://github.com/react-component/slider#api).`
26+
}
27+
}
28+
);

0 commit comments

Comments
 (0)