diff --git a/src/Tabs.js b/src/Tabs.js new file mode 100644 index 0000000..88c2409 --- /dev/null +++ b/src/Tabs.js @@ -0,0 +1,122 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; +import withRipple from './withRipple'; +import colorGetter from './colorGetter'; +import { sizes } from './media'; + +const TabContent = styled.div` + flex: 1; + width: 100%; +`; + +const TabPanel = ({ children }) => ( + {children} +); + +TabPanel.propTypes = { + children: PropTypes.any.isRequired, +}; + +class Tabs extends Component { + static Panel = TabPanel; + + static propTypes = { + children: PropTypes.any.isRequired, + tabBreak: PropTypes.string, + }; + + static defaultProps = { + tabBreak: `${sizes.tablet}px`, + }; + + state = { + selectedTab: 0, + }; + + selectTab = (tabIndex) => { + this.setState({ selectedTab: tabIndex }); + }; + + render() { + const { children, tabBreak } = this.props; + const { selectedTab } = this.state; + + return ( + + + {React.Children.map(children, ({ props: { label } }, index) => + this.selectTab(index)} + > + {label} + + )} + + + + {React.Children.map(children, (comp, index) => + selectedTab === index ? comp : undefined + )} + + + ); + } +} + +const TabsWrapper = styled.div` + flex: 1; + display: flex; + flex-direction: column; +`; + +const TabButton = withRipple(styled.button` + flex: 1; + height: 50px; + padding: 0px 24px; + display: flex; + align-items: center; + justify-content: center; + font-size: 16px; + cursor: default; + background: transparent; + outline: none; + transition: border-color 0.2s ease-in; + border: none; + border-bottom: 4px solid ${props => props.selected + ? colorGetter(props, 'primaryColorDark') + : '#fff' + }; + + &:hover, &:focus, &:active { + border-bottom: 4px solid ${props => props.selected + ? colorGetter(props, 'primaryColorDark') + : colorGetter(props, 'greyLighter') + }; + } +`); + +const TabList = styled.div` + display: flex; + flex-direction: row; + width: 100%; + + @media (max-width: ${props => props.breakPoint}) { + flex-direction: column; + & > div, + & > div > button { + width: 100%; + } + } +`; + +const Content = styled.div` + flex: 1; + width: 100%; + padding-top: 16px; +`; + +export default Tabs; diff --git a/src/index.js b/src/index.js index 96b795f..810f8d2 100644 --- a/src/index.js +++ b/src/index.js @@ -31,3 +31,4 @@ export { default as OutsideReactor } from './OutsideReactor'; export { default as Drawer } from './Drawer'; export { default as Dropmenu } from './Dropmenu'; export { default as Modal } from './Modal'; +export { default as Tabs } from './Tabs'; diff --git a/src/media.js b/src/media.js index 2490821..b7b81cd 100644 --- a/src/media.js +++ b/src/media.js @@ -1,7 +1,7 @@ /* eslint-disable no-param-reassign */ import { css } from 'styled-components'; -const sizes = { +export const sizes = { giant: 1170, desktop: 992, tablet: 768,