Skip to content

Instantly share code, notes, and snippets.

@craig-jennings
Last active November 16, 2020 18:00
Show Gist options
  • Save craig-jennings/526710c8b3e080e669f8d8a60c6263d8 to your computer and use it in GitHub Desktop.
Save craig-jennings/526710c8b3e080e669f8d8a60c6263d8 to your computer and use it in GitHub Desktop.
Simple React Tab Component
function Tabs({ children, defaultActiveTab, lazyLoadPanel }) {
/* -- Hooks -- */
const [activeTab, setActiveTab] = useState(defaultActiveTab || children[0]?.props.label);
/* -- Event Handlers -- */
/* -- Rendering -- */
const tabList = [];
const panels = [];
let panel = null;
React.Children.forEach(children, (child) => {
const { label } = child.props;
const isActive = label === activeTab;
tabList.push(
<div isActive={isActive} key={label} onClick={() => setActiveTab(label)}> {/* This container can be styled */}
{child.props.children[0]}
</div>,
);
if (lazyLoadPanel && isActive) {
panel = <div key={label}>{child.props.children[1]}</div>;
} else {
panels.push(
<div style={{ display: isActive ? 'block' : 'none' }} key={label}>
{child.props.children[1]}
</div>,
);
}
});
return (
<div>
<div>{tabList}</div> {/* Container should be styled */}
<div>{lazyLoadPanel ? panel : panels}</div> {/* Container should be styled */}
</div>
);
}
Tabs.propTypes = {
children: PropTypes.node,
defaultActiveTab: PropTypes.string,
lazyLoadPanel: PropTypes.bool,
};
// These are just structure components that have no actual functionality associated with them
const Tab = ({ children }) => children;
Tab.Header = ({ children }) => children;
Tab.Panel = ({ children }) => children;
Tab.propTypes = {
children: PropTypes.node,
label: PropTypes.string.isRequired,
};
export default Tabs;
export { Tab };
function MyTabs() {
  return (
    <Tabs defaultActiveTab="iron-man">
      <Tab label="captain-america">
        <Tab.Header>Captain America</Tab.Header>
        <Tab.Panel>He's so cool!</Tab.Panel>
      </Tab>
    
      <Tab label="batman">
        <Tab.Header>Batman</Tab.Header>
        <Tab.Panel>Dark and brooding</Tab.Panel>
      </Tab>
    
      <Tab label="iron-man">
        <Tab.Header>Iron Man</Tab.Header>
        <Tab.Panel>Rich, Playboy Philanthropist</Tab.Panel>
      </Tab>
    </Tabs>
  );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment