import { NavigationChevronLeft, NavigationChevronRight } from '@repay/cactus-icons' import React from 'react' import styled, { ThemeContext } from 'styled-components' import Box, { BoxProps } from '../Box/Box' import Flex, { JustifyContent } from '../Flex/Flex' import { keyDownAsClick, preventAction } from '../helpers/a11y' import { AsProps, GenericComponent } from '../helpers/asProps' import { flexItem, FlexItemProps } from '../helpers/flexItem' import { FocusSetter, useFocusControl } from '../helpers/focus' import { omitProps } from '../helpers/omit' import { useValue } from '../helpers/react' import { BUTTON_WIDTH, GetScrollInfo, ScrollButton, useScroll } from '../helpers/scroll' import { border, insetBorder, isResponsiveTouchDevice, media, textStyle } from '../helpers/theme' interface TabListProps extends Omit, 'role'> { fullWidth?: boolean justifyContent?: JustifyContent fillGaps?: boolean } interface TabProps extends FlexItemProps { /** Name of the tab, used by the controller to auto-generate `id` and `panelId` */ name?: string /** ID of the panel this tab controls; directly mapped to `aria-controls` */ panelId?: string children?: React.ReactNode } interface TabPanelProps extends BoxProps, Omit, 'color'> { /** Name of the tab, used by the controller to auto-generate `id` and `tabId` */ tab?: string /** ID of the tab that controls this panel; directly mapped to `aria-labelledby` */ tabId?: string } interface TabControllerProps { children?: React.ReactNode id?: string initialTabId?: string } interface TabContextType { id?: string currentTab: string | null setCurrent: React.MouseEventHandler } const TabContext = React.createContext(undefined) export const TabList: React.FC = ({ fullWidth = true, fillGaps = false, onFocus, onBlur, ...props }) => { const id = React.useContext(TabContext)?.id const theme = React.useContext(ThemeContext) const orientation = props['aria-orientation'] || 'horizontal' const [listRef, scroll] = useScroll(orientation, true, getScrollInfo) const [setFocus, rootRef] = useFocusControl(getTabs) // Other values may center things strangely resulting in inaccessible tabs. if (scroll.showScroll) { props.justifyContent = 'flex-start' } const showScroll = scroll.showScroll && !isResponsiveTouchDevice(theme.breakpoints) const keyHandler = useKeyHandler(setFocus) const focusHandler = useFocusHandler(setFocus, onFocus) const blurHandler = React.useCallback( (e) => { e.currentTarget.tabIndex = 0 onBlur?.(e) }, [onBlur] ) return ( ) } TabList.defaultProps = { fullWidth: true, fillGaps: false, justifyContent: 'flex-start', 'aria-orientation': 'horizontal', } function TabFunc( { name, panelId, ...props }: TabProps & AsProps, ref: React.Ref ) { const ctx = React.useContext(TabContext) if (ctx && name) { props.id = props.id || generateId(ctx.id, name, 'tab') panelId = panelId || generateId(ctx.id, name, 'panel') } return ( ) } const TabFR = React.forwardRef(TabFunc) as any export const Tab = TabFR as typeof TabFunc TabFR.displayName = 'Tab' export const TabPanel: React.FC = ({ tab, tabId, ...props }) => { const ctx = React.useContext(TabContext) if (ctx && tab) { props.id = props.id || generateId(ctx.id, tab, 'panel') tabId = tabId || generateId(ctx.id, tab, 'tab') } return ( // @ts-ignore Says the type of `color` is wrong, can't figure out why.