diff --git a/framework/PageActions/PageActionDropdown.tsx b/framework/PageActions/PageActionDropdown.tsx index 27be75bbb2..7bb6b5951b 100644 --- a/framework/PageActions/PageActionDropdown.tsx +++ b/framework/PageActions/PageActionDropdown.tsx @@ -1,16 +1,18 @@ -import { ButtonVariant, Tooltip } from '@patternfly/react-core'; import { + ButtonVariant, + Divider, Dropdown, DropdownItem, - DropdownPosition, - DropdownSeparator, - DropdownToggle, - KebabToggle, -} from '@patternfly/react-core/deprecated'; -import { CircleIcon } from '@patternfly/react-icons'; + DropdownList, + DropdownPopperProps, + Icon, + MenuToggle, + MenuToggleElement, + Tooltip, +} from '@patternfly/react-core'; +import { CircleIcon, EllipsisVIcon } from '@patternfly/react-icons'; import { ComponentClass, FunctionComponent, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Link } from 'react-router-dom'; import styled from 'styled-components'; import { PFColorE, getPatternflyColor } from '../components/pfcolors'; import { getID } from '../hooks/useID'; @@ -40,7 +42,7 @@ interface PageActionDropdownProps { isDisabled?: string | undefined; label?: string; onOpen?: (label: string, open: boolean) => void; - position?: DropdownPosition; + position?: DropdownPopperProps['position']; selectedItem?: T; selectedItems?: T[]; tooltip?: string; @@ -97,64 +99,15 @@ export function PageActionDropdown(props: PageActionDropdownPr const id = getID(props.label ?? 'actions-dropdown'); if (actions.length === 0) return <>; - const Icon = icon; const isPrimary = variant === ButtonVariant.primary || (hasBulkActions && !!selectedItems?.length); /** Turn primary button to secondary if there are items selected */ const isSecondary = variant === ButtonVariant.primary && !hasBulkActions && !!selectedItems?.length; - const Toggle = - label || Icon ? ( - setDropdownOpen(!dropdownOpen)} - toggleVariant={isSecondary ? 'secondary' : isPrimary ? 'primary' : undefined} - toggleIndicator={Icon && iconOnly ? null : undefined} - style={isPrimary && !label ? { color: 'var(--pf-v5-global--Color--light-100)' } : {}} - icon={Icon ? : undefined} - data-cy={id} - > - {iconOnly ? undefined : label} - - ) : ( - setDropdownOpen(!dropdownOpen)} - toggleVariant={isPrimary ? 'primary' : undefined} - style={isPrimary && !label ? { color: 'var(--pf-v5-global--Color--light-100)' } : {}} - data-cy={id} - /> - ); - const dropdown = ( - setDropdownOpen(false)} - toggle={Toggle} - isOpen={dropdownOpen} - isPlain={!label || iconOnly} - dropdownItems={actions.map((action, index) => ( - - ))} - position={position} - // ZIndex 400 is needed for PF table stick headers - style={{ zIndex: dropdownOpen ? 400 : undefined, padding: 0 }} - className={ - props.variant === ButtonVariant.control ? 'pf-v5-c-button pf-m-control' : undefined - } - /> - ); - let tooltipContent; + const isKebab = Boolean(!label && !icon); + const CustomIcon = icon; + let tooltipContent; if (isDisabled) { tooltipContent = isDisabled; } else if (tooltip) { @@ -165,9 +118,65 @@ export function PageActionDropdown(props: PageActionDropdownPr tooltipContent = undefined; } + const dropdownMenuLabel: string | JSX.Element | undefined = + iconOnly && CustomIcon ? ( + + + + ) : ( + label + ); + return ( - {dropdown} + setDropdownOpen(false)} + onOpenChange={(isOpen) => setDropdownOpen(isOpen)} + popperProps={{ + appendTo: () => document.body, + preventOverflow: true, + enableFlip: true, + position: position, + }} + toggle={(toggleRef: React.Ref) => ( + setDropdownOpen(!dropdownOpen)} + isExpanded={dropdownOpen} + style={isPrimary && !label ? { color: 'var(--pf-v5-global--Color--light-100)' } : {}} + icon={ + CustomIcon ? ( + + + + ) : undefined + } + > + {dropdownMenuLabel ?? } + + )} + > + + {actions.map((action, index) => ( + + ))} + + ); } @@ -187,8 +196,8 @@ function PageDropdownActionItem(props: { switch (action.type) { case PageActionType.Button: { - let Icon: ComponentClass | FunctionComponent | undefined = action.icon; - if (!Icon && hasIcons) Icon = TransparentIcon; + let CustomIcon: ComponentClass | FunctionComponent | undefined = action.icon; + if (!CustomIcon && hasIcons) CustomIcon = TransparentIcon; let tooltip; if (isDisabled) { @@ -206,11 +215,14 @@ function PageDropdownActionItem(props: { tooltip = t(`Select at least one item from the list`); isButtonDisabled = true; } + return ( : undefined} + id={getID(action)} + data-cy={getID(action)?.split('.').join('-')} + isAriaDisabled={isButtonDisabled} onClick={() => { switch (action.selection) { case PageActionSelection.None: @@ -224,10 +236,22 @@ function PageDropdownActionItem(props: { break; } }} - isAriaDisabled={isButtonDisabled} - id={getID(action)} - data-cy={getID(action)?.split('.').join('-')} + style={{ + color: + action.isDanger && !isDisabled ? getPatternflyColor(PFColorE.Danger) : undefined, + }} > + {CustomIcon ? ( + + + + ) : undefined} {action.label} @@ -236,8 +260,8 @@ function PageDropdownActionItem(props: { } case PageActionType.Link: { - let Icon: ComponentClass | FunctionComponent | undefined = action.icon; - if (!Icon && hasIcons) Icon = TransparentIcon; + let CustomIcon: ComponentClass | FunctionComponent | undefined = action.icon; + if (!CustomIcon && hasIcons) CustomIcon = TransparentIcon; const tooltip = isDisabled ? isDisabled : action.tooltip; let to: string; @@ -258,14 +282,27 @@ function PageDropdownActionItem(props: { return ( : undefined} - component={{action.label}} + data-cy={getID(action)?.split('.').join('-')} style={{ color: action.isDanger && !isDisabled ? getPatternflyColor(PFColorE.Danger) : undefined, }} - /> + > + {CustomIcon ? ( + + + + ) : undefined} + {action.label} + ); } @@ -295,7 +332,7 @@ function PageDropdownActionItem(props: { } case PageActionType.Seperator: - return ; + return ; } } diff --git a/framework/PageInputs/PageMultiSelect.tsx b/framework/PageInputs/PageMultiSelect.tsx index abe9678555..a74e460563 100644 --- a/framework/PageInputs/PageMultiSelect.tsx +++ b/framework/PageInputs/PageMultiSelect.tsx @@ -331,7 +331,7 @@ export function PageMultiSelect< isOpen={open} onOpenChange={setOpen} toggle={Toggle} - popperProps={{ appendTo: () => document.body }} + popperProps={{ appendTo: () => document.body, preventOverflow: true, enableFlip: true }} innerRef={selectListRef} > diff --git a/framework/PageInputs/PageSingleSelect.tsx b/framework/PageInputs/PageSingleSelect.tsx index a052d03c07..74e2d18842 100644 --- a/framework/PageInputs/PageSingleSelect.tsx +++ b/framework/PageInputs/PageSingleSelect.tsx @@ -311,7 +311,7 @@ export function PageSingleSelect< isOpen={open} onOpenChange={setOpen} toggle={props.toggle ?? Toggle} - popperProps={{ appendTo: () => document.body }} + popperProps={{ appendTo: () => document.body, preventOverflow: true, enableFlip: true }} shouldFocusToggleOnSelect innerRef={selectListRef} > diff --git a/framework/PageToolbar/PageToolbar.tsx b/framework/PageToolbar/PageToolbar.tsx index e0119cf857..acda0b9c94 100644 --- a/framework/PageToolbar/PageToolbar.tsx +++ b/framework/PageToolbar/PageToolbar.tsx @@ -182,6 +182,7 @@ export function PageToolbar(props: PageToolbarProps) {