import { cloneElement, forwardRef } from "react"; import { Box } from "../box"; import { useScrollbarWidth } from "../../utils"; import { StyledContent, StyledCount, StyledList, StyledTabs, StyledTabName, StyledTrigger, } from "./tabs.styled"; import type { UrlObject } from "url"; interface TabData { index: string; tabName: | string | React.ReactElement<{ href: string | UrlObject; children?: React.ReactNode; onMouseDown: (e: MouseEvent) => void; }>; content: React.ReactNode; count?: number | undefined; } export interface TabsProps extends React.ComponentProps { ariaLabel: string; defaultTab: string; tabs: TabData[]; listProps?: Omit, "aria-label" | "data-show-scrollbars">; triggerProps?: Omit, "value">; contentProps?: Omit, "value">; } export const Tabs = forwardRef( // eslint-disable-next-line max-lines-per-function ( { ariaLabel, defaultTab, tabs, onValueChange, value, listProps, triggerProps, contentProps, ...rootProps }, ref ) => { const width = useScrollbarWidth(); const shouldOverrideScrollbars = width > 0; return ( {tabs.map((tab) => { const count = typeof tab.count === "number" && ( {tab.count} ); const tabName = typeof tab.tabName !== "string" ? ( cloneElement( tab.tabName, { onMouseDown: (e: MouseEvent) => { if (process.env.NODE_ENV !== "development") { // prevent default prohibits actual tab change in the radix tab component // new page will be loaded because of URL change, and it will take care of updating the contents // but on development it's slow for next.js to rebuild the page (it does that on each navigation) // so we allow this tab change to happen on development - it causes blink, but faster = better DX e.preventDefault(); } }, }, <> {tab.tabName.props.children} {count} ) ) : ( <> {tab.tabName} {count} ); return ( {tabName} ); })} {tabs.map((tab) => { return ( {tab.content} ); })} ); } ); Tabs.displayName = "Tabs";