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

Commit 5d732da

Browse files
scharingerTigge
authored andcommitted
fix(slider): snap to ticks using keyboard buttons
Snap to the ticks when using the keyboard to move the slider.
1 parent 8222d04 commit 5d732da

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

packages/core/src/Slider/index.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,14 @@ export const Slider: React.FC<SliderProps> = ({
366366
[tickMarkers]
367367
)
368368

369+
/** Convert from the slider track value format (0.0 - 1.0) to the format used by the value. */
370+
const convertDecimalToValue = useCallback(
371+
x => min + x * (max - min),
372+
[min, max]
373+
)
374+
375+
const shouldSnapToTick = snap && tickMarkers.length > 0
376+
369377
// Computes the new value and passed it to the handleChange callback
370378
const handleClick = useCallback(
371379
(e: PointerEvent | React.MouseEvent<BaseElement>) => {
@@ -377,15 +385,15 @@ export const Slider: React.FC<SliderProps> = ({
377385
let x = clamp((e.pageX - left) / width)
378386

379387
// Find x position if snap is enabled
380-
if (e.type !== 'pointermove' && snap && tickMarkers.length > 0) {
388+
if (e.type !== 'pointermove' && shouldSnapToTick) {
381389
const snapTo = snapValues.reduce((a, b) =>
382390
Math.abs(b - x) < Math.abs(a - x) ? b : a
383391
)
384392

385393
x = snapTo
386394
}
387395

388-
handleChange(min + x * (max - min))
396+
handleChange(convertDecimalToValue(x))
389397
}
390398
},
391399
[handleChange, max, min, onClick, snap, snapValues, tickMarkers.length]
@@ -421,6 +429,15 @@ export const Slider: React.FC<SliderProps> = ({
421429
}
422430
}, [handleClick, pressed])
423431

432+
const getNextSnap = useCallback(
433+
() => snapValues.find(snapValue => snapValue > fraction),
434+
[snapValues, fraction]
435+
)
436+
const getPreviousSnap = useCallback(
437+
() => snapValues.reverse().find(snapValue => snapValue < fraction),
438+
[snapValues, fraction]
439+
)
440+
424441
// Keyboard support
425442
const handleKeyDown = useCallback<React.KeyboardEventHandler<BaseElement>>(
426443
event => {
@@ -442,23 +459,31 @@ export const Slider: React.FC<SliderProps> = ({
442459
switch (event.key) {
443460
case SliderKeys.ArrowRight:
444461
case SliderKeys.ArrowUp: {
445-
newValue = value + onePercent
462+
newValue = shouldSnapToTick
463+
? convertDecimalToValue(getNextSnap())
464+
: value + onePercent
446465
break
447466
}
448467

449468
case SliderKeys.ArrowLeft:
450469
case SliderKeys.ArrowDown: {
451-
newValue = value - onePercent
470+
newValue = shouldSnapToTick
471+
? convertDecimalToValue(getPreviousSnap())
472+
: value - onePercent
452473
break
453474
}
454475

455476
case SliderKeys.PageUp: {
456-
newValue = value + onePercent * 10
477+
newValue = shouldSnapToTick
478+
? convertDecimalToValue(getNextSnap())
479+
: value + onePercent * 10
457480
break
458481
}
459482

460483
case SliderKeys.PageDown: {
461-
newValue = value - onePercent * 10
484+
newValue = shouldSnapToTick
485+
? convertDecimalToValue(getPreviousSnap())
486+
: value - onePercent * 10
462487
break
463488
}
464489

@@ -475,6 +500,7 @@ export const Slider: React.FC<SliderProps> = ({
475500
default:
476501
}
477502

503+
// keep new value inside min and max
478504
if (newValue !== undefined) {
479505
if (newValue > max) {
480506
newValue = max

0 commit comments

Comments
 (0)