import React, { Fragment, ReactNode, useEffect, useState } from 'react'; import { css } from 'styled-components'; import { lighten } from 'polished'; import { Flex, Wrapper, WrapperProps, black, secondary, borderRadius, boxShadow, centerX, Line, Text, } from 'dot-design-system'; import { fontSizes } from '../styles/typography'; import { arrayToObject, liftChildren } from '../utils/arrays'; import { useStateEffect } from 'dot-utils'; export interface TabItem { key: string; title: string; icon?: any; onClick?: () => boolean; tab: () => ReactNode; subMenu?: TabItem[]; } interface Props extends WrapperProps { tabs: TabItem[]; renderAfterTabs?: () => ReactNode; variant: 'clean' | 'dark' | 'mini'; activeKey?: string; onTabSelect?: (newActiveKey: string) => boolean; containerProps?: WrapperProps; } export enum MenuType { Dark = 'dark', Clean = 'clean', Mini = 'mini', } type VariantProps = { [Type in MenuType]: { line?: WrapperProps; nav: WrapperProps; item: WrapperProps; underline?: string; }; }; const variantProps: VariantProps = { dark: { line: {}, nav: { background: black, borderRadius, px: 20, css: css` display: inline-flex; && { @media (max-width: 870px) { * { font-size: 14px; } } @media (max-width: 650px) { padding-left: 0; padding-right: 0; * { font-size: 12px; } } @media (max-width: 410px) { p { font-size: 10px; } } } `, }, item: { color: '#fff', css: css` && { &:hover { background-color: ${lighten(0.1, black)}; } @media (max-width: 550px) { flex-direction: column; padding: 10px; * { margin: 0; } } } `, }, underline: secondary, }, clean: { line: { mt: -7, opacity: 0.3, }, nav: { css: ``, }, item: { py: 5, px: 0, mr: 15, fontSize: fontSizes.theta, }, underline: black, }, mini: { nav: { css: ``, }, item: {}, underline: black, }, }; function TabsMenu({ tabs, renderAfterTabs = () => null, variant, activeKey, onTabSelect, css: cssProp, containerProps = {}, ...props }: Props) { const [active, setActive] = useStateEffect(activeKey || tabs[0].key); const tabMap = arrayToObject('key', liftChildren('subMenu', tabs)); const handleChange = (key: string) => () => { const newTab = tabMap[key]; const onClick = newTab.onClick; if (onClick) { const canChange = onClick(); if (!canChange) { return; } } if (onTabSelect) { const canChange = onTabSelect(key); if (!canChange) { return; } } return setActive(key); }; const currentTab = tabMap[active]; const thisProps = variantProps[variant]; useEffect(() => { if (activeKey && activeKey !== active) { setActive(activeKey); } }, [activeKey]); const hasSubmenu = tabs.some((tab) => !!tab.subMenu); const containerStyles = css` position: relative; ${thisProps.nav.css}; z-index: ${(hasSubmenu && 3) || 2}; `; return ( {tabs.map((item: TabItem) => { const isActive = item.key === active || item?.subMenu?.some((subItem) => subItem.key === active); return ( {item.icon || null} {item.title} {thisProps.underline && ( )} {item.subMenu && ( {item.subMenu.map((subItem) => ( {subItem.title} ))} )} ); })} {thisProps.line && } {renderAfterTabs()} {currentTab.tab()} ); } export default TabsMenu;