Skip to content
Advertisement

Accessibility – React Ensure click events have key events

I want to be sure that all my onClick event are next to a onKeyDown event.

I will use eslint-plugin-jsx-a11y to ensure this. But in code, It is a way to do this generic. I mean, it will be annoying to do all the time:

 if(event.keyCode === 13){
    ...
 }

I would like to have a way to tell an element that in onKeyDown in case that the user use the execute the function in the onClick. Or a similar solution like http://www.karlgroves.com/2014/11/24/ridiculously-easy-trick-for-keyboard-accessibility/

In angular for instance, I have this clear. Let’s go for a directive to do this automatically. But in React I don’t know wich is the best approach.


eslint rule: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md

Advertisement

Answer

Finally I only see 2 solutions:

1 I can create a component that encapsulate all those actions… But this is the work of a button. And I want not to open a new way to create buttons in my project, this is just for exceptions and this can create a vicious behave inside the project. And for that we have another component… the button 🙂

2 create a decorator for the actions.

export function a11yButtonActionHandler(target, key, descriptor) {
    const fn = descriptor.value;
    if (typeof fn !== 'function') {
        throw new Error(`@a11yButtonActionHandler decorator can only be applied to methods not: ${typeof fn}`);
    }

    descriptor.value = function actionHandler(event) {
        if (!event || event.type === 'click' ||
            (['keydown', 'keypress'].includes(event.type) && ['Enter', ' '].includes(event.key))
        ) {
            fn.call(this, event);
        }
    };

    return descriptor;
}

and use the decorator.

@a11yButtonActionHandler
myAction(event) {
 ...
}

<div className="element-with-very-good-excuse-to-dont-be-a-button"
     role="button"
     tabIndex="0"
     onKeyDown={ this.myAction }
     onClick={ this.myAction }>
Advertisement