import React, {JSXElementConstructor, ReactNode, useContext} from 'react'; import clsx from 'clsx'; import {useFocusManager} from '@react-aria/focus'; import {TabContext} from './tabs-context'; import {LinkProps} from 'react-router-dom'; export interface TabProps { className?: string; index?: number; children: ReactNode; isDisabled?: boolean; padding?: string; elementType?: 'button' | 'a' | JSXElementConstructor; to?: LinkProps['to']; relative?: LinkProps['relative']; replace?: LinkProps['replace']; width?: string; } export function Tab({ index, className, isDisabled, children, padding: paddingProp, elementType = 'button', to, relative, width = 'min-w-min', }: TabProps) { const { selectedTab, setSelectedTab, tabsRef, size = 'md', id, } = useContext(TabContext); const isSelected = index === selectedTab; const focusManager = useFocusManager(); const padding = paddingProp || (size === 'sm' ? 'px-12' : 'px-18'); const mergedClassname = clsx( 'tracking-wide overflow-hidden capitalize text-sm flex items-center justify-center outline-none transition-colors', 'focus-visible:ring focus-visible:ring-2 ring-inset rounded whitespace-nowrap cursor-pointer', width, textColor({isDisabled, isSelected}), className, size === 'md' && `${padding} h-48`, size === 'sm' && `${padding} h-32`, isDisabled && 'pointer-events-none', ); const onKeyDown = (e: React.KeyboardEvent) => { switch (e.key) { case 'ArrowLeft': focusManager?.focusPrevious(); break; case 'ArrowRight': focusManager?.focusNext(); break; case 'Home': focusManager?.focusFirst(); break; case 'End': focusManager?.focusLast(); break; } }; const tabIndex = isSelected ? 0 : -1; const Element = elementType; return ( { setSelectedTab(index!); }} to={to} relative={relative} className={mergedClassname} ref={(el: HTMLElement) => { if (tabsRef.current && el) { tabsRef.current[index!] = el; } }} > {children} ); } interface TextColorProps { isDisabled?: boolean; isSelected: boolean; } function textColor({isDisabled, isSelected}: TextColorProps): string { if (isDisabled) { return 'text-disabled cursor-default'; } if (isSelected) { return 'text-primary'; } return 'text-muted hover:text-main'; }