From 3e49b6c4fbe1d168020a5ed1812717f87b2afefa Mon Sep 17 00:00:00 2001 From: Peggy Li Date: Thu, 24 Aug 2017 12:59:22 -0700 Subject: [PATCH 1/2] Autogenerated files --- src/TabbedTable/TabbedTable.jsx | 27 +++++++++++++++++++++++++++ src/TabbedTable/TabbedTable.less | 11 +++++++++++ src/index.js | 1 + src/less/components.less | 1 + test/TabbedTable_test.jsx | 21 +++++++++++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 src/TabbedTable/TabbedTable.jsx create mode 100644 src/TabbedTable/TabbedTable.less create mode 100644 test/TabbedTable_test.jsx diff --git a/src/TabbedTable/TabbedTable.jsx b/src/TabbedTable/TabbedTable.jsx new file mode 100644 index 000000000..f722319b2 --- /dev/null +++ b/src/TabbedTable/TabbedTable.jsx @@ -0,0 +1,27 @@ +import React from "react"; + +import "./TabbedTable.less"; + +/* + Add a description of your component here. + + If your component can be expressed without state, + use the stateless function syntax instead! +*/ +export default class TabbedTable extends React.Component { + constructor(props) { + super(props); + // Set state and bind methods here + } + + /* Insert any additional lifecycle methods, + event handlers, and helper methods here */ + + render() { + // Fill in render method here + } +} + +TabbedTable.propTypes = { + // List required and optional proptypes +} diff --git a/src/TabbedTable/TabbedTable.less b/src/TabbedTable/TabbedTable.less new file mode 100644 index 000000000..65950a328 --- /dev/null +++ b/src/TabbedTable/TabbedTable.less @@ -0,0 +1,11 @@ +.TabbedTable { + /* + Use namespaced classes that begin with "TabbedTable" + to avoid clashing with global styles. If possible, avoid + over-nesting selectors and instead use clear class names + that convey the purpose and/or state of the element: + + .TabbedTable--container + .TabbedTable--input-disabled + */ +} diff --git a/src/index.js b/src/index.js index 0a52a5262..e6f7d9da5 100644 --- a/src/index.js +++ b/src/index.js @@ -51,3 +51,4 @@ export {Number}; import Tooltip from "./Tooltip"; export {Tooltip}; +export {TabbedTable} from "./TabbedTable/TabbedTable"; diff --git a/src/less/components.less b/src/less/components.less index 2742ca149..bdd7385a6 100644 --- a/src/less/components.less +++ b/src/less/components.less @@ -15,3 +15,4 @@ @import "../Icon/Icon"; @import "../LeftNav/LeftNav"; @import "../AlertBox/AlertBox"; +@import "../TabbedTable/TabbedTable"; diff --git a/test/TabbedTable_test.jsx b/test/TabbedTable_test.jsx new file mode 100644 index 000000000..c73f07b15 --- /dev/null +++ b/test/TabbedTable_test.jsx @@ -0,0 +1,21 @@ +import assert from "assert"; +import React from "react"; +import sinon from "sinon"; +import {shallow} from "enzyme"; +import {TabbedTable} from "../src"; + +describe("TabbedTable", () => { + it("renders (something)", () => { + /* + Write tests here that assert qualities about + TabbedTable's type, classes, properties, + and event handling. + + Refer to enzyme's API and examples for Mocha: + http://airbnb.io/enzyme/ + + Refer to sinon's API for mocking event functions: + http://sinonjs.org/docs/ + */ + }); +}); From ba649d1396c065658c48b4f7f8ec9b15a72b6021 Mon Sep 17 00:00:00 2001 From: Peggy Li Date: Thu, 24 Aug 2017 13:10:45 -0700 Subject: [PATCH 2/2] Copy TabbedTable component from apps-dashboard --- src/TabbedTable/Tab.jsx | 13 +++++ src/TabbedTable/TabbedTable.jsx | 81 ++++++++++++++++++++++++++------ src/TabbedTable/TabbedTable.less | 43 +++++++++++++---- 3 files changed, 113 insertions(+), 24 deletions(-) create mode 100644 src/TabbedTable/Tab.jsx diff --git a/src/TabbedTable/Tab.jsx b/src/TabbedTable/Tab.jsx new file mode 100644 index 000000000..d1ee2707c --- /dev/null +++ b/src/TabbedTable/Tab.jsx @@ -0,0 +1,13 @@ +import * as PropTypes from "prop-types"; +import {Table} from "clever-components"; +import MorePropTypes from "clever-components/dist/utils/MorePropTypes"; + + +export default function Tab() { + throw new Error("Configuration component - not meant to be rendered."); +} + +Tab.propTypes = { + children: MorePropTypes.instanceOfComponent(Table), + name: PropTypes.string.isRequired, +}; diff --git a/src/TabbedTable/TabbedTable.jsx b/src/TabbedTable/TabbedTable.jsx index f722319b2..4b42ec4d5 100644 --- a/src/TabbedTable/TabbedTable.jsx +++ b/src/TabbedTable/TabbedTable.jsx @@ -1,27 +1,80 @@ -import React from "react"; +import * as PropTypes from "prop-types"; +import * as React from "react"; +import * as classnames from "classnames"; +import MorePropTypes from "clever-components/dist/utils/MorePropTypes"; + +import Tab from "./Tab"; import "./TabbedTable.less"; -/* - Add a description of your component here. - If your component can be expressed without state, - use the stateless function syntax instead! -*/ -export default class TabbedTable extends React.Component { +export default class TabbedTable extends React.PureComponent { + static cssClass = { + TAB_BAR: "TabbedTable--TabBar", + TITLE: "TabbedTable--Title", + TABS: "TabbedTable--Tabs", + TAB_NAME: "TabbedTable--TabName", + SELECTED_TAB_NAME: "TabbedTable--SelectedTabName", + }; + + static propTypes = { + children: PropTypes.arrayOf(PropTypes.oneOfType([ + MorePropTypes.instanceOfComponent(Tab), + PropTypes.oneOf([null, false]), // allow for conditionally including tabs + ])).isRequired, + title: PropTypes.string, + }; + constructor(props) { super(props); - // Set state and bind methods here + + this.state = { + selectedTabIndex: 0, + }; } - /* Insert any additional lifecycle methods, - event handlers, and helper methods here */ + _onSelect(e, tabIndex) { + e.preventDefault(); + this.setState({selectedTabIndex: tabIndex}); + } render() { - // Fill in render method here + const {cssClass} = TabbedTable; + const {children, title} = this.props; + const {selectedTabIndex} = this.state; + + const tabLinks = React.Children.map(children, (tab, i) => { + if (!tab) { + return null; + } + return ( + this._onSelect(e, i)} + key={tab.props.name} + > + {tab.props.name} + + ); + }); + + const selectedTab = children[selectedTabIndex]; + const tableToRender = React.Children.only(selectedTab.props.children); + return ( +
+
+ {title &&

{title}

} + + + {tabLinks} + +
+ {tableToRender} +
+ ); } } -TabbedTable.propTypes = { - // List required and optional proptypes -} +TabbedTable.Tab = Tab; diff --git a/src/TabbedTable/TabbedTable.less b/src/TabbedTable/TabbedTable.less index 65950a328..8cc895d38 100644 --- a/src/TabbedTable/TabbedTable.less +++ b/src/TabbedTable/TabbedTable.less @@ -1,11 +1,34 @@ -.TabbedTable { - /* - Use namespaced classes that begin with "TabbedTable" - to avoid clashing with global styles. If possible, avoid - over-nesting selectors and instead use clear class names - that convey the purpose and/or state of the element: - - .TabbedTable--container - .TabbedTable--input-disabled - */ +@import (reference) "~clever-components/dist/less/index"; + +.TabbedTable--TabBar { + .margin--bottom--m; +} + +.TabbedTable--Title { + display: inline-block; + border-right: @size_4xs solid @neutral_gray; + color: @neutral_black; + padding: @size_2xs @size_m; + .margin--right--m; + .text--large; + .text--semi-bold; +} + +.TabbedTable--Tabs { + font-size: @size_s; + color: @neutral_dark_gray; +} + +.TabbedTable--TabName { + .margin--left--s; + color: @neutral_dark_gray; +} + +.TabbedTable--TabName:hover { + cursor: pointer; +} + +.TabbedTable--SelectedTabName { + color: @primary_blue; + .text--semi-bold; }