Skip to content

Commit

Permalink
Allows arbitrary components anywhere inside <TabList>
Browse files Browse the repository at this point in the history
  • Loading branch information
danez committed Apr 13, 2017
1 parent b50c77e commit 0a15604
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 19 deletions.
41 changes: 25 additions & 16 deletions src/components/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,15 @@ export default class Tabs extends Component {
}

getTabsCount() {
return this.props.children && this.props.children[0] ?
React.Children.count(this.props.children[0].props.children) :
0;
if (
Array.isArray(this.props.children) &&
Array.isArray(this.props.children[0].props.children)
) {
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 @@ -178,25 +184,28 @@ export default class Tabs extends Component {
return null;
}

const tabRef = (node) => { this.tabNodes[`tabs-${index}`] = node; };
// 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 key = `tabs-${index}`;
const tabRef = (node) => { this.tabNodes[key] = node; };
const id = this.tabIds[index];
const panelId = this.panelIds[index];
const selected = state.selectedIndex === index;
const focus = selected && state.focus;

index++;

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

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

Expand Down Expand Up @@ -254,7 +263,7 @@ export default class Tabs extends Component {
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 @@ -214,22 +214,30 @@ describe('<Tabs />', () => {
it('should not clone non tabs element', () => {
class Demo extends React.Component {
render() {
const plus = <div ref="yolo">+</div>; // eslint-disable-line react/no-string-refs
const arbitrary1 = <div ref="arbitrary1">One</div>; // eslint-disable-line react/no-string-refs
const arbitrary2 = <span ref="arbitrary2">Two</span>; // eslint-disable-line react/no-string-refs
const arbitrary3 = <small ref="arbitrary3">Three</small>; // eslint-disable-line react/no-string-refs

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

0 comments on commit 0a15604

Please sign in to comment.