Skip to content

Commit

Permalink
feat(react-tabs): React component for Simple Alt tabs.
Browse files Browse the repository at this point in the history
[#85440704]

Signed-off-by: Nicole Sullivan <nsullivan@pivotal.io>
  • Loading branch information
Paul Meskers authored and stubbornella committed Jan 6, 2015
1 parent 30db5ba commit 611a501
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/pivotal-ui/components/tabs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -497,3 +497,30 @@ You can use any 130px by 130px svg for the icon in the center of the tab. Please
}
}
}


/*doc
---
title: React Simple Alt Tabs
name: react_simple_alt_tabs
categories:
- Beta
---
```html_example_table
<div id="simple-alt-tabs-example"></div>
```
```jsx_example
React.render(
<UI.SimpleAltTabs>
<UI.Tab heading="Tab 1">Wow!</UI.Tab>
<UI.Tab heading="Tab 2" active="true">
<h2>Neat!</h2>
<span>So much content.</span>
</UI.Tab>
</UI.SimpleAltTabs>,
document.getElementById('simple-alt-tabs-example')
);
```
*/
5 changes: 4 additions & 1 deletion src/pivotal-ui/javascripts/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,8 @@ module.exports = {
ShadowPanel: require('./panels.jsx').ShadowPanel,
HighlightPanel: require('./panels.jsx').HighlightPanel,

Image: require('./images.jsx').Image
Image: require('./images.jsx').Image,

SimpleAltTabs: require('./tabs.jsx').SimpleAltTabs,
Tab: require('./tabs.jsx').Tab
};
64 changes: 64 additions & 0 deletions src/pivotal-ui/javascripts/tabs.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict';

var React = require('react');
var _ = require('lodash');

var SimpleAltTabs = React.createClass({
render: function () {
var activeIndex = _.findIndex(this.props.children, function (tab) {
return tab.props.active;
});

if (activeIndex === -1) {
activeIndex = 0;
}

var tabs = _.map(this.props.children, function(tab, index) {
var className = index === activeIndex ? 'active' : '';
var tabId = '#tab-' + index;

return (
<li key={'tab-head-' + index} className={className}>
<a data-toggle="tab" href={tabId}>{tab.props.heading}</a>
</li>
);
});

var contents = _.map(this.props.children, function(tab, index) {
var classes = ['tab-pane', 'fade'];
var tabId = 'tab-' + index;
if (index === activeIndex) {
classes.push('in');
classes.push('active');
}

return (
<div key={'tab-content-' + index} id={tabId} className={classes.join(" ")}>
{tab.props.children}
</div>
);
});

return (
<div className="tab-simple-alt">
<ul className="nav nav-tabs">
{tabs}
</ul>
<div className="tab-content">
{contents}
</div>
</div>
);
}
});

var Tab = React.createClass({
render: function () {
return "";
}
});

module.exports = {
SimpleAltTabs: SimpleAltTabs,
Tab: Tab
};
1 change: 1 addition & 0 deletions test/spec/javascripts/table_sortable_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ describe('TableSortable', function() {

afterEach(function() {
React.unmountComponentAtNode(this.node);
document.body.removeChild(this.node);
});

it('adds the class "sortable" on all sortable columns', function() {
Expand Down
58 changes: 58 additions & 0 deletions test/spec/javascripts/tabs_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use strict';

var $ = require('jquery');
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;

var SimpleAltTabs = require('../../../src/pivotal-ui/javascripts/tabs.jsx').SimpleAltTabs;
var Tab = require('../../../src/pivotal-ui/javascripts/tabs.jsx').Tab;

describe('SimpleAltTabs', function() {
beforeEach(function() {
this.node = $('<div id="container"></div>').appendTo('body').get(0);
});

afterEach(function() {
React.unmountComponentAtNode(this.node);
document.body.removeChild(this.node);
});

describe("when the active flag is not set", function() {
beforeEach(function() {
React.render(
<SimpleAltTabs>
<Tab heading="My first tab" >Content for first tab</Tab>
<Tab heading="My second tab" >Content for second tab</Tab>
</SimpleAltTabs>,
this.node
);
});

it("renders the correct tabs and content", function() {
expect($('#container .tab-simple-alt ul.nav.nav-tabs li.active a')).toHaveText("My first tab");
expect($('#container .tab-simple-alt ul.nav.nav-tabs li:not(.active) a')).toHaveText("My second tab");

expect($('#container li.active a').attr('href')).toEqual('#' + $('#container .tab-pane.active').attr("id"));

expect($('#container .tab-simple-alt .tab-content .tab-pane.in.active')).toHaveText("Content for first tab");
expect($('#container .tab-simple-alt .tab-content .tab-pane:not(.in.active)')).toHaveText("Content for second tab");
});
});

describe("when the active flag is set on a tab", function() {
beforeEach(function() {
React.render(
<SimpleAltTabs>
<Tab heading="My first tab" >Content for first tab</Tab>
<Tab heading="My second tab" active="true">Content for second tab</Tab>
</SimpleAltTabs>,
this.node
);
});

it("sets the specified tab as active", function() {
expect($('#container .tab-simple-alt ul.nav.nav-tabs li.active a')).toHaveText("My second tab");
expect($('#container .tab-simple-alt .tab-content .tab-pane.in.active')).toHaveText("Content for second tab");
});
});
});

0 comments on commit 611a501

Please sign in to comment.