import classNames from 'classnames'; import { useRouter } from 'next/router'; import { Children, isValidElement, ReactNode, useCallback, useEffect, useState, } from 'react'; interface GridTabsProps { children: ReactNode; group: string; } export const GridTabs = ({ children, group }: GridTabsProps) => { const { query, asPath, replace } = useRouter(); const [activeTab, setActiveTab] = useState(() => { if (query[group]) { return query[group]; } // Default to first tab return children[0].props.name; }); // Using replace inside an effect causes a render loop. Seems like its not using useCallback // eslint-disable-next-line const safeReplace = useCallback((path: string) => replace(path), []); // Update the query string in the url when the active tab changes // uses group property as the query stirng key useEffect(() => { const [url, queryString] = asPath.split('?'); const searchParams = new URLSearchParams(queryString); searchParams.set(group, activeTab as string); safeReplace(`${url}?${searchParams.toString()}`); }, [activeTab, group, asPath, safeReplace]); return (
{/* the tabs */}
{Children.map(children, (child) => { if (isValidElement(child)) { return ( setActiveTab(child.props.name)} /> ); } return null; })}
{/* the content */}
{Children.map(children, (child) => { if (isValidElement(child) && activeTab === child.props.name) { return ( {child.props.children} ); } return null; })}
); }; interface GridTabProps { children: ReactNode; name: string; } export const GridTab = ({ children }: GridTabProps) => { return
{children}
; }; interface GridTabControlProps { group: string; name: string; isActive: boolean; onClick: () => void; } const GridTabControl = ({ group, name, isActive, onClick, }: GridTabControlProps) => { const buttonClass = classNames( 'py-4', 'px-12', 'border-t border-neutral-200', 'capitalize', { 'text-vega-pink': isActive, 'bg-white': isActive, } ); return ( ); }; interface GridTabPanelProps { group: string; name: string; children: ReactNode; } const GridTabPanel = ({ group, name, children }: GridTabPanelProps) => { return (
{children}
); };