import type { ReactNode, FunctionComponent } from 'react'; import { Children, isValidElement, useState, useContext } from 'react'; import { Button, Dropdown, DropdownList, MenuToggle, OverflowMenu, OverflowMenuContent, OverflowMenuControl, OverflowMenuDropdownItem, OverflowMenuGroup, OverflowMenuItem, OverflowMenuProps } from '@patternfly/react-core'; import { EllipsisVIcon } from '@patternfly/react-icons'; import { ResponsiveActionProps } from '../ResponsiveAction'; import { OverflowMenuContext } from '@patternfly/react-core/dist/esm/components/OverflowMenu/OverflowMenuContext'; /** extends OverflowMenuProps */ export interface ResponsiveActionsProps extends Omit { /** Indicates breakpoint at which to switch between horizontal menu and vertical dropdown */ breakpoint?: OverflowMenuProps['breakpoint']; /** Custom OUIA ID */ ouiaId?: string; /** Child actions to be displayed */ children: React.ReactNode; } const ResponsiveActionsDropdown: FunctionComponent<{ ouiaId: string; dropdownItems: ReactNode[]; pinnedItemsDisabled: boolean[]; regularItemsDisabled: boolean[]; }> = ({ ouiaId, dropdownItems, pinnedItemsDisabled, regularItemsDisabled }) => { const [ isOpen, setIsOpen ] = useState(false); const { isBelowBreakpoint } = useContext(OverflowMenuContext); const isKebabDisabled = (() => { const allPinnedDisabled = pinnedItemsDisabled.length > 0 && pinnedItemsDisabled.every(disabled => disabled); const allRegularDisabled = regularItemsDisabled.length > 0 && regularItemsDisabled.every(disabled => disabled); if (isBelowBreakpoint) { return (pinnedItemsDisabled.length > 0 || regularItemsDisabled.length > 0) && (pinnedItemsDisabled.length === 0 || allPinnedDisabled) && (regularItemsDisabled.length === 0 || allRegularDisabled); } else { return allRegularDisabled; } })(); return ( setIsOpen(false)} toggle={(toggleRef) => ( } onClick={() => setIsOpen(!isOpen)} isExpanded={isOpen} isDisabled={isKebabDisabled} /> )} isOpen={isOpen} onOpenChange={setIsOpen} > {dropdownItems} ); }; export const ResponsiveActions: FunctionComponent = ({ ouiaId = 'ResponsiveActions', breakpoint = 'lg', children, ...props }: ResponsiveActionsProps) => { // separate persistent, pinned and collapsed actions const persistentActions: ReactNode[] = []; const pinnedActions: ReactNode[] = []; const dropdownItems: ReactNode[] = []; const pinnedItemsDisabled: boolean[] = []; const regularItemsDisabled: boolean[] = []; let hasRegularActions = false; Children.forEach(children, (child, index) => { if (isValidElement(child)) { const { isPersistent, isPinned, children, onClick, ...actionProps } = child.props; const key = child.key ?? index; if (isPersistent || isPinned) { (isPersistent ? persistentActions : pinnedActions).push( ); } else { hasRegularActions = true; } if (!isPersistent) { dropdownItems.push( {children} ); if (isPinned) { pinnedItemsDisabled.push(!!actionProps.isDisabled); } else { regularItemsDisabled.push(!!actionProps.isDisabled); } } } }); // Only render OverflowMenu if there are actions to display if (persistentActions.length === 0 && pinnedActions.length === 0 && dropdownItems.length === 0) { return null; } return ( {persistentActions.length > 0 ? ( {persistentActions} ) : null} {pinnedActions.length > 0 ? ( {pinnedActions} ) : null} {dropdownItems.length > 0 && ( )} ); }; export default ResponsiveActions;