import React from 'react'; import styles from '@patternfly/react-styles/css/components/Tabs/tabs'; import { css } from '@patternfly/react-styles'; import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; import { Popper } from '../../helpers'; import { Menu, MenuContent, MenuList, MenuItem } from '../Menu'; import { TabsContext } from './TabsContext'; import { TabProps } from './Tab'; import { TabTitleText } from './TabTitleText'; export interface OverflowTabProps extends React.HTMLProps { /** Additional classes added to the overflow tab */ className?: string; /** The tabs that should be displayed in the menu */ overflowingTabs?: TabProps[]; /** Flag which shows the count of overflowing tabs when enabled */ showTabCount?: boolean; /** The text which displays when an overflowing tab isn't selected */ defaultTitleText?: string; /** The aria label applied to the button which toggles the tab overflow menu */ toggleAriaLabel?: string; /** z-index of the overflow tab */ zIndex?: number; /** Flag indicating if scroll on focus of the first menu item should occur. */ shouldPreventScrollOnItemFocus?: boolean; /** Time in ms to wait before firing the toggles' focus event. Defaults to 0 */ focusTimeoutDelay?: number; } export const OverflowTab: React.FunctionComponent = ({ className, overflowingTabs = [], showTabCount, defaultTitleText = 'More', toggleAriaLabel, zIndex = 9999, shouldPreventScrollOnItemFocus = true, focusTimeoutDelay = 0, ...props }: OverflowTabProps) => { const menuRef = React.useRef(); const overflowTabRef = React.useRef(); const overflowLIRef = React.useRef(); const [isExpanded, setIsExpanded] = React.useState(false); const { localActiveKey, handleTabClick } = React.useContext(TabsContext); const closeMenu = () => { setIsExpanded(false); overflowTabRef.current.focus(); }; const handleMenuKeys = (ev: KeyboardEvent) => { const menuContainsEventTarget = menuRef?.current?.contains(ev.target as Node); if (isExpanded && menuContainsEventTarget && ev.key === 'Escape') { closeMenu(); } }; const handleClick = (ev: MouseEvent) => { const clickIsOutsideMenu = !menuRef?.current?.contains(ev.target as Node); const clickIsOutsideOverflowTab = !overflowTabRef?.current?.contains(ev.target as Node); if (isExpanded && clickIsOutsideMenu && clickIsOutsideOverflowTab) { closeMenu(); } }; React.useEffect(() => { window.addEventListener('click', handleClick); window.addEventListener('keydown', handleMenuKeys); return () => { window.removeEventListener('click', handleClick); window.removeEventListener('keydown', handleMenuKeys); }; }, [isExpanded, menuRef, overflowTabRef]); const selectedTab = overflowingTabs.find((tab) => tab.eventKey === localActiveKey); const tabTitle = selectedTab?.title ? selectedTab.title : defaultTitleText; const toggleMenu = () => { setIsExpanded((prevIsExpanded) => !prevIsExpanded); setTimeout(() => { if (menuRef?.current) { const firstElement = menuRef.current.querySelector('li > button,input:not(:disabled)'); firstElement && (firstElement as HTMLElement).focus({ preventScroll: shouldPreventScrollOnItemFocus }); } }, focusTimeoutDelay); }; const overflowTab = (