import React, { useState, useEffect, useRef } from 'react'; import './Tabs.scss'; import NoData from '../NoData/NoData'; import Icon from '../Icon'; interface TabComponentProps { /** * Label for the tab */ label: string; /** * Optional icon name for the tab */ iconName?: string; /** * Optional icon/text/both display options for the tab */ iconText?: 'icon' | 'text' | 'both'; /** * Function to handle the click event on the tab */ onClick: () => void; /** * Boolean to indicate if the tab is active */ isActive: boolean; /** * Optional flag to disable the tab */ disabled?: boolean; /** * Optional submenu associated with the tab */ submenu?: React.ReactNode; /** * Optional function to handle submenu click */ onSubmenuClick?: () => void; /** * Boolean to indicate if the submenu is open */ isSubmenuOpen?: boolean; } const TabComponent: React.FC = ({ label, iconName, iconText, onClick, isActive, disabled, submenu, onSubmenuClick, isSubmenuOpen, }) => { const submenuRef = useRef(null); return (
{(iconText === 'icon' || iconText === 'both') && ( )} {(iconText === 'text' || iconText === 'both') && {label}} {submenu && (
{isSubmenuOpen && (
{submenu}
)}
)}
); }; interface ContentComponentProps { /** * The content that is rendered in the content area of the tab */ children: React.ReactNode; } const ContentComponent: React.FC = ({ children }) => { return
{children}
; }; interface Tab { /** * Unique identifier for the tab */ id: string; /** * Label for the tab */ label: string; /** * Optional icon name for the tab */ iconName?: string; /** * Icon/Text display option for the tab */ iconText?: 'icon' | 'text' | 'both'; /** * The component/content rendered for the tab */ component: React.ReactNode; /** * Optional flag to disable the tab */ disabled?: boolean; /** * Optional submenu component */ submenu?: React.ReactNode; } interface TabsProps { /** * Array of Tab objects to be rendered in the tab bar */ tabs: Tab[]; } const Tabs: React.FC = ({ tabs }) => { const [activeTab, setActiveTab] = useState(tabs[0]?.id || ''); const [scrollPosition, setScrollPosition] = useState(0); const [showScrollButtons, setShowScrollButtons] = useState(false); const [openSubmenuId, setOpenSubmenuId] = useState(null); const tabBarRef = useRef(null); const tabContainerRef = useRef(null); const handleTabClick = (id: string) => { const selectedTab = tabs.find((tab) => tab.id === id); if (selectedTab && !selectedTab.disabled) { setActiveTab(id); setOpenSubmenuId(null); } }; const handleScroll = (direction: 'left' | 'right') => { if (tabBarRef.current) { const containerWidth = tabContainerRef.current?.offsetWidth || 0; const tabBarWidth = tabBarRef.current.scrollWidth; const step = 100; setScrollPosition((prevPosition) => { let newPosition = prevPosition + (direction === 'left' ? -step : step); if (newPosition < 0) newPosition = 0; if (newPosition > tabBarWidth - containerWidth) newPosition = tabBarWidth - containerWidth; return newPosition; }); } }; const checkOverflow = () => { if (tabBarRef.current && tabContainerRef.current) { const containerWidth = tabContainerRef.current.offsetWidth; const tabBarWidth = tabBarRef.current.scrollWidth; setShowScrollButtons(tabBarWidth > containerWidth); } }; useEffect(() => { checkOverflow(); window.addEventListener('resize', checkOverflow); return () => window.removeEventListener('resize', checkOverflow); }, [tabs, scrollPosition]); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { const submenu = document.querySelector('.submenu'); if (submenu && !submenu.contains(event.target as Node)) { setOpenSubmenuId(null); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); const handleSubmenuClick = (id: string) => { setOpenSubmenuId((prevId) => (prevId === id ? null : id)); }; const renderTabs = () => { return tabs.map((tab) => ( handleTabClick(tab.id)} disabled={tab.disabled} submenu={tab.submenu} isSubmenuOpen={tab.id === openSubmenuId} onSubmenuClick={() => handleSubmenuClick(tab.id)} /> )); }; const activeTabContent = tabs.find((tab) => tab.id === activeTab)?.component; return (
{showScrollButtons && ( )}
{renderTabs()}
{showScrollButtons && ( )}
{activeTabContent ? ( {activeTabContent} ) : ( )}
); }; export default Tabs;