Skip to content

Commit

Permalink
📱 Slider: added touch support (#3144)
Browse files Browse the repository at this point in the history
  • Loading branch information
oddvernes authored Nov 15, 2023
1 parent d7604b4 commit 424e8f1
Showing 1 changed file with 41 additions and 9 deletions.
50 changes: 41 additions & 9 deletions packages/eds-core-react/src/components/Slider/Slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
useRef,
HTMLAttributes,
MouseEvent,
TouchEvent,
KeyboardEvent,
useEffect,
ChangeEvent,
Expand Down Expand Up @@ -54,6 +55,7 @@ type RangeWrapperProps = {
$disabled: boolean
$hideActiveTrack: boolean
$labelAlwaysOn: boolean
$touchNavigation: boolean
}

const RangeWrapper = styled.div.attrs<RangeWrapperProps>(
Expand Down Expand Up @@ -114,6 +116,20 @@ const RangeWrapper = styled.div.attrs<RangeWrapperProps>(
&:where(:hover, :has(:focus-visible)) {
--showTooltip: 1;
}
${({ $touchNavigation }) =>
$touchNavigation &&
css`
& > input[type='range'] {
pointer-events: none;
}
& > input[type='range']::-webkit-slider-thumb {
pointer-events: auto;
}
& > input[type='range']::-moz-range-thumb {
pointer-events: auto;
}
`};
`

type WrapperProps = {
Expand Down Expand Up @@ -236,7 +252,7 @@ export type SliderProps = {
disabled?: boolean
/** hides the "active" fill color from the track */
hideActiveTrack?: boolean
/** Make the current value tooltip always visible, otherwise it only shows on hover/focus
/** Make the current value label always visible, otherwise it only shows on hover/focus or while using touch input
* @default false
*/
labelAlwaysOn?: boolean
Expand Down Expand Up @@ -269,6 +285,7 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(
const [initalValue, setInitalValue] = useState<number[]>(parsedValue)
const [sliderValue, setSliderValue] = useState<number[]>(parsedValue)
const [mousePressed, setMousePressed] = useState<boolean>(false)
const [touchNavigation, setTouchNavigation] = useState<boolean>(false)

useEffect(() => {
if (isRangeSlider) {
Expand Down Expand Up @@ -337,13 +354,22 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(
return outputFunction ? outputFunction(text) : text
}

const findClosestRange = (event: MouseEvent) => {
const findClosestRange = (event: MouseEvent | TouchEvent) => {
const target = event.target as HTMLOutputElement | HTMLInputElement
if (target.type === 'output' || mousePressed) {
return
}
let clientX: number
if (event.type === 'touchstart') {
clientX = (event as TouchEvent<HTMLInputElement>).targetTouches[0].clientX
setTouchNavigation(true)
} else if (event.type === 'mousemove') {
clientX = (event as MouseEvent<HTMLInputElement>).clientX
setTouchNavigation(false)
}

const bounds = target.getBoundingClientRect()
const x = event.clientX - bounds.left
const x = clientX - bounds.left
const inputWidth = minRange.current.offsetWidth
const minValue = parseFloat(minRange.current.value)
const maxValue = parseFloat(maxRange.current.value)
Expand Down Expand Up @@ -371,8 +397,8 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(
}
}

const handleDragging = (e: MouseEvent) => {
if (e.type === 'mousedown') {
const handleDragging = (type: string) => {
if (type === 'mousedown' || type === 'touchmove') {
setMousePressed(true)
} else {
setMousePressed(false)
Expand Down Expand Up @@ -409,10 +435,14 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(
$min={min}
$disabled={disabled}
$hideActiveTrack={hideActiveTrack}
$labelAlwaysOn={labelAlwaysOn}
$labelAlwaysOn={labelAlwaysOn || touchNavigation}
$touchNavigation={touchNavigation}
onMouseMove={findClosestRange}
onMouseDown={handleDragging}
onMouseUp={handleDragging}
onTouchStartCapture={findClosestRange}
onTouchEnd={(e) => handleDragging(e.type)}
onTouchMove={(e) => handleDragging(e.type)}
onMouseDown={(e) => handleDragging(e.type)}
onMouseUp={(e) => handleDragging(e.type)}
>
{minMaxDots && <WrapperGroupLabelDots />}
<SrOnlyLabel htmlFor={inputIdA}>Value A</SrOnlyLabel>
Expand Down Expand Up @@ -473,7 +503,9 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(
value={sliderValue[0]}
disabled={disabled}
$hideActiveTrack={hideActiveTrack}
$labelAlwaysOn={labelAlwaysOn}
$labelAlwaysOn={labelAlwaysOn || touchNavigation}
onTouchStartCapture={() => setTouchNavigation(true)}
onMouseDownCapture={() => setTouchNavigation(false)}
>
<SliderInput
type="range"
Expand Down

0 comments on commit 424e8f1

Please sign in to comment.