Skip to content

Commit f58102c

Browse files
committed
feat: enhance RangeSlider with style customization props and accessibility improvements
1 parent 11a33af commit f58102c

File tree

2 files changed

+102
-62
lines changed

2 files changed

+102
-62
lines changed

README.md

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ A high-performance React Native range slider component built with react-native-r
1313
- 📱 Pure JavaScript implementation
1414
- 🔧 Configurable min/max values and step sizes
1515
- 🎛 Support for minimum distance between markers
16-
- 🔒 Optional snap-to-step behavior
17-
- 🌐 RTL (Right-to-Left) support (automatic)
16+
- 🌐 RTL (Right-to-Left) support
1817

1918
## Performance Benefits
2019

@@ -54,14 +53,22 @@ const YourComponent = () => {
5453
min={0}
5554
max={100}
5655
step={1}
57-
onValuesChange={handleValuesChange}
58-
// Customize appearance
59-
selectedTrackColor="#2196F3"
60-
unselectedTrackColor="#CECECE"
61-
markerColor="white"
62-
// Optional behavior props
63-
snapsToStep={true}
56+
// Style customization
57+
selectedTrackStyle={{ backgroundColor: '#2196F3' }}
58+
unselectedTrackStyle={{ backgroundColor: '#CECECE' }}
59+
markerStyle={{ backgroundColor: 'white' }}
60+
pressedMarkerStyle={{ transform: [{ scale: 1.2 }] }}
61+
// Behavior
62+
enabled={true}
6463
allowOverlap={false}
64+
showMarkerLines={true}
65+
// Callbacks
66+
onValuesChange={handleValuesChange}
67+
onValuesChangeStart={(values) => console.log('Started:', values)}
68+
onValuesChangeFinish={(values) => console.log('Finished:', values)}
69+
// Accessibility
70+
leftMarkerAccessibilityLabel="Minimum value"
71+
rightMarkerAccessibilityLabel="Maximum value"
6572
/>
6673
);
6774
};
@@ -80,26 +87,58 @@ const YourComponent = () => {
8087
| trackHeight | number | No | 2.5 | Height of slider track |
8188
| minimumDistance | number | No | 16 | Minimum distance between markers |
8289
| enabled | boolean | No | true | Enable/disable slider |
83-
| snapsToStep | boolean | No | false | Snap values to steps |
8490
| allowOverlap | boolean | No | false | Allow markers to overlap |
91+
| showMarkerLines | boolean | No | true | Show marker lines inside handles |
92+
| selectedTrackStyle | object | No | - | Style object for selected track portion |
93+
| unselectedTrackStyle | object | No | - | Style object for unselected track portion |
94+
| markerStyle | object | No | - | Style object for both markers |
95+
| pressedMarkerStyle | object | No | - | Style applied when marker is pressed |
96+
| containerStyle | object | No | - | Style for the container view |
97+
| onValuesChange | function | No | () => {} | Called while dragging |
98+
| onValuesChangeStart | function | No | () => {} | Called when drag starts |
99+
| onValuesChangeFinish | function | No | () => {} | Called when drag ends |
100+
| leftMarkerAccessibilityLabel | string | No | "Left handle" | Accessibility label for left marker |
101+
| rightMarkerAccessibilityLabel | string | No | "Right handle" | Accessibility label for right marker |
85102

86103
## Styling
87104

88-
The component is highly customizable through style props:
105+
The component supports several style customization props:
89106

90107
```javascript
91108
<RangeSlider
92-
// Colors
93-
selectedTrackColor="#2196F3"
94-
unselectedTrackColor="#CECECE"
95-
markerColor="white"
109+
// Track styles
110+
selectedTrackStyle={{
111+
backgroundColor: '#2196F3',
112+
height: 4,
113+
}}
114+
unselectedTrackStyle={{
115+
backgroundColor: '#CECECE',
116+
height: 4,
117+
}}
118+
119+
// Marker styles
120+
markerStyle={{
121+
backgroundColor: 'white',
122+
borderColor: '#CECECE',
123+
borderWidth: 0.5,
124+
shadowColor: '#000',
125+
shadowOffset: { width: 0, height: 2 },
126+
shadowOpacity: 0.25,
127+
shadowRadius: 3.84,
128+
}}
129+
130+
// Pressed marker style
131+
pressedMarkerStyle={{
132+
transform: [{ scale: 1.2 }],
133+
}}
134+
135+
// Container style
136+
containerStyle={{
137+
height: 50,
138+
}}
96139

97-
// Custom styles
98-
selectedStyle={{...}}
99-
unselectedStyle={{...}}
100-
markerStyle={{...}}
101-
pressedMarkerStyle={{...}}
102-
containerStyle={{...}}
140+
// Show/hide marker lines
141+
showMarkerLines={true}
103142
/>
104143
```
105144

src/RangeSlider.js

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ const DEFAULT_VALUES = {
2424
MARKER_SIZE: 32,
2525
TRACK_HEIGHT: 2.5,
2626
STEP: 1,
27-
MARKER_COLOR: 'white',
28-
SELECTED_TRACK_COLOR: '#2196F3',
29-
UNSELECTED_TRACK_COLOR: '#CECECE',
3027
LEFT_MARKER_LABEL: 'Left handle',
3128
RIGHT_MARKER_LABEL: 'Right handle',
3229
MINIMUM_DISTANCE: MIN_MARKER_SPACING,
30+
SHOW_MARKER_LINES: true,
3331
};
3432

3533
const createDynamicStyles = (props) => ({
@@ -40,20 +38,18 @@ const createDynamicStyles = (props) => ({
4038
track: {
4139
position: 'absolute',
4240
height: props.trackHeight,
43-
backgroundColor: props.unselectedTrackColor,
4441
width: props.sliderWidth,
4542
left: HORIZONTAL_PADDING,
4643
},
4744
selectedTrack: {
4845
position: 'absolute',
4946
height: props.trackHeight,
50-
backgroundColor: props.selectedTrackColor,
5147
},
5248
marker: {
5349
height: props.markerSize,
5450
width: props.markerSize,
5551
borderRadius: props.markerSize / 2,
56-
backgroundColor: props.markerColor,
52+
backgroundColor: 'white', // Move default color here
5753
position: 'absolute',
5854
shadowColor: '#000',
5955
shadowOffset: { width: 0, height: 2 },
@@ -82,8 +78,8 @@ const RangeSlider = forwardRef(
8278
step = DEFAULT_VALUES.STEP,
8379

8480
// Style props
85-
selectedStyle,
86-
unselectedStyle,
81+
selectedTrackStyle,
82+
unselectedTrackStyle,
8783
markerStyle,
8884
pressedMarkerStyle,
8985
containerStyle,
@@ -93,13 +89,9 @@ const RangeSlider = forwardRef(
9389
markerSize = DEFAULT_VALUES.MARKER_SIZE,
9490
trackHeight = DEFAULT_VALUES.TRACK_HEIGHT,
9591
minimumDistance = DEFAULT_VALUES.MINIMUM_DISTANCE,
96-
markerColor = DEFAULT_VALUES.MARKER_COLOR,
97-
selectedTrackColor = DEFAULT_VALUES.SELECTED_TRACK_COLOR,
98-
unselectedTrackColor = DEFAULT_VALUES.UNSELECTED_TRACK_COLOR,
9992

10093
// Behavior props
10194
enabled = true,
102-
snapsToStep = false,
10395
allowOverlap = false,
10496

10597
// Callback props
@@ -110,6 +102,9 @@ const RangeSlider = forwardRef(
110102
// Accessibility props
111103
leftMarkerAccessibilityLabel = DEFAULT_VALUES.LEFT_MARKER_LABEL,
112104
rightMarkerAccessibilityLabel = DEFAULT_VALUES.RIGHT_MARKER_LABEL,
105+
106+
// Marker lines prop
107+
showMarkerLines = DEFAULT_VALUES.SHOW_MARKER_LINES,
113108
},
114109
ref
115110
) => {
@@ -186,15 +181,13 @@ const RangeSlider = forwardRef(
186181
const leftValue = convertPositionToValue(leftPosition);
187182
const rightValue = convertPositionToValue(rightPosition);
188183

189-
if (snapsToStep) {
190-
return [
191-
Math.round(leftValue / step) * step,
192-
Math.round(rightValue / step) * step,
193-
];
194-
}
195-
return [leftValue, rightValue];
184+
// Always round values according to step size
185+
return [
186+
Math.round(leftValue / step) * step,
187+
Math.round(rightValue / step) * step,
188+
];
196189
},
197-
[convertPositionToValue, step, snapsToStep]
190+
[convertPositionToValue, step]
198191
);
199192

200193
const leftGesture = useAnimatedGestureHandler({
@@ -293,9 +286,6 @@ const RangeSlider = forwardRef(
293286
sliderWidth,
294287
markerSize,
295288
trackHeight,
296-
markerColor,
297-
selectedTrackColor,
298-
unselectedTrackColor,
299289
enabled,
300290
});
301291

@@ -306,12 +296,19 @@ const RangeSlider = forwardRef(
306296
<View
307297
style={[staticStyles.container, containerStyle, { direction: 'ltr' }]}
308298
>
309-
<View style={[dynamicStyles.track, unselectedStyle]} />
299+
<View
300+
style={[
301+
dynamicStyles.track,
302+
{ backgroundColor: '#CECECE' }, // Default color
303+
unselectedTrackStyle,
304+
]}
305+
/>
310306

311307
<Animated.View
312308
style={[
313309
dynamicStyles.selectedTrack,
314-
selectedStyle,
310+
{ backgroundColor: '#2196F3' }, // Default color
311+
selectedTrackStyle,
315312
animatedTrackStyle,
316313
]}
317314
/>
@@ -334,9 +331,13 @@ const RangeSlider = forwardRef(
334331
leftMarkerStyle,
335332
]}
336333
>
337-
<View style={staticStyles.markerLine} />
338-
<View style={staticStyles.markerLine} />
339-
<View style={staticStyles.markerLine} />
334+
{showMarkerLines && (
335+
<>
336+
<View style={staticStyles.markerLine} />
337+
<View style={staticStyles.markerLine} />
338+
<View style={staticStyles.markerLine} />
339+
</>
340+
)}
340341
</Animated.View>
341342
</PanGestureHandler>
342343

@@ -358,9 +359,13 @@ const RangeSlider = forwardRef(
358359
rightMarkerStyle,
359360
]}
360361
>
361-
<View style={staticStyles.markerLine} />
362-
<View style={staticStyles.markerLine} />
363-
<View style={staticStyles.markerLine} />
362+
{showMarkerLines && (
363+
<>
364+
<View style={staticStyles.markerLine} />
365+
<View style={staticStyles.markerLine} />
366+
<View style={staticStyles.markerLine} />
367+
</>
368+
)}
364369
</Animated.View>
365370
</PanGestureHandler>
366371
</View>
@@ -404,8 +409,8 @@ RangeSlider.propTypes = {
404409
step: PropTypes.number,
405410

406411
// Style props
407-
selectedStyle: PropTypes.object,
408-
unselectedStyle: PropTypes.object,
412+
selectedTrackStyle: PropTypes.object,
413+
unselectedTrackStyle: PropTypes.object,
409414
markerStyle: PropTypes.object,
410415
pressedMarkerStyle: PropTypes.object,
411416
containerStyle: PropTypes.object,
@@ -415,13 +420,9 @@ RangeSlider.propTypes = {
415420
markerSize: PropTypes.number,
416421
trackHeight: PropTypes.number,
417422
minimumDistance: PropTypes.number,
418-
markerColor: PropTypes.string,
419-
selectedTrackColor: PropTypes.string,
420-
unselectedTrackColor: PropTypes.string,
421423

422424
// Behavior props
423425
enabled: PropTypes.bool,
424-
snapsToStep: PropTypes.bool,
425426
allowOverlap: PropTypes.bool,
426427

427428
// Callback props
@@ -432,6 +433,9 @@ RangeSlider.propTypes = {
432433
// Accessibility props
433434
leftMarkerAccessibilityLabel: PropTypes.string,
434435
rightMarkerAccessibilityLabel: PropTypes.string,
436+
437+
// Marker lines prop
438+
showMarkerLines: PropTypes.bool,
435439
};
436440

437441
RangeSlider.defaultProps = {
@@ -440,16 +444,13 @@ RangeSlider.defaultProps = {
440444
markerSize: DEFAULT_VALUES.MARKER_SIZE,
441445
trackHeight: DEFAULT_VALUES.TRACK_HEIGHT,
442446
enabled: true,
443-
snapsToStep: false,
444447
allowOverlap: false,
445-
markerColor: DEFAULT_VALUES.MARKER_COLOR,
446-
selectedTrackColor: DEFAULT_VALUES.SELECTED_TRACK_COLOR,
447-
unselectedTrackColor: DEFAULT_VALUES.UNSELECTED_TRACK_COLOR,
448448
onValuesChange: () => {},
449449
onValuesChangeFinish: () => {},
450450
onValuesChangeStart: () => {},
451451
leftMarkerAccessibilityLabel: DEFAULT_VALUES.LEFT_MARKER_LABEL,
452452
rightMarkerAccessibilityLabel: DEFAULT_VALUES.RIGHT_MARKER_LABEL,
453+
showMarkerLines: DEFAULT_VALUES.SHOW_MARKER_LINES,
453454
};
454455

455456
export default RangeSlider;

0 commit comments

Comments
 (0)