From 611a501c73d35fe8990b71465d7281cef9d0e42e Mon Sep 17 00:00:00 2001 From: Paul Meskers Date: Tue, 6 Jan 2015 14:42:30 -0500 Subject: [PATCH] feat(react-tabs): React component for Simple Alt tabs. [#85440704] Signed-off-by: Nicole Sullivan --- src/pivotal-ui/components/tabs.scss | 27 +++++++++ src/pivotal-ui/javascripts/components.js | 5 +- src/pivotal-ui/javascripts/tabs.jsx | 64 ++++++++++++++++++++ test/spec/javascripts/table_sortable_spec.js | 1 + test/spec/javascripts/tabs_spec.js | 58 ++++++++++++++++++ 5 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 src/pivotal-ui/javascripts/tabs.jsx create mode 100644 test/spec/javascripts/tabs_spec.js diff --git a/src/pivotal-ui/components/tabs.scss b/src/pivotal-ui/components/tabs.scss index b4c4855d5..83c943c36 100644 --- a/src/pivotal-ui/components/tabs.scss +++ b/src/pivotal-ui/components/tabs.scss @@ -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 +
+``` + +```jsx_example +React.render( + + Wow! + +

Neat!

+ So much content. +
+
, + document.getElementById('simple-alt-tabs-example') +); +``` +*/ diff --git a/src/pivotal-ui/javascripts/components.js b/src/pivotal-ui/javascripts/components.js index 20391330e..be86a0c45 100644 --- a/src/pivotal-ui/javascripts/components.js +++ b/src/pivotal-ui/javascripts/components.js @@ -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 }; diff --git a/src/pivotal-ui/javascripts/tabs.jsx b/src/pivotal-ui/javascripts/tabs.jsx new file mode 100644 index 000000000..5fe044413 --- /dev/null +++ b/src/pivotal-ui/javascripts/tabs.jsx @@ -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 ( +
  • + {tab.props.heading} +
  • + ); + }); + + 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 ( +
    + {tab.props.children} +
    + ); + }); + + return ( +
    +
      + {tabs} +
    +
    + {contents} +
    +
    + ); + } +}); + +var Tab = React.createClass({ + render: function () { + return ""; + } +}); + +module.exports = { + SimpleAltTabs: SimpleAltTabs, + Tab: Tab +}; diff --git a/test/spec/javascripts/table_sortable_spec.js b/test/spec/javascripts/table_sortable_spec.js index e5ec530c1..c69ab1d28 100644 --- a/test/spec/javascripts/table_sortable_spec.js +++ b/test/spec/javascripts/table_sortable_spec.js @@ -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() { diff --git a/test/spec/javascripts/tabs_spec.js b/test/spec/javascripts/tabs_spec.js new file mode 100644 index 000000000..80ce2bf07 --- /dev/null +++ b/test/spec/javascripts/tabs_spec.js @@ -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 = $('
    ').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( + + Content for first tab + Content for second tab + , + 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( + + Content for first tab + Content for second tab + , + 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"); + }); + }); +});