Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions examples/basic/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,30 @@ const App = React.createClass({
<p>Source: <a href="http://en.wikipedia.org/wiki/Yoshi" target="_blank">Wikipedia</a></p>
</TabPanel>
</Tabs>

<Tabs>
<TabList>
<small style={{ padding: '0 10px' }}>Tabs:</small>
<Tab>Tab A</Tab>
<Tab>Tab B</Tab>
<code style={{ padding: '0 10px' }}>(separator)</code>
<Tab>Tab C</Tab>
<span style={{ padding: '0 10px' }}><small>End of tabs</small></span>
</TabList>

<TabPanel>
<h2>This is Tab A</h2>
<p>You can put arbitrary elements inside <code>{'<TabList>'}</code>.</p>
</TabPanel>
<TabPanel>
<h2>This is Tab B</h2>
<p>Navigating through the tabs with the keyboard will skip these arbitrary elements.</p>
</TabPanel>
<TabPanel>
<h2>This is Tab C</h2>
<p>Just mind that the output might be invalid HTML (<code>{'<div>'}</code> inside a <code>{'<ul>'}</code> for instance).</p>
</TabPanel>
</Tabs>
</div>
);
},
Expand Down
35 changes: 20 additions & 15 deletions src/components/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,12 @@ module.exports = React.createClass({
},

getTabsCount() {
return this.props.children && this.props.children[0] ?
React.Children.count(this.props.children[0].props.children) :
0;
if (this.props.children && this.props.children[0]) {
const tabs = this.props.children[0].props.children.filter(x => x.type === Tab);
return React.Children.count(tabs);
}

return 0;
},

getPanelsCount() {
Expand Down Expand Up @@ -202,6 +205,12 @@ module.exports = React.createClass({
return null;
}

// Exit early if this is not a tab. That way we can have arbitrary
// elements anywhere inside <TabList>
if (tab.type !== Tab) {
return tab;
}

const ref = `tabs-${index}`;
const id = tabIds[index];
const panelId = panelIds[index];
Expand All @@ -210,17 +219,13 @@ module.exports = React.createClass({

index++;

if (tab.type === Tab) {
return cloneElement(tab, {
ref,
id,
panelId,
selected,
focus,
});
}

return tab;
return cloneElement(tab, {
ref,
id,
panelId,
selected,
focus,
});
}),
});

Expand Down Expand Up @@ -282,7 +287,7 @@ module.exports = React.createClass({
return;
}

const index = [].slice.call(node.parentNode.children).indexOf(node);
const index = [].slice.call(node.parentNode.children).filter(isTabNode).indexOf(node);
this.setSelected(index);
return;
}
Expand Down
14 changes: 11 additions & 3 deletions src/components/__tests__/Tabs-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,22 +190,30 @@ describe('react-tabs', () => {
it('should not clone non tabs element', () => {
class Demo extends React.Component {
render() {
const plus = <div ref="yolo">+</div>;
const arbitrary1 = <div ref="arbitrary1">One</div>;
const arbitrary2 = <span ref="arbitrary2">Two</span>;
const arbitrary3 = <small ref="arbitrary3">Three</small>;

return (<Tabs>
<TabList>
{arbitrary1}
<Tab>Foo</Tab>
{plus}
{arbitrary2}
<Tab>Bar</Tab>
{arbitrary3}
</TabList>

<TabPanel>Hello Baz</TabPanel>
<TabPanel>Hello Faz</TabPanel>
</Tabs>);
}
}

const wrapper = mount(<Demo />);

expect(wrapper.ref('yolo').text()).toBe('+');
expect(wrapper.ref('arbitrary1').text()).toBe('One');
expect(wrapper.ref('arbitrary2').text()).toBe('Two');
expect(wrapper.ref('arbitrary3').text()).toBe('Three');
});
});

Expand Down
3 changes: 2 additions & 1 deletion src/helpers/childrenPropType.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Tab from '../components/Tab';
import TabList from '../components/TabList';
import TabPanel from '../components/TabPanel';

module.exports = function childrenPropTypes(props, propName) {
let error;
Expand All @@ -27,7 +28,7 @@ module.exports = function childrenPropTypes(props, propName) {
tabsCount++;
}
});
} else if (child.type.displayName === 'TabPanel') {
} else if (child.type === TabPanel) {
panelsCount++;
} else {
error = new Error(
Expand Down