All files / src/components/Tabs index.tsx

0% Statements 0/18
0% Branches 0/11
0% Functions 0/6
0% Lines 0/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118                                                                                                                                                                                                                                           
import React, { useEffect, useState } from 'react';
import { TabContext, TabList, TabPanel } from '@mui/lab';
import { Box, Tab as MuiTab, useTheme } from '@mui/material';
import { useDeviceInfo } from '../../utils';
import Icon from '../Icon/Icon';
import { IconName } from '../Icon/icons';
 
export type Tab = {
  icon?: IconName;
  id: string;
  label: string;
  children: React.ReactNode;
  disabled?: boolean;
};
 
export type TabsProps = {
  tabs: Tab[];
  onTabChange?: (tab: string) => void;
  activeTab?: string;
};
 
const Tabs = ({ tabs, onTabChange, activeTab }: TabsProps): JSX.Element => {
  const [selectedTab, setSelectedTab] = useState<string>(activeTab ?? tabs[0]?.id ?? '');
  const theme = useTheme();
  const { isMobile } = useDeviceInfo();
 
  const tabStyles = {
    color: theme.palette.TwClrTxtSecondary as string,
    fontSize: '16px',
    fontWeight: 600,
    lineHeight: '24px',
    padding: theme.spacing(1, 2),
    minHeight: theme.spacing(4.5),
    textTransform: 'capitalize',
    '&:hover': {
      backgroundColor: theme.palette.TwClrBgHover as string,
    },
    '&.Mui-selected': {
      color: theme.palette.TwClrTxtBrand as string,
    },
    '&.MuiTab-labelIcon': {
      display: 'flex',
      flexDirection: 'row',
      alignItems: 'center',
    },
    '& .MuiTab-iconWrapper': {
      fill: theme.palette.TwClrIcnSecondary as string,
      marginBottom: 0,
      marginRight: theme.spacing(1),
    },
    '&.Mui-selected .MuiTab-iconWrapper': {
      fill: theme.palette.TwClrIcnBrand as string,
    },
  };
 
  const tabHeaderProps = {
    borderBottom: 1,
    borderColor: 'divider',
    margin: isMobile ? 0 : theme.spacing(0, 4),
  };
 
  const tabPanelStyles = {
    padding: 0,
  };
 
  const setTab = (tab: string) => {
    if (onTabChange) {
      onTabChange(tab);
    } else {
      setSelectedTab(tab);
    }
  };
 
  useEffect(() => {
    if (activeTab !== undefined) {
      setSelectedTab(activeTab);
    }
  }, [activeTab]);
 
  return (
    <Box sx={{ width: '100%' }}>
      <TabContext value={selectedTab}>
        <Box sx={tabHeaderProps}>
          <TabList
            variant='scrollable'
            sx={{ minHeight: theme.spacing(4.5) }}
            onChange={(unused, value: string) => setTab(value)}
            TabIndicatorProps={{
              style: {
                background: theme.palette.TwClrBgBrand,
                height: '4px',
              },
            }}
          >
            {tabs.map((tab, index) => (
              <MuiTab
                icon={tab.icon ? <Icon name={tab.icon} /> : undefined}
                label={tab.label}
                value={tab.id}
                sx={tabStyles}
                key={index}
                disabled={tab.disabled}
              />
            ))}
          </TabList>
        </Box>
        {tabs.map((tab, index) => (
          <TabPanel value={tab.id} key={index} sx={tabPanelStyles}>
            {tab.children}
          </TabPanel>
        ))}
      </TabContext>
    </Box>
  );
};
 
export default Tabs;