import { LayoutGroup, motion } from 'framer-motion'; import React, { useEffect, useState } from 'react'; import { isMobile } from 'react-device-detect'; import styled from 'styled-components'; import { Alignment, Size, ThemeMode } from '../../types'; import { getThemedColor } from '../../utils/colorUtils'; import Typography, { TypographyWeight } from '../Typography'; import { SLIDER_ANIMATION_DURATION, TabsProps, TabsSize, TYPOGRAPHY_SIZE } from './Tabs.constants'; import { SLIDER_CSS, TABS_CONTAINER_CSS, TAB_CELL_CSS } from './Tabs.styles'; const TabsContainer = styled(motion.ul)<{ $size: TabsSize; $forceTheme?: ThemeMode; $fullWidth?: boolean }>` display: flex; align-items: center; list-style-type: none; margin: 0; padding: 4px; box-sizing: border-box; background: ${(props) => getThemedColor('var(--bg-field-default)', props.$forceTheme)}; width: ${(props) => (props.$fullWidth || isMobile ? '100%' : 'fit-content')}; ${TABS_CONTAINER_CSS} `; const TabCell = styled(motion.li)<{ $size: TabsSize; $isClickable: boolean }>` width: 100%; position: relative; isolation: isolate; cursor: ${(props) => (props.$isClickable ? 'pointer' : 'default')}; ${TAB_CELL_CSS} `; const Slider = styled(motion.div)<{ $size: TabsSize; $forceTheme?: ThemeMode }>` position: absolute; top: 0; left: 0; right: 0; z-index: -1; height: 100%; background: ${(props) => getThemedColor('var(--bg-l3-solid)', props.$forceTheme)}; box-shadow: ${(props) => getThemedColor('var(--shadow-l1)', props.$forceTheme)}; ${SLIDER_CSS} `; /** * Component that renders tabs to filter between two or more pages. */ const Tabs: React.FC = ({ tabs, forceTheme, fullWidth, size = Size.MEDIUM }: TabsProps) => { const typographySize = TYPOGRAPHY_SIZE[size]; // Whether or not the component has mounted const [isLoaded, setIsLoaded] = useState(false); // Needed to disable the slider animation on mount useEffect(() => { setIsLoaded(true); }, []); return ( {tabs.map(({ active, label, onClick }) => ( {label} {active && ( )} ))} ); }; export default Tabs;