Adding hideMode to Tabs

- Defaulting to `unmounted` - not mounting inactive tabs. `display` mode will mount inactive tabs but keep them hidden.
- Closes #709
old
Abhi Rao 2016-08-30 15:08:22 -05:00
parent f9d6d3b1c6
commit 8e0b64f852
3 changed files with 62 additions and 25 deletions

View File

@ -12,6 +12,7 @@ const factory = (Tab, TabContent) => {
className: PropTypes.string,
disableAnimatedBottomBorder: PropTypes.bool,
fixed: PropTypes.bool,
hideMode: PropTypes.oneOf(['display', 'unmounted']),
index: PropTypes.number,
inverse: PropTypes.bool,
onChange: PropTypes.func,
@ -27,7 +28,8 @@ const factory = (Tab, TabContent) => {
static defaultProps = {
index: 0,
fixed: false,
inverse: false
inverse: false,
hideMode: 'unmounted'
};
state = {
@ -119,18 +121,21 @@ const factory = (Tab, TabContent) => {
}
renderContents (contents) {
const activeIdx = contents.findIndex((item, idx) => {
return this.props.index === idx;
const contentElements = contents.map((item, idx) => {
return React.cloneElement(item, {
key: idx,
theme: this.props.theme,
active: this.props.index === idx,
hidden: this.props.index !== idx && this.props.hideMode === 'display',
tabIndex: idx
});
});
if (contents && contents[activeIdx]) {
return React.cloneElement(contents[activeIdx], {
key: activeIdx,
theme: this.props.theme,
active: true,
tabIndex: activeIdx
});
if (this.props.hideMode === 'display') {
return contentElements;
}
return contentElements.filter((item, idx) => (idx === this.props.index));
}
render () {

View File

@ -18,23 +18,23 @@ const getRenderedClassName = (tree, TargetComponent) => {
describe('Tabs', function () {
let tabContents, composition;
it('only renders the current tab', function () {
class Composition extends Component {
constructor () {
super();
this.state = { index: 0 };
}
render () {
return (
<Tabs index={this.state.index}>
<Tab label="tab1">tab1</Tab>
<Tab label="tab2">tab2</Tab>
</Tabs>
);
}
class Composition extends Component {
constructor () {
super();
this.state = { index: 0 };
}
render () {
return (
<Tabs index={this.state.index} {...this.props}>
<Tab label="tab1">tab1</Tab>
<Tab label="tab2">tab2</Tab>
</Tabs>
);
}
}
it('defaults to only rendering the current tab', function () {
// initial render
composition = utils.renderComponent(Composition);
@ -55,6 +55,37 @@ describe('Tabs', function () {
expect(tabContents[0].props.tabIndex).toEqual(1);
});
it('renders inactive tabs when hideMode is set to display', function () {
// initial render
composition = utils.renderComponent(Composition, { hideMode: 'display' });
tabContents = ReactTestUtils
.scryRenderedComponentsWithType(composition, TabContent);
expect(tabContents.length).toEqual(2);
let tabOne = tabContents.find((tab) => (tab.props.children === 'tab1'));
let tabTwo = tabContents.find((tab) => (tab.props.children === 'tab2'));
expect(tabOne.props.hidden).toEqual(false);
expect(tabTwo.props.hidden).toEqual(true);
// after tab change
composition.setState({ index: 1 });
composition.forceUpdate();
tabContents = ReactTestUtils
.scryRenderedComponentsWithType(composition, TabContent);
expect(tabContents.length).toEqual(2);
tabOne = tabContents.find((tab) => (tab.props.children === 'tab1'));
tabTwo = tabContents.find((tab) => (tab.props.children === 'tab2'));
expect(tabOne.props.hidden).toEqual(true);
expect(tabTwo.props.hidden).toEqual(false);
});
describe('#render', function () {
it('does not use fixed by default', function () {
const tree = ReactTestUtils.renderIntoDocument(<Tabs theme={theme} />);

View File

@ -71,6 +71,7 @@ This component acts as the wrapper and the main controller of the content that i
| `className` | `String` | `''` | Additional class name to provide custom styling.|
| `disableAnimatedBottomBorder` | `Boolean` | `false` | Disable the animation below the active tab.|
| `fixed` | `Boolean` | `false` | If True, the tabs will be 'fixed tabs'.|
| `hideMode` | `enum`(`'display'`,`'unmounted'`) | `unmounted` | `unmounted` mode will not mount the tab content of inactive tabs. `display` mode will mount but hide inactive tabs. Consider holding state outside of the Tabs component before using `display` mode |
| `index` | `Number` | `0` | Current <Tab> |
| `inverse` | `Boolean` | `false` | If True, the tabs will have an inverse style.|
| `onChange` | `Function` | | Callback function that is fired when the tab changes.|