Skip to content

Instantly share code, notes, and snippets.

@Temzasse
Created November 1, 2017 09:21
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Temzasse/638f47c165455c37853756ee2ce2b324 to your computer and use it in GitHub Desktop.
Save Temzasse/638f47c165455c37853756ee2ce2b324 to your computer and use it in GitHub Desktop.
A React.js + styled-components Tabs component
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import withRipple from './withRipple';
const TabContent = styled.div`
flex: 1;
width: 100%;
`;
const TabPanel = ({ children }) => (
<TabContent role='tabpanel' tabindex='0'>{children}</TabContent>
);
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: '768px',
};
state = {
selectedTab: 0,
};
selectTab = (tabIndex) => {
this.setState({ selectedTab: tabIndex });
};
render() {
const { children, tabBreak } = this.props;
const { selectedTab } = this.state;
return (
<TabsWrapper>
<TabList breakPoint={tabBreak} role='tablist'>
{React.Children.map(children, ({ props: { label } }, index) =>
<TabButton
role='tab'
selected={selectedTab === index}
aria-selected={selectedTab === index ? 'true' : 'false'}
onClick={() => this.selectTab(index)}
>
{label}
</TabButton>
)}
</TabList>
<Content>
{React.Children.map(children, (comp, index) =>
selectedTab === index ? comp : undefined
)}
</Content>
</TabsWrapper>
);
}
}
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 ? 'blue' : '#fff'};
&:hover, &:focus, &:active {
border-bottom: 4px solid ${props => props.selected ? 'blue' : '#eee'};
}
`);
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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment