Skip to content

Commit 722969d

Browse files
committedJun 18, 2015
[added] Accessibility, add tab roles when type "tabs"
add tablist and tab roles when the nav is bsStyle "tabs"
1 parent 4adaa70 commit 722969d

File tree

4 files changed

+71
-6
lines changed

4 files changed

+71
-6
lines changed
 

‎src/Nav.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const Nav = React.createClass({
5252

5353
return (
5454
<nav {...this.props} className={classNames(this.props.className, classes)}>
55-
{this.renderUl()}
55+
{ this.renderUl() }
5656
</nav>
5757
);
5858
},
@@ -67,7 +67,11 @@ const Nav = React.createClass({
6767
classes['navbar-right'] = this.props.right;
6868

6969
return (
70-
<ul {...this.props} className={classNames(this.props.className, classes)} ref="ul">
70+
<ul {...this.props}
71+
role={this.props.bsStyle === 'tabs' ? 'tablist' : null}
72+
className={classNames(this.props.className, classes)}
73+
ref="ul"
74+
>
7175
{ValidComponentChildren.map(this.props.children, this.renderNavItem)}
7276
</ul>
7377
);
@@ -95,6 +99,7 @@ const Nav = React.createClass({
9599
return cloneElement(
96100
child,
97101
{
102+
role: this.props.bsStyle === 'tabs' ? 'tab' : null,
98103
active: this.getChildActiveProp(child),
99104
activeKey: this.props.activeKey,
100105
activeHref: this.props.activeHref,

‎src/NavItem.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ const NavItem = React.createClass({
1010
active: React.PropTypes.bool,
1111
disabled: React.PropTypes.bool,
1212
href: React.PropTypes.string,
13+
role: React.PropTypes.string,
1314
title: React.PropTypes.node,
1415
eventKey: React.PropTypes.any,
15-
target: React.PropTypes.string
16+
target: React.PropTypes.string,
17+
'aria-controls': React.PropTypes.string
1618
},
1719

1820
getDefaultProps() {
@@ -23,32 +25,35 @@ const NavItem = React.createClass({
2325

2426
render() {
2527
let {
28+
role,
2629
disabled,
2730
active,
2831
href,
2932
title,
3033
target,
3134
children,
35+
'aria-controls': ariaControls, // eslint-disable-line react/prop-types
3236
...props } = this.props; // eslint-disable-line object-shorthand
3337
let classes = {
3438
active,
3539
disabled
3640
};
3741
let linkProps = {
42+
role,
3843
href,
3944
title,
4045
target,
4146
onClick: this.handleClick,
4247
ref: 'anchor'
4348
};
4449

45-
if (href === '#') {
50+
if (!role && href === '#') {
4651
linkProps.role = 'button';
4752
}
4853

4954
return (
50-
<li {...props} className={classNames(props.className, classes)}>
51-
<a {...linkProps}>
55+
<li {...props} role='presentation' className={classNames(props.className, classes)}>
56+
<a {...linkProps} aria-selected={active} aria-controls={ariaControls}>
5257
{ children }
5358
</a>
5459
</li>

‎test/NavItemSpec.js

+36
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,40 @@ describe('NavItem', function () {
106106
let linkElement = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
107107
assert.equal(linkElement.outerHTML.match('role="button"'), null);
108108
});
109+
110+
describe('Web Accessibility', function(){
111+
112+
it('Should pass aria-controls to the link', function () {
113+
let instance = ReactTestUtils.renderIntoDocument(
114+
<NavItem href="/path/to/stuff" target="_blank" aria-controls='hi'>Item content</NavItem>
115+
);
116+
117+
let linkElement = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
118+
119+
assert.ok(linkElement.hasAttribute('aria-controls'));
120+
});
121+
122+
it('Should add aria-selected to the link', function () {
123+
let instance = ReactTestUtils.renderIntoDocument(
124+
<NavItem active>Item content</NavItem>
125+
);
126+
127+
let linkElement = React.findDOMNode(
128+
ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
129+
130+
assert.equal(linkElement.getAttribute('aria-selected'), 'true');
131+
});
132+
133+
it('Should pass role down', function () {
134+
let instance = ReactTestUtils.renderIntoDocument(
135+
<NavItem role='tab'>Item content</NavItem>
136+
);
137+
138+
let linkElement = React.findDOMNode(
139+
ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
140+
141+
assert.equal(linkElement.getAttribute('role'), 'tab');
142+
});
143+
});
144+
109145
});

‎test/NavSpec.js

+19
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,23 @@ describe('Nav', function () {
114114

115115
assert.ok(items[0].props.navItem);
116116
});
117+
118+
119+
describe('Web Accessibility', function(){
120+
121+
it('Should have tablist and tab roles', function () {
122+
let instance = ReactTestUtils.renderIntoDocument(
123+
<Nav bsStyle="tabs" activeKey={1}>
124+
<NavItem key={1}>Tab 1 content</NavItem>
125+
<NavItem key={2}>Tab 2 content</NavItem>
126+
</Nav>
127+
);
128+
129+
let ul = ReactTestUtils.scryRenderedDOMComponentsWithTag(instance, 'ul')[0];
130+
let navItem = ReactTestUtils.scryRenderedDOMComponentsWithTag(instance, 'a')[0];
131+
132+
assert.equal(React.findDOMNode(ul).getAttribute('role'), 'tablist');
133+
assert.equal(React.findDOMNode(navItem).getAttribute('role'), 'tab');
134+
});
135+
});
117136
});

0 commit comments

Comments
 (0)
Please sign in to comment.