Skip to content

Commit

Permalink
Make Slider and Hue Accessible
Browse files Browse the repository at this point in the history
This commit addresses issue
casesandberg#847 by making the hue
and slider swatch focusable and controllable using arrow keys.

It does this by setting tabIndex to zero and  adding onKeyDown
handlers to the SliderSwatch and Hue components.

It also changes the detection of keys to the key property rather than
keyCode which is deprecated
(https://www.w3schools.com/jsref/event_key_keycode.asp).

For updating the hue, changing the hue on the slider is
implemented in hue.js for horizontal sliders only.

For repeated key presses to work (ie. arrow key held down) the usage of
onChange is required, in addition to onChangeComplete, otherwise the
slider won't move while the arrow key is held down, rather needing to be
pressed many times. Resolving this within the package is the scope of a
future commit, as are tests and docs.
  • Loading branch information
EddyIonescu committed Dec 28, 2021
1 parent bc9a0e1 commit f3f47bb
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 14 deletions.
5 changes: 4 additions & 1 deletion src/components/common/Hue.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export class Hue extends (PureComponent || Component) {

handleChange = (e) => {
const change = hue.calculateChange(e, this.props.direction, this.props.hsl, this.container)
change && typeof this.props.onChange === 'function' && this.props.onChange(change, e)
if (change && typeof this.props.onChange === 'function') {
this.props.onChange(change, e)
}
}

handleMouseDown = (e) => {
Expand Down Expand Up @@ -74,6 +76,7 @@ export class Hue extends (PureComponent || Component) {
onMouseDown={ this.handleMouseDown }
onTouchMove={ this.handleChange }
onTouchStart={ this.handleChange }
onKeyDown={ this.handleChange }
>
<style>{ `
.hue-horizontal {
Expand Down
4 changes: 1 addition & 3 deletions src/components/common/Swatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import { handleFocus } from '../../helpers/interaction'

import Checkboard from './Checkboard'

const ENTER = 13

export const Swatch = ({ color, style, onClick = () => {}, onHover, title = color,
children, focus, focusStyle = {} }) => {
const transparent = color === 'transparent'
Expand All @@ -25,7 +23,7 @@ export const Swatch = ({ color, style, onClick = () => {}, onHover, title = colo
})

const handleClick = e => onClick(color, e)
const handleKeyDown = e => e.keyCode === ENTER && onClick(color, e)
const handleKeyDown = e => e.key === 'Enter' && onClick(color, e)
const handleHover = e => onHover(color, e)

const optionalEvents = {}
Expand Down
2 changes: 1 addition & 1 deletion src/components/slider/SliderPointer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const SliderPointer = () => {
})

return (
<div style={ styles.picker } />
<div tabIndex={ 0 } style={ styles.picker } />
)
}

Expand Down
9 changes: 8 additions & 1 deletion src/components/slider/SliderSwatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,15 @@ export const SliderSwatch = ({ hsl, offset, onClick = () => {}, active, first, l
source: 'hsl',
}, e)

const handleKeyDown = e => e.key === 'Enter' && handleClick(e)

return (
<div style={ styles.swatch } onClick={ handleClick } />
<div
tabIndex={ 0 }
style={ styles.swatch }
onClick={ e => handleClick(e) }
onKeyDown={ e => handleKeyDown(e) }
/>
)
}

Expand Down
39 changes: 31 additions & 8 deletions src/helpers/hue.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
export const calculateChange = (e, direction, hsl, container) => {
const containerWidth = container.clientWidth
const containerHeight = container.clientHeight
const x = typeof e.pageX === 'number' ? e.pageX : e.touches[0].pageX
const y = typeof e.pageY === 'number' ? e.pageY : e.touches[0].pageY
const left = x - (container.getBoundingClientRect().left + window.pageXOffset)
const top = y - (container.getBoundingClientRect().top + window.pageYOffset)

if (direction === 'vertical') {
const y = typeof e.pageY === 'number' ? e.pageY : e.touches[0].pageY
const top = y - (container.getBoundingClientRect().top + window.pageYOffset)

let h
if (top < 0) {
h = 359
Expand All @@ -27,17 +26,41 @@ export const calculateChange = (e, direction, hsl, container) => {
}
}
} else {
const prevH = hsl.h
// Each step is a 0.5% movement in the slider. Repeated key press is supported when
// onChange is used, but not onChangeComplete.
const ArrowStep = containerWidth / 200
const prevLeft = prevH * containerWidth / 360
let left
if (e.key === 'ArrowLeft') {
left = prevLeft - ArrowStep
}
if (e.key === 'ArrowRight') {
left = prevLeft + ArrowStep
}
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
// Prevent web-app from scrolling horizontally, only the slider should be moving.
e.preventDefault()
}
if (!left && left !== 0) {
let x
if (typeof e.pageX === 'number') {
x = e.pageX
} else if (e.touches && e.touches.length) {
x = e.touches[0].pageX
}
left = x - (container.getBoundingClientRect().left + window.pageXOffset)
}

let h
if (left < 0) {
h = 0
} else if (left > containerWidth) {
h = 359
} else {
const percent = (left * 100) / containerWidth
h = ((360 * percent) / 100)
h = 360 * left / containerWidth
}

if (hsl.h !== h) {
if ((h || h === 0) && prevH !== h) {
return {
h,
s: hsl.s,
Expand Down

0 comments on commit f3f47bb

Please sign in to comment.