GithubHelp home page GithubHelp logo

react-a11y's Introduction

React A11y

build status

Identifies accessibility issues in your React.js elements

screenshot

⛔️DEPRECATION NOTICE ⛔️

This library is being deprecated in favor of @axe-core/react.
Deque Systems are one of the top authorities on web accessibility. Their auditing tools based on their axe-core engine are unrivaled and have become the gold standard for auditing web accessibility issues. Now that they have developed a runtime React DOM auditing tool, that does what react-a11y attempts to do but better, it seems counterproductive to continue to maintain react-a11y. Let's pool our resources and energies into the best product and I believe any accessibility tool backed by the experts at Deque Systems is bound to be one we can trust and depend on. Please go check out and install @axe-core/react today!

Installation

Run:

npm install react-a11y

Usage

In your main application file, require the module and call it, you'll start getting warnings in the console as your app renders. Note that by default all rules are turned off so you need to turn them on first (by setting them to "warn" or "error").

import React    from 'react';
import ReactDOM from 'react-dom';

if (process.env.NODE_ENV === 'development') {
  const a11y = require('react-a11y').default;
  a11y(React, ReactDOM, {
    rules: {
      'img-uses-alt': 'warn',
      'img-redundant-alt': [ 'warn', [ 'image', 'photo', 'foto', 'bild' ]]
    // ...
    }
  });
}

You probably don't want to call it if you're in production, since it patches the React rendering functions and this might make this slower.

Migrating to v1.1.0

A number of the rule names have changed and the previous rule names have been deprecated. These deprecated rules will be removed in v2.0.0. The following is the mapping of old to new rules:

Old Rule New Rule
avoid-positive-tabindex tabindex-no-positive
button-role-space click-events-have-key-events
label-uses-for label-has-for
mouse-events-map-to-key-events mouse-events-have-key-events
no-unsupported-elements-use-aria aria-unsupported-elements
onclick-uses-tabindex interactive-supports-focus
redundant-alt img-redundant-alt
use-onblur-not-onchange no-onchange
valid-aria-role aria-role

Options

These are the supported configuration options, annotated using flow type annotations

a11y(React : React, ReactDOM : ReactDOM, opts : object? );

React is the React object you want to shim to allow the accessibility tests.

ReactDOM is the ReactDOM object you're using to render the React components. This is only used on the client side, so you can safely omit it when using react-a11y in node.

options:

  • plugins : [string] An array of strings corresponding to names of plugins to be used. Eg. if the array contains 'aria-wai' it would include the rules in a (yet to be written) react-a11y-plugin-aria-wai module. You are responsible for installing this module.

  • rules : object The configuration options for each of the rules. This uses the same format as eslint does:

    const rules = {
      'img-uses-alt': 'off',
      'redundant-alt': [
        'warn',
        // other options to pass to the rule:
        [
          'foto'
        ]
      ]
    };

    Refer to the rule docs to see what options are defined for each rule.

  • reporter : object => undefined Use this to modify how the warnings are displayed. The reporter is a function that accepts an object with the following keys:

    • msg : string - the error message
    • tagName : string - the tagName of the violating element (eg. 'img')
    • severity : string - the severity as configured by the user in the corresponding rule configuration (one of 'off', 'warn', or 'error')
    • props : object - the props as passed to the element
    • displayName : string? - the displayName of the owner, if any
    • DOMNode : object? - the violating DOMNode as rendered to the browser DOM, this is only available on when react-a11y is running in the browser.
    • url : string? - The url to a webpage explaining why this rule is important

    The default reporter displays all the information it can, but listens to the deprecated options includeSrcNode, warningPrefix and throwErro and throwError.

  • filterFn : (string, string, string) => boolean You can filter failures by passing a function to the filterFn option. The filter function will receive three arguments: the name of the Component instance or ReactElement, the id of the violating element, and the failure message.

    Note: If it is a ReactElement, the name will be the node type (eg. div)

    // only show errors on CommentList
    const commentListFailures = function (name, id, msg) {
      return name === "CommentList";
    };
    
    a11y(React, ReactDOM, { filterFn: commentListFailures });

Cleaning Up In Tests

Use the restoreAll() method to clean up mutations made to React. Useful if you are using react-a11y in your test suite:

beforeEach(() => a11y(React));
afterEach(() => a11y.restoreAll());

Writing plugins

The rules in this version of react-a11y are pluggable! You can write your own plugin to add more rules. Have a look at writing plugins in the docs to get started!

Contributing

Interested in contributing? Great! Look here for more info: CONTRIBUTING.md.

react-a11y's People

Contributors

alexlande avatar angus-c avatar asaayers avatar coreykumpal avatar ebenpack avatar gaearon avatar hongbo-miao avatar joonhocho avatar jsharpe avatar kloots avatar matt-royal avatar mrfr0g avatar robdel12 avatar romeovs avatar ryanflorence avatar seanmcp avatar seannyphoenix avatar swaagie avatar tbroadley avatar ted-humpal avatar wyattdanger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-a11y's Issues

hasChildTextNode cannot handle an undefined child.

If the children array has an undefined child it will throw undefined errors for child.type. It's probably due to bad render functions on the users end, but it is confusing none the less. An error message would be useful.

Release planned soon?

Is there a publish on npm planned soon? A lot of outstanding PRs were taken care of last week and we would like to benefit from them.

Thank you very much!

Potential es5 goodies causing js errors in Android browser and IE8

Amazing project, love the work you are doing!

Just noticed if i require react-a11y before my es5 shims and shams i get JS errors on IE8 and older Android browsers.
Unfortunately neither of these devices/technologies allow me to get a valid error message that i can pass on to you guys. My minimal investigation tells me IE8 and android(internet) is not handling some es5 or 6 goodies.

Requiring the library after the es5 shim works fine.

Improve "You have an unlabled element or control" message

The "You have an unlabled element or control" warnings are very difficult to track down because the message doesn't offer any additional clues as to where the issue is other than giving you the name of the component.

I'm wondering if it's possible to improve this message at all? Perhaps add the name of the parent component(s)?

Label checks can produce false failures

I introduced a logic error in 0.2.0. When the child is a component, hasChildTextNode() uses a componentDidMount listener to check the DOM of the rendered component. However, after binding the componentDidMount listener, hasChildTextNode() returns undefined, resulting in the error handler being called prematurely. To fix this hasChildTextNode() should return true in this case.

Label assertion should fail if none of the child Components have label text

Introduced in 0.2.0: If an element has multiple children that are custom components and none have label text the label assertion should fail. Here's the test case:

it('warns if no child components have label text', () => {
  var Bar = React.createClass({
    render: () => {
      return (
        <div className="bar"></div>
      );
    }
  });

  var Foo = React.createClass({
    render: function() {
      return (
        <div className="foo"></div>
      );
    }
  });

  expectWarning(assertions.render.NO_LABEL.msg, () => {
    React.render(<div role="button"><Bar/><Foo/></div>, fixture);
  });
});

Use React.findDOMNode to log element references

When there's an error, we currently use document.getElementById to log element element references. Since the code is executed in a componentDidMount/componentDidUpdate callback, we could use React.findDOMNode() instead.

Provide a means of filtering errors

If you use react-a11y on an existing project, you'll likely be overwhelmed by the number of accessibility errors. It'd be useful to have a means of filtering errors by component name, so developers can easily focus on addressing failures on a per-component basis.

No ID listed in warnings

I added the ID back in #14 so we could actually find the elements producing warnings.

selection_195

What's the point of warning without a direct reference to where it's being produced?

Putting the ID only on elements that were failing was great because I had some CSS targeting *[id^=a11y-] { which would cause broken elements to fade in and out so you could find them. The animation is also very irritating which motivates fixing it immediately.

So now after upgrading I can't find the elements throwing warnings and I can't style broken elements.

Don't use babel-runtime

Let babel inline any helpers it needs. The runtime is more useful for apps than individual libs of this size.

Label assertions don't account for the label being an image created by a custom component

The current assertion code doesn't account for when the label is an image created via a custom component. Here's the test cases:

it('does not warn when the label is an image with alt text', () => {
  var Foo = React.createClass({
    render: function() {
      return (
        <img alt="foo"/>
      );
    }
  });

  doNotExpectWarning(assertions.render.NO_LABEL.msg, () => {
    React.render(<div role="button"><Foo/></div>, fixture);
  });
});

it('warns when the label is an image without alt text', () => {
  var Foo = React.createClass({
    render: function() {
      return (
        <img alt=""/>
      );
    }
  });

  expectWarning(assertions.render.NO_LABEL.msg, () => {
    React.render(<div role="button"><Foo/></div>, fixture);
  });
});

Label assertion fails when child is a Component

We have tests covering the case where an element's label is a deeply nested text node. For example:

it('does not warn if there are deeply nested text node children', () => {
  doNotExpectWarning(assertions.props.onClick.NO_LABEL.msg, () => {
    <div onClick={k}><span><span>foo</span></span></div>;
  });
});

However, if an element's label is a text node nested inside a Component, the label test fails. For example:

it('does not warn if there are deeply nested text node children inside of a component', () => {
  var Foo = React.createClass({
    render: function() {
      return (
        <div className="foo">
          <span><span>foo</span></span>
        </div>
      );
    }
  });

  doNotExpectWarning(assertions.props.onClick.NO_LABEL.msg, () => {
    <div role="gridcell" onClick={k}>
      <Foo/>
    </div>;
  });
});

Another, more simplified example that also fails:

it('warns if a Component has no label of any sort', () => {
  var Foo = React.createClass({
    render: function() {
      return (
        <div className="foo"></div>
      );
    }
  });

  expectWarning(assertions.props.onClick.NO_LABEL.msg, () => {
    <Foo onClick={k}/>;
  });
});

Provide a means of logging DOM element references

Currently error messages provide the id of the element with the error. It'd be more useful to log a DOM element reference, to reduce the amount of effort required to see the element in the DOM inspector.

Uncaught RangeError: Maximum call stack size exceeded

Hi,

I tried to upgrade from 0.1.1 to 0.2.6.
First my att didn't even start until I added babel-runtime as a dep. Now the app starts but I get the following error:

Chrome:
Uncaught RangeError: Maximum call stack size exceeded
(anonymous function) @ client.bundle.js:1
React.createElement @ index.js:171
React.createElement @ index.js:172
React.createElement @ index.js:172
React.createElement @ index.js:172
React.createElement @ index.js:172
React.createElement @ index.js:172
React.createElement @ index.js:172
...

Firefox:
too much recursion

Node: 0.12.5
React 0.13.3

Rails + Browserify issues

Thank you so much for making this! I've successfully used react-a11y on a Node project, but I am trying to implement this in my day job at Articulate.

Stack in addition to React:

  • Rails
  • NPM
  • browserify-rails

I know the code is being loaded on the page, but I can't seem to trigger any warnings/errors no matter how bad my code is (for example, rendering anchor tags with '#' as the href with no role or anthing).

Any help would be much appreciated,
Robert

Label test should require a label for placeholder anchors

Currently the label assertions don't evaluate placeholder anchors. These elements should be evaluated. Here's the test cases:

it('warns if there is no label on a placeholder link', () => {
  expectWarning(assertions.render.NO_LABEL.msg, () => {
    <a/>;
  });
});

it('does not warn when a placeholder link has a label', () => {
  doNotExpectWarning(assertions.render.NO_LABEL.msg, () => {
    <a>foo</a>;
  });
});

Global build

Would it be possible to provide a global build distribution à la react-router's /dist bundle?

Drop-in a11y checks for quick prototypes.would be very handy.

Bower Support

Can you please add bower support to this package? We'd like to use react-a11y on the client-side, and bower makes this much easier for us.

Switch to headless tests

Suggestion from @AsaAyers, worth investigating:
I don’t think the tests actually require a browser. What do you think of switching to headless tests? I have a couple projects using Jest and I really like it. I’m not sure if the tests even need a DOM, so plain jasmine-node may be an even be an option.

Placeholder links currently (incorrectly) require role="button" and tabIndex

HTML5 doesn't require the href attribute on links, but our tests fail since the code checks if the tabIndex is set using strict inequality:

props.tabIndex !== null

New tests that need to be added to check for this:

describe('placeholder links without href', () => {
  it('does not warn', () => {
    doNotExpectWarning(assertions.tags.a.HASH_HREF_NEEDS_BUTTON.msg, () => {
      <a class="foo" />;
    });
  });
});

describe('placeholder links without tabindex', () => {
  it('does not warn', () => {
    doNotExpectWarning(assertions.tags.a.TABINDEX_NEEDS_BUTTON.msg, () => {
      <a class="foo" />;
    });
  });
});

Is there a way to show the displayName of the parent ReactElement?

Right now the warnings are contextless - if you throw this in to an existing app with many accessibility issues, it can be hard to track down where in the codebase the problems are coming from without throwing. Is there a way to log the warnings with the displayName of the containing ReactElement?

Excluding components from tests

Hey all, feature request time.

It would be really useful if there was a way to exclude a given component (and children) from tests.

I'm using react-a11y with redux-devtools, which gives me a whole slew of a11y errors in the devtools panel (enough to lock up my browser window because of the flood of console logs as redux-devtools re-renders).

Another common use case would be to silence false positives.

assertions.js failing with "TypeError: Cannot read property 'children' of undefined"

This bit of code in assertions.js is failing for me in some cases:

var hasChildTextNode = function hasChildTextNode(props, children) {
  var hasText = false;
  React.Children.forEach(children, function (child) {
    if (hasText) return;else if (child === null) return;else if (typeof child === 'undefined') return;else if (typeof child === 'string') hasText = true;else if (child.type === 'img' && child.props.alt) hasText = true;else if (child.props.children) hasText = hasChildTextNode(child.props, child.props.children);
  });
  return hasText;
};

The error I get is: TypeError: Cannot read property 'children' of undefined.

I've isolated it down to a node with some text in it. I don't see anything special about it, but removing that node makes the issue go away.

EDIT More info. It seems to be related to text which is an integer:

// This will cause an error
var x = 1;
return (
    <button>
        <span>{x}</span>
    </button>
)

// However, this is totally okay
var x = 1;
return (
    <button>
        <span>{x.toString()}</span>
    </button>
)

Conflict with newer versions of Babel?

I'm writing a server that serves some rendered React components, and would like to use react-a11y in my project. However, adding var a11y = require('react-a11y') makes the script stop working, it generates the following output:

Error: Cannot find module 'babel-runtime/helpers/to-consumable-array'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:278:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/Marco/Projects/Prototypes/node_modules/react-a11y/dist/index.js:3:26)
    at Module._compile (module.js:460:26)
    at Module._extensions..js (module.js:478:10)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/Marco/Projects/Prototypes/node_modules/babel-core/lib/babel/api/register/node.js:161:7)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)

It seems to be conflicting because the Babel version I'm using is different, and I'm guessing some part of react-a11ys dependencies is expecting some method to (still) exist. I'm not quite sure how to fix this. Perhaps specifying stricter dependencies?

fwiw, my babel version is 5.4.7

Label assertion errors if label is a number

Current react-a11y will throw an error during label evaluations if an element's label is a number. Here's the test case:

it('does not warn when the label is a number', () => {
  doNotExpectWarning(assertions.render.NO_LABEL.msg, () => {
    <a>{1111}</a>;
  });
});

Incompatible with React 0.14: "Cannot assign to read only property 'id' of #<Object>"

I've been migrating to React 0.14 and I'm starting to get this error from react-a11y when instantiating new components via renderSubtreeIntoContainer:

TypeError: Cannot assign to read only property 'id' of #<Object>
    at Object.React.createElement (webpack:///./~/react-a11y/dist/index.js?:171:14)
    at render (eval at executeCode (webpack:///./html/js/libs/ReactPlayground.js?), <anonymous>:23:16)
    at ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext (webpack:///./~/react/lib/ReactCompositeComponent.js?:546:34)
    at ReactCompositeComponentMixin._renderValidatedComponent (webpack:///./~/react/lib/ReactCompositeComponent.js?:566:32)
    at ReactPerf.measure.wrapper (webpack:///./~/react/lib/ReactPerf.js?:66:21)
    at ReactCompositeComponentMixin.mountComponent (webpack:///./~/react/lib/ReactCompositeComponent.js?:181:32)
    at ReactPerf.measure.wrapper [as mountComponent] (webpack:///./~/react/lib/ReactPerf.js?:66:21)
    at Object.ReactReconciler.mountComponent (webpack:///./~/react/lib/ReactReconciler.js?:37:35)
    at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (webpack:///./~/react/lib/ReactMultiChild.js?:187:44)
    at ReactDOMComponent.Mixin._createContentMarkup (webpack:///./~/react/lib/ReactDOMComponent.js?:498:32)

Any ideas what could be going wrong?

Add ARIA validation

At a minimum can validate values of ARIA attributes. It might be more difficult to assert values that require the id of another element in the DOM, but we may be able make the assertion using a componentDidMount callback—similar to what we did to enable logging of DOM element references.

hasChildTextNode doesn’t handle numeric children

The code at assertions.js#L34-L35 doesn’t handle numeric children and throws an uncaught error trying to access properties of the number object in these instances.

This is a seemingly common thing in the wild. Things like react-data-components emit elements whose only children are numbers.

I’m happy to provide a PR, but not sure what the best option is here, but it may be to handle numeric children as strings. That said, this perhaps brings up a question about how “implicit” string conversions should be handled.

Thoughts on react-a11y and ESLint

I wonder if react-a11y might be better served as an ESLint plugin (similar to https://www.npmjs.com/package/eslint-plugin-react)?

Currently, to use react-a11y you need to load it into your code (remembering to remove it for production builds), run your app, open the dev tools, review the warnings, go back to your code editor, make the fix, then reload the app again to confirm the warning went away. With ESLint, those warnings could be directly integrated into build tools, and code editors without having to actually execute the application code.

Any thoughts?

Uncaught TypeError: Cannot read property 'type' of null in assertions.js

First off, great idea. I'm really excited about the work being done on this project.

Now, I just tried dropping it into my app and I quickly ran into this showstopping error:

Uncaught TypeError: Cannot read property 'type' of null

Which seems to be happening on this line:

if (hasText) return;else if (typeof child === "string") hasText = true;else if (child.type === "img" && child.props.alt) hasText = true;else if (child.props.children) hasText = hasChildTextNode(child.props, child.props.children);

Specifically, it seems that child is null in this case, so when you try to do child.type, we get an explosion. Adding a check like:

else if (child === null) return;

before the child.type check prevents this from happening, but I'm not really sure if that's the correct solution. Let me know if it is, or if there is a better solution, and I'll be happy to submit a PR.

Different react-a11y ids (server side render)

I am using React in isomorphic way, and have met warning message, after server side rendering. (You can reach message in attachments). How can I set react-a11 on client and on server? Thank you.
2015-07-29 15 47 25

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.