diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index 7cc0879c2e2..7806a59e90d 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { css } from '@patternfly/react-styles'; import { Menu, MenuContent, MenuProps } from '../../../components/Menu'; -import { Popper } from '../../../helpers/Popper/Popper'; +import { Popper, PopperProps } from '../../../helpers/Popper/Popper'; import { useOUIAProps, OUIAProps } from '../../../helpers'; export interface DropdownProps extends MenuProps, OUIAProps { @@ -32,6 +32,8 @@ export interface DropdownProps extends MenuProps, OUIAProps { ouiaSafe?: boolean; /** z-index of the dropdown menu */ zIndex?: number; + /** Additional properties to pass to the Popper */ + popperProps?: PopperProps; } const DropdownBase: React.FunctionComponent = ({ @@ -48,6 +50,7 @@ const DropdownBase: React.FunctionComponent = ({ ouiaId, ouiaSafe = true, zIndex = 9999, + popperProps, ...props }: DropdownProps) => { const localMenuRef = React.useRef(); @@ -100,7 +103,7 @@ const DropdownBase: React.FunctionComponent = ({ onSelect(event, itemId)} + onSelect={(event, itemId) => onSelect && onSelect(event, itemId)} isPlain={isPlain} isScrollable={isScrollable} {...(minWidth && { @@ -121,6 +124,7 @@ const DropdownBase: React.FunctionComponent = ({ appendTo={containerRef.current || undefined} isVisible={isOpen} zIndex={zIndex} + {...popperProps} /> ); diff --git a/packages/react-core/src/next/components/Select/Select.tsx b/packages/react-core/src/next/components/Select/Select.tsx index 4f6b09e9185..a2886771273 100644 --- a/packages/react-core/src/next/components/Select/Select.tsx +++ b/packages/react-core/src/next/components/Select/Select.tsx @@ -97,7 +97,7 @@ const SelectBase: React.FunctionComponent = ({ role={role} className={css(className)} ref={menuRef} - onSelect={(event, itemId) => onSelect(event, itemId)} + onSelect={(event, itemId) => onSelect && onSelect(event, itemId)} isPlain={isPlain} selected={selected} {...(minWidth && { diff --git a/packages/react-core/src/next/components/Wizard/WizardContext.tsx b/packages/react-core/src/next/components/Wizard/WizardContext.tsx index 9dc3e80e9f6..3c39a93df3d 100644 --- a/packages/react-core/src/next/components/Wizard/WizardContext.tsx +++ b/packages/react-core/src/next/components/Wizard/WizardContext.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { isCustomWizardFooter, isWizardSubStep, WizardStepType, WizardFooterType } from './types'; -import { getActiveStep } from './utils'; import { WizardFooter, WizardFooterProps } from './WizardFooter'; export interface WizardContextProps { @@ -74,7 +73,8 @@ export const WizardContextProvider: React.FunctionComponent getActiveStep(steps, activeStepIndex), [activeStepIndex, steps]); + + const activeStep = React.useMemo(() => steps.find(step => step.index === activeStepIndex), [activeStepIndex, steps]); const close = React.useCallback(() => onClose?.(null), [onClose]); const goToNextStep = React.useCallback(() => onNext(null, steps), [onNext, steps]); diff --git a/packages/react-core/src/next/components/Wizard/WizardToggle.tsx b/packages/react-core/src/next/components/Wizard/WizardToggle.tsx index 3690d773636..d769a00119e 100644 --- a/packages/react-core/src/next/components/Wizard/WizardToggle.tsx +++ b/packages/react-core/src/next/components/Wizard/WizardToggle.tsx @@ -6,8 +6,10 @@ import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-i import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon'; import { KeyTypes } from '../../../helpers/constants'; -import { WizardNavProps, WizardBody, WizardStep, WizardStepProps } from '../Wizard'; import { WizardStepType, isWizardSubStep } from './types'; +import { WizardNavProps } from './WizardNav'; +import { WizardStep, WizardStepProps } from './WizardStep'; +import { WizardBody } from './WizardBody'; /** * Used to toggle between step content, including the body and footer. This is also where the navigation and its expandability is controlled. diff --git a/packages/react-core/src/next/components/Wizard/utils.ts b/packages/react-core/src/next/components/Wizard/utils.ts index accd1db2fc2..f83a42a0381 100644 --- a/packages/react-core/src/next/components/Wizard/utils.ts +++ b/packages/react-core/src/next/components/Wizard/utils.ts @@ -57,6 +57,3 @@ export const normalizeStepProps = ({ steps: _steps, ...controlStep }: WizardStepProps): Omit => controlStep; - -export const getActiveStep = (steps: WizardStepType[], activeStepIndex: number) => - steps.find(step => step.index === activeStepIndex); diff --git a/packages/react-integration/cypress/integration/tablesimpleactions.spec.ts b/packages/react-integration/cypress/integration/tablesimpleactions.spec.ts index 0a14531336b..98753c2cfcc 100644 --- a/packages/react-integration/cypress/integration/tablesimpleactions.spec.ts +++ b/packages/react-integration/cypress/integration/tablesimpleactions.spec.ts @@ -20,14 +20,14 @@ describe('Table Simple Actions Test', () => { }); it('Verify dropdown toggle', () => { - cy.get('td .pf-c-dropdown__toggle') + cy.get('td .pf-c-menu-toggle') .first() .should('exist'); - cy.get('td .pf-c-dropdown__toggle') + cy.get('td .pf-c-menu-toggle') .first() .click(); - cy.get('.pf-c-dropdown__menu').should('exist'); - cy.get('.pf-c-dropdown__menu-item') + cy.get('.pf-c-menu').should('exist'); + cy.get('.pf-c-menu__item') .first() .click(); }); diff --git a/packages/react-table/src/components/Table/ActionsColumn.tsx b/packages/react-table/src/components/Table/ActionsColumn.tsx index be497547f81..2f382eaf543 100644 --- a/packages/react-table/src/components/Table/ActionsColumn.tsx +++ b/packages/react-table/src/components/Table/ActionsColumn.tsx @@ -1,71 +1,59 @@ import * as React from 'react'; -import { Dropdown } from '@patternfly/react-core/dist/esm/components/Dropdown'; -import { KebabToggle } from '@patternfly/react-core/dist/esm/components/Dropdown/KebabToggle'; -import { DropdownItem } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownItem'; -import { DropdownSeparator } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownSeparator'; -import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; - -import { - DropdownDirection, - DropdownPosition -} from '@patternfly/react-core/dist/esm/components/Dropdown/dropdownConstants'; - +import { Dropdown, DropdownItem, DropdownList } from '@patternfly/react-core/dist/esm/next/components'; +import { Button } from '@patternfly/react-core/dist/esm/components/Button'; +import { Divider } from '@patternfly/react-core/dist/esm/components/Divider'; +import { MenuToggle } from '@patternfly/react-core/dist/esm/components/MenuToggle'; import { IAction, IExtraData, IRowData } from './TableTypes'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; export interface CustomActionsToggleProps { - onToggle: (isOpen: boolean) => void; + onToggle: (evt: React.MouseEvent) => void; isOpen: boolean; isDisabled: boolean; + toggleRef: React.Ref; } - -export interface ActionsColumnProps { - children?: React.ReactNode; +export interface ActionsColumnProps extends Omit, 'label'> { + /** Actions to be rendered within or without the action dropdown */ items: IAction[]; + /** Indicates whether the actions dropdown is disabled */ isDisabled?: boolean; - menuAppendTo?: HTMLElement | (() => HTMLElement) | 'inline' | 'parent'; - dropdownPosition?: DropdownPosition; - dropdownDirection?: DropdownDirection; + /** Data of the row the action dropdown is located */ rowData?: IRowData; + /** Extra data of a row */ extraData?: IExtraData; + /** Custom actions toggle for the actions dropdown */ actionsToggle?: (props: CustomActionsToggleProps) => React.ReactNode; + /** Additional properties for the actions dropdown popper */ + popperProps?: any; + /** @hide Forwarded ref */ + innerRef?: React.Ref; } -export interface ActionsColumnState { - isOpen: boolean; -} - -export class ActionsColumn extends React.Component { - static displayName = 'ActionsColumn'; - private toggleRef = React.createRef(); - static defaultProps = { - children: null as React.ReactNode, - items: [] as IAction[], - dropdownPosition: DropdownPosition.right, - dropdownDirection: DropdownDirection.down, - menuAppendTo: 'inline', - rowData: {} as IRowData, - extraData: {} as IExtraData - }; - constructor(props: ActionsColumnProps) { - super(props); - this.state = { - isOpen: false - }; - } +const ActionsColumnBase: React.FunctionComponent = ({ + items, + isDisabled, + rowData, + extraData, + actionsToggle, + popperProps = { + position: 'right', + direction: 'down', + popperMatchesTriggerWidth: false + }, + ...props +}: ActionsColumnProps) => { + const [isOpen, setIsOpen] = React.useState(false); - onToggle = (isOpen: boolean): void => { - this.setState({ - isOpen - }); + const onToggle = () => { + setIsOpen(!isOpen); }; - onClick = ( + const onActionClick = ( event: React.MouseEvent | React.KeyboardEvent | MouseEvent, onClick: | ((event: React.MouseEvent, rowIndex: number | undefined, rowData: IRowData, extraData: IExtraData) => void) | undefined ): void => { - const { rowData, extraData } = this.props; // Only prevent default if onClick is provided. This allows href support. if (onClick) { event.preventDefault(); @@ -74,62 +62,61 @@ export class ActionsColumn extends React.Component - ); + return ( + + {items + .filter(item => item.isOutsideDropdown) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .map(({ title, itemKey, onClick, isOutsideDropdown, ...props }, key) => + typeof title === 'string' ? ( + + ) : ( + React.cloneElement(title as React.ReactElement, { onClick, isDisabled, ...props }) + ) + )} - return ( - - {items - .filter(item => item.isOutsideDropdown) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .map(({ title, itemKey, onClick, isOutsideDropdown, ...props }, key) => - typeof title === 'string' ? ( - - ) : ( - React.cloneElement(title as React.ReactElement, { onClick, isDisabled, ...props }) - ) - )} - setIsOpen(isOpen)} + toggle={toggleRef => + actionsToggle ? ( + actionsToggle({ onToggle, isOpen, isDisabled, toggleRef }) + ) : ( + + + + ) + } + {...(rowData && rowData.actionProps)} + {...props} + popperProps={popperProps} + > + + {items .filter(item => !item.isOutsideDropdown) .map(({ title, itemKey, onClick, isSeparator, ...props }, key) => isSeparator ? ( - + ) : ( { - this.onClick(event, onClick); - this.onToggle(!isOpen); + onActionClick(event, onClick); + onToggle(); }} {...props} key={itemKey || key} @@ -139,11 +126,13 @@ export class ActionsColumn extends React.Component ) )} - isPlain - {...(rowData && rowData.actionProps)} - /> - {children} - - ); - } -} + + + + ); +}; + +export const ActionsColumn = React.forwardRef((props: ActionsColumnProps, ref: React.Ref) => ( + +)); +ActionsColumn.displayName = 'ActionsColumn'; diff --git a/packages/react-table/src/components/Table/TableTypes.tsx b/packages/react-table/src/components/Table/TableTypes.tsx index 60c347663b0..29d8f9a06ea 100644 --- a/packages/react-table/src/components/Table/TableTypes.tsx +++ b/packages/react-table/src/components/Table/TableTypes.tsx @@ -1,4 +1,4 @@ -import { DropdownItemProps } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownItem'; +import { DropdownItemProps } from '@patternfly/react-core/next'; import { formatterValueType, ColumnType, RowType, RowKeyType, HeaderType } from './base'; import { SortByDirection } from './SortColumn'; import { @@ -108,6 +108,7 @@ export interface IColumn { dropdownDirection?: DropdownDirection; menuAppendTo?: HTMLElement | (() => HTMLElement) | 'inline' | 'parent'; actionsToggle?: (props: CustomActionsToggleProps) => React.ReactNode; + actionsPopperProps?: any; allRowsSelected?: boolean; allRowsExpanded?: boolean; isHeaderSelectDisabled?: boolean; diff --git a/packages/react-table/src/components/Table/__tests__/__snapshots__/Table.test.tsx.snap b/packages/react-table/src/components/Table/__tests__/__snapshots__/Table.test.tsx.snap index c4c2549432c..016cd74ae0e 100644 --- a/packages/react-table/src/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +++ b/packages/react-table/src/components/Table/__tests__/__snapshots__/Table.test.tsx.snap @@ -148,33 +148,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -225,33 +226,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -302,33 +304,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -379,33 +382,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -456,33 +460,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -533,33 +538,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -610,33 +616,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -687,33 +694,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -764,33 +772,34 @@ exports[`Table Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5374,33 +5383,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5451,33 +5461,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5528,33 +5539,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5605,33 +5617,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5682,33 +5695,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5759,33 +5773,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5836,33 +5851,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5913,33 +5929,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -5990,33 +6007,34 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
@@ -6067,34 +6085,35 @@ exports[`Table Simple Actions table 1`] = ` style="padding-right: 0px;" >
- + + +
diff --git a/packages/react-table/src/components/Table/examples/LegacyTableActions.tsx b/packages/react-table/src/components/Table/examples/LegacyTableActions.tsx index 9dcf397ac40..10b19664cb3 100644 --- a/packages/react-table/src/components/Table/examples/LegacyTableActions.tsx +++ b/packages/react-table/src/components/Table/examples/LegacyTableActions.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { Button, Checkbox, - DropdownToggle, + MenuToggle, ToggleGroup, ToggleGroupItem, ToggleGroupItemProps, @@ -62,9 +62,9 @@ export const LegacyTableActions: React.FunctionComponent = () => { const [useCustomToggle, setUseCustomToggle] = React.useState(false); const customActionsToggle = (props: CustomActionsToggleProps) => ( - + Actions - + ); const columns: TableProps['cells'] = [ @@ -77,7 +77,7 @@ export const LegacyTableActions: React.FunctionComponent = () => { ]; const rows: TableProps['rows'] = repositories.map(repo => { - let singleActionButton = null; + let singleActionButton: React.ReactNode = null; if (repo.singleAction !== '') { singleActionButton = ( diff --git a/packages/react-table/src/components/Table/utils/decorators/cellActions.tsx b/packages/react-table/src/components/Table/utils/decorators/cellActions.tsx index 66c2caf9de3..c91a3097c7c 100644 --- a/packages/react-table/src/components/Table/utils/decorators/cellActions.tsx +++ b/packages/react-table/src/components/Table/utils/decorators/cellActions.tsx @@ -33,7 +33,7 @@ export const cellActions = ( rowIndex, columnIndex, column: { - extraParams: { dropdownPosition, dropdownDirection, actionsToggle, menuAppendTo } + extraParams: { actionsToggle, actionsPopperProps } }, property }: IExtra @@ -58,13 +58,11 @@ export const cellActions = ( children: ( {label as React.ReactNode} diff --git a/packages/react-table/src/components/TableComposable/examples/ComposableTableActions.tsx b/packages/react-table/src/components/TableComposable/examples/ComposableTableActions.tsx index 288ff652b55..a90cd93bb9f 100644 --- a/packages/react-table/src/components/TableComposable/examples/ComposableTableActions.tsx +++ b/packages/react-table/src/components/TableComposable/examples/ComposableTableActions.tsx @@ -1,6 +1,6 @@ /* eslint-disable no-console */ import React from 'react'; -import { Button, DropdownToggle, ToggleGroup, ToggleGroupItem, ToggleGroupItemProps } from '@patternfly/react-core'; +import { Button, MenuToggle, ToggleGroup, ToggleGroupItem, ToggleGroupItemProps } from '@patternfly/react-core'; import { TableComposable, TableText, @@ -52,9 +52,9 @@ export const ComposableTableActions: React.FunctionComponent = () => { }; const customActionsToggle = (props: CustomActionsToggleProps) => ( - + Actions - + ); const defaultActions = (repo: Repository): IAction[] => [ @@ -130,7 +130,7 @@ export const ComposableTableActions: React.FunctionComponent = () => { if (repo.name === '5') { rowActions = lastRowActions(repo); } - let singleActionButton = null; + let singleActionButton: React.ReactNode = null; if (repo.singleAction !== '') { singleActionButton = (