diff --git a/lib/components/Tabs.js b/lib/components/Tabs.js index ad99d53fbe..b87d0495ad 100644 --- a/lib/components/Tabs.js +++ b/lib/components/Tabs.js @@ -5,11 +5,6 @@ import jss from 'js-stylesheet'; import uuid from '../helpers/uuid'; import childrenPropType from '../helpers/childrenPropType'; -// Determine if a node from event.target is a Tab element -function isTabNode(node) { - return node.nodeName === 'LI' && node.getAttribute('role') === 'tab'; -} - // Determine if a tab node is disabled function isTabDisabled(node) { return node.getAttribute('aria-disabled') === 'true'; @@ -70,7 +65,7 @@ module.exports = React.createClass({ handleClick(e) { let node = e.target; do { - if (isTabNode(node)) { + if (this.isTabNode(node)) { if (isTabDisabled(node)) { return; } @@ -83,7 +78,7 @@ module.exports = React.createClass({ }, handleKeyDown(e) { - if (isTabNode(e.target)) { + if (this.isTabNode(e.target)) { let index = this.state.selectedIndex; let preventDefault = false; @@ -305,12 +300,36 @@ module.exports = React.createClass({ )} onClick={this.handleClick} onKeyDown={this.handleKeyDown} + role="tabs" > {this.getChildren()} ); }, + // Determine if a node from event.target is a Tab element for the current Tabs container. + // If the clicked element is not a Tab, it returns false. + // If it finds another Tabs container between the Tab and `this`, it returns false. + isTabNode(node) { + // return immediately if the clicked element is not a Tab. + if ((node.nodeName === 'LI' && node.getAttribute('role') === 'tab') === false) { + return false; + } + + // Check if the first occurrence of a Tabs container is `this` one. + let nodeAncestor = node.parentElement; + let lastAncestor = node; + do { + if (nodeAncestor === findDOMNode(this)) { + return true; + } + lastAncestor = nodeAncestor; + nodeAncestor = nodeAncestor.parentElement; + } while (lastAncestor.getAttribute('role') !== 'tabs'); + + return false; + }, + // This is an anti-pattern, so sue me copyPropsToState(props) { let selectedIndex = props.selectedIndex;