diff --git a/src/Nav.js b/src/Nav.js
index ed3b0d2ac9..d4873cc2b4 100644
--- a/src/Nav.js
+++ b/src/Nav.js
@@ -52,7 +52,7 @@ const Nav = React.createClass({
return (
);
},
@@ -67,7 +67,11 @@ const Nav = React.createClass({
classes['navbar-right'] = this.props.right;
return (
-
+
{ValidComponentChildren.map(this.props.children, this.renderNavItem)}
);
@@ -95,6 +99,7 @@ const Nav = React.createClass({
return cloneElement(
child,
{
+ role: this.props.bsStyle === 'tabs' ? 'tab' : null,
active: this.getChildActiveProp(child),
activeKey: this.props.activeKey,
activeHref: this.props.activeHref,
diff --git a/src/NavItem.js b/src/NavItem.js
index 9bc768df48..c17aec0fac 100644
--- a/src/NavItem.js
+++ b/src/NavItem.js
@@ -10,9 +10,11 @@ const NavItem = React.createClass({
active: React.PropTypes.bool,
disabled: React.PropTypes.bool,
href: React.PropTypes.string,
+ role: React.PropTypes.string,
title: React.PropTypes.node,
eventKey: React.PropTypes.any,
- target: React.PropTypes.string
+ target: React.PropTypes.string,
+ 'aria-controls': React.PropTypes.string
},
getDefaultProps() {
@@ -23,18 +25,21 @@ const NavItem = React.createClass({
render() {
let {
+ role,
disabled,
active,
href,
title,
target,
children,
+ 'aria-controls': ariaControls, // eslint-disable-line react/prop-types
...props } = this.props; // eslint-disable-line object-shorthand
let classes = {
active,
disabled
};
let linkProps = {
+ role,
href,
title,
target,
@@ -42,13 +47,13 @@ const NavItem = React.createClass({
ref: 'anchor'
};
- if (href === '#') {
+ if (!role && href === '#') {
linkProps.role = 'button';
}
return (
- -
-
+
-
+
{ children }
diff --git a/test/NavItemSpec.js b/test/NavItemSpec.js
index 3f931ae1c0..a7f6ffb6a1 100644
--- a/test/NavItemSpec.js
+++ b/test/NavItemSpec.js
@@ -106,4 +106,40 @@ describe('NavItem', function () {
let linkElement = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.equal(linkElement.outerHTML.match('role="button"'), null);
});
+
+ describe('Web Accessibility', function(){
+
+ it('Should pass aria-controls to the link', function () {
+ let instance = ReactTestUtils.renderIntoDocument(
+ Item content
+ );
+
+ let linkElement = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
+
+ assert.ok(linkElement.hasAttribute('aria-controls'));
+ });
+
+ it('Should add aria-selected to the link', function () {
+ let instance = ReactTestUtils.renderIntoDocument(
+ Item content
+ );
+
+ let linkElement = React.findDOMNode(
+ ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
+
+ assert.equal(linkElement.getAttribute('aria-selected'), 'true');
+ });
+
+ it('Should pass role down', function () {
+ let instance = ReactTestUtils.renderIntoDocument(
+ Item content
+ );
+
+ let linkElement = React.findDOMNode(
+ ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
+
+ assert.equal(linkElement.getAttribute('role'), 'tab');
+ });
+ });
+
});
diff --git a/test/NavSpec.js b/test/NavSpec.js
index 81a8d09fe4..c53a5bbb55 100644
--- a/test/NavSpec.js
+++ b/test/NavSpec.js
@@ -114,4 +114,23 @@ describe('Nav', function () {
assert.ok(items[0].props.navItem);
});
+
+
+ describe('Web Accessibility', function(){
+
+ it('Should have tablist and tab roles', function () {
+ let instance = ReactTestUtils.renderIntoDocument(
+
+ );
+
+ let ul = ReactTestUtils.scryRenderedDOMComponentsWithTag(instance, 'ul')[0];
+ let navItem = ReactTestUtils.scryRenderedDOMComponentsWithTag(instance, 'a')[0];
+
+ assert.equal(React.findDOMNode(ul).getAttribute('role'), 'tablist');
+ assert.equal(React.findDOMNode(navItem).getAttribute('role'), 'tab');
+ });
+ });
});