Skip to content
Permalink
Browse files

SafeAnchor a11y - Provide keydown handler for "space" (#2697)

* Provide keydown handler for "space"

If `onKeyDown` prop is supplied, prefer that
If no `onKeyDown` supplied, handle "space" with the `onClick` handler.
Test that space bar calls click handler.

* Check for key, not keycode

* Only add handler if rendering `a` tag

Chain own-props `onKeyDown` with space handler

* Prevent default only for space, don't check for `a`

* Style nits
  • Loading branch information...
andrewdushane authored and jquense committed Aug 26, 2017
1 parent c152582 commit 027e185a87f42a7de2a5fb46a1c99ce3eacac7e9
Showing with 24 additions and 1 deletion.
  1. +13 −1 src/SafeAnchor.js
  2. +11 −0 test/SafeAnchorSpec.js
@@ -2,9 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import elementType from 'prop-types-extra/lib/elementType';

import createChainedFunction from './utils/createChainedFunction';

const propTypes = {
href: PropTypes.string,
onClick: PropTypes.func,
onKeyDown: PropTypes.func,
disabled: PropTypes.bool,
role: PropTypes.string,
tabIndex: PropTypes.oneOfType([
@@ -36,6 +39,7 @@ class SafeAnchor extends React.Component {
super(props, context);

this.handleClick = this.handleClick.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
}

handleClick(event) {
@@ -55,8 +59,15 @@ class SafeAnchor extends React.Component {
}
}

handleKeyDown(event) {
if (event.key === ' ') {
event.preventDefault();
this.handleClick(event);
}
}

render() {
const { componentClass: Component, disabled, ...props } = this.props;
const { componentClass: Component, disabled, onKeyDown, ...props } = this.props;

if (isTrivialHref(props.href)) {
props.role = props.role || 'button';
@@ -74,6 +85,7 @@ class SafeAnchor extends React.Component {
<Component
{...props}
onClick={this.handleClick}
onKeyDown={createChainedFunction(this.handleKeyDown, onKeyDown)}
/>
);
}
@@ -39,6 +39,17 @@ describe('SafeAnchor', () => {
handleClick.should.have.been.calledOnce;
});

it('provides onClick handler as onKeyDown handler for "space"', () => {
const handleClick = sinon.spy();

tsp(<SafeAnchor onClick={handleClick} />)
.shallowRender()
.find('a')
.trigger('keyDown', { key: ' ', preventDefault() {} });

handleClick.should.have.been.calledOnce;
});

it('prevents default when no href is provided', () => {
const handleClick = sinon.spy();

0 comments on commit 027e185

Please sign in to comment.
You can’t perform that action at this time.