Skip to content

Commit

Permalink
Add keyboard accessibility to move crop area with arrow keys (#570)
Browse files Browse the repository at this point in the history
* feat: add keyboard accessibility to move crop area with arrow keys

* chore: remove uneeded formated line

* chore: add keyboardStep prop reference to README file
  • Loading branch information
JGuardiola95 authored Oct 11, 2024
1 parent eae14fb commit 646b997
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ See [#428](https://github.com/ValentinH/react-easy-crop/issues/428), [#409](http
| `setMediaSize` | `(size: MediaSize) => void` | | [Advanced Usage] Used to expose the `mediaSize` value for use with the `getInitialCropFromCroppedAreaPixels` and `getInitialCropFromCroppedAreaPercentages` functions. See [this CodeSandbox instance](https://codesandbox.io/s/react-easy-crop-forked-3v0hi3) for a simple example. |
| `setCropSize` | `(size: Size) => void` | | [Advanced Usage] Used to expose the `cropSize` value for use with the `getInitialCropFromCroppedAreaPixels` and `getInitialCropFromCroppedAreaPercentages` functions. See [this CodeSandbox instance](https://codesandbox.io/s/react-easy-crop-forked-3v0hi3) for a simple example. |
| `nonce` | string | | The nonce to add to the style tag when the styles are auto injected. |
| `keyboardStep` | number | | The keyboardStep prop controls the number of pixels the crop area moves with each press of an arrow key when using keyboard navigation. Defaults to 1. |

<a name="onCropCompleteProp"></a>

Expand Down
37 changes: 37 additions & 0 deletions src/Cropper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export type CropperProps = {
setMediaSize?: (size: MediaSize) => void
setCropSize?: (size: Size) => void
nonce?: string
keyboardStep: number
}

type State = {
Expand All @@ -72,6 +73,7 @@ type State = {

const MIN_ZOOM = 1
const MAX_ZOOM = 3
const KEYBOARD_STEP = 1

type GestureEvent = UIEvent & {
rotation: number
Expand All @@ -96,6 +98,7 @@ class Cropper extends React.Component<CropperProps, State> {
zoomSpeed: 1,
restrictPosition: true,
zoomWithScroll: true,
keyboardStep: KEYBOARD_STEP,
}

imageRef: React.RefObject<HTMLImageElement> = React.createRef()
Expand Down Expand Up @@ -727,6 +730,38 @@ class Cropper extends React.Component<CropperProps, State> {
this.emitCropData()
}

onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
const { crop, onCropChange, keyboardStep, zoom, rotation } = this.props
const step = keyboardStep

if (!this.state.cropSize) return

let newCrop = { ...crop }

switch (event.key) {
case 'ArrowUp':
newCrop.y -= step
break
case 'ArrowDown':
newCrop.y += step
break
case 'ArrowLeft':
newCrop.x -= step
break
case 'ArrowRight':
newCrop.x += step
break
default:
return
}

if (this.props.restrictPosition) {
newCrop = restrictPosition(newCrop, this.mediaSize, this.state.cropSize, zoom, rotation)
}

onCropChange(newCrop)
}

render() {
const {
image,
Expand Down Expand Up @@ -810,6 +845,8 @@ class Cropper extends React.Component<CropperProps, State> {
width: this.state.cropSize.width,
height: this.state.cropSize.height,
}}
tabIndex={0}
onKeyDown={this.onKeyDown}
data-testid="cropper"
className={classNames(
'reactEasyCrop_CropArea',
Expand Down

0 comments on commit 646b997

Please sign in to comment.