From 6326b296e83ed594cbdfe5395aabfb14deca9171 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Wed, 4 Oct 2023 10:50:05 +0200 Subject: [PATCH 1/6] feat: ability to add props to WizardFooter buttons --- .../src/components/Wizard/Wizard.tsx | 5 ++++ .../src/components/Wizard/WizardContext.tsx | 13 ++++++++-- .../src/components/Wizard/WizardFooter.tsx | 24 +++++++++++++++---- .../src/components/Wizard/types.tsx | 13 ++++++++++ 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/packages/react-core/src/components/Wizard/Wizard.tsx b/packages/react-core/src/components/Wizard/Wizard.tsx index 2aabacadaed..779421d327f 100644 --- a/packages/react-core/src/components/Wizard/Wizard.tsx +++ b/packages/react-core/src/components/Wizard/Wizard.tsx @@ -8,6 +8,7 @@ import { WizardStepType, isCustomWizardNav, WizardFooterType, + WizardFooterButtonsProps, WizardNavType, WizardStepChangeScope } from './types'; @@ -53,6 +54,8 @@ export interface WizardProps extends React.HTMLProps { onSave?: (event: React.MouseEvent) => void | Promise; /** Callback function to close the wizard */ onClose?: (event: React.MouseEvent) => void; + /** Interface for adding properties to footer buttons. */ + footerButtonsProps?: WizardFooterButtonsProps; } export const Wizard = ({ @@ -69,6 +72,7 @@ export const Wizard = ({ onStepChange, onSave, onClose, + footerButtonsProps, ...wrapperProps }: WizardProps) => { const [activeStepIndex, setActiveStepIndex] = React.useState(startIndex); @@ -166,6 +170,7 @@ export const Wizard = ({ goToStepById={goToStepById} goToStepByName={goToStepByName} goToStepByIndex={goToStepByIndex} + footerButtonsProps={footerButtonsProps} >
= ({ @@ -59,7 +66,8 @@ export const WizardContextProvider: React.FunctionComponent { const [currentSteps, setCurrentSteps] = React.useState(initialSteps); const [currentFooter, setCurrentFooter] = React.useState(); @@ -101,6 +109,7 @@ export const WizardContextProvider: React.FunctionComponent ); diff --git a/packages/react-core/src/components/Wizard/WizardFooter.tsx b/packages/react-core/src/components/Wizard/WizardFooter.tsx index a44679e2a8e..6dee556b480 100644 --- a/packages/react-core/src/components/Wizard/WizardFooter.tsx +++ b/packages/react-core/src/components/Wizard/WizardFooter.tsx @@ -4,7 +4,7 @@ import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Wizard/wizard'; import { Button, ButtonVariant } from '../Button'; -import { isCustomWizardFooter, WizardStepType } from './types'; +import { isCustomWizardFooter, WizardFooterButtonsProps, WizardStepType } from './types'; /** * Hosts the standard structure of a footer with ties to the active step so that text for buttons can vary from step to step. @@ -33,6 +33,8 @@ export interface WizardFooterProps { isBackHidden?: boolean; /** Flag to hide the cancel button */ isCancelHidden?: boolean; + /** Interface for adding properties to footer buttons. */ + footerButtonsProps?: WizardFooterButtonsProps; } /** @@ -62,22 +64,34 @@ const InternalWizardFooter = ({ isCancelHidden, nextButtonText = 'Next', backButtonText = 'Back', - cancelButtonText = 'Cancel' + cancelButtonText = 'Cancel', + footerButtonsProps }: Omit) => ( {!isBackHidden && ( - )} - {!isCancelHidden && (
-
diff --git a/packages/react-core/src/components/Wizard/types.tsx b/packages/react-core/src/components/Wizard/types.tsx index 7be809dbf8f..e545a96c08f 100644 --- a/packages/react-core/src/components/Wizard/types.tsx +++ b/packages/react-core/src/components/Wizard/types.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { WizardNavProps, WizardNavItemProps, WizardFooterProps } from '.'; +import { ButtonProps } from '../Button'; /** Type used to define 'basic' steps, or in other words, steps that are neither parents or children of parents. */ export interface WizardBasicStep { @@ -57,6 +58,18 @@ export type WizardFooterType = Partial | CustomWizardFooterFu export type WizardNavType = Partial | CustomWizardNavFunction | React.ReactElement; export type WizardNavItemType = Partial | CustomWizardNavItemFunction | React.ReactElement; +type FooterButtonProps = Omit; + +/** Interface for adding properties to footer buttons. */ +export interface WizardFooterButtonsProps { + /** Additional props for the Next button. */ + nextButtonProps?: Omit; + /** Additional props for the Back button. */ + backButtonProps?: Omit; + /** Additional props for the Cancel button. */ + cancelButtonProps?: FooterButtonProps; +} + /** Callback for the Wizard's 'nav' property. Returns element which replaces the Wizard's default navigation. */ export type CustomWizardNavFunction = ( isExpanded: boolean, From c5ee1996682f1c8613149f68b4574ce6b4e3784d Mon Sep 17 00:00:00 2001 From: adamviktora Date: Wed, 4 Oct 2023 12:28:59 +0200 Subject: [PATCH 2/6] fix(WizardFooter): null check --- packages/react-core/src/components/Wizard/WizardFooter.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-core/src/components/Wizard/WizardFooter.tsx b/packages/react-core/src/components/Wizard/WizardFooter.tsx index 6dee556b480..da74da95c6c 100644 --- a/packages/react-core/src/components/Wizard/WizardFooter.tsx +++ b/packages/react-core/src/components/Wizard/WizardFooter.tsx @@ -73,7 +73,7 @@ const InternalWizardFooter = ({ variant={ButtonVariant.secondary} onClick={onBack} isDisabled={isBackDisabled} - {...footerButtonsProps.backButtonProps} + {...footerButtonsProps?.backButtonProps} > {backButtonText} @@ -84,14 +84,14 @@ const InternalWizardFooter = ({ type="submit" onClick={onNext} isDisabled={isNextDisabled} - {...footerButtonsProps.nextButtonProps} + {...footerButtonsProps?.nextButtonProps} > {nextButtonText} {!isCancelHidden && (
-
From 0427f12a9215cd1662b258fb8f1c636d106e5a26 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Wed, 4 Oct 2023 13:30:58 +0200 Subject: [PATCH 3/6] fix(Wizard): simpler design of adding footer buttons props --- .../src/components/Wizard/Wizard.tsx | 5 ---- .../src/components/Wizard/WizardContext.tsx | 13 ++------- .../src/components/Wizard/WizardFooter.tsx | 29 ++++++++++--------- .../src/components/Wizard/types.tsx | 13 --------- 4 files changed, 18 insertions(+), 42 deletions(-) diff --git a/packages/react-core/src/components/Wizard/Wizard.tsx b/packages/react-core/src/components/Wizard/Wizard.tsx index 779421d327f..2aabacadaed 100644 --- a/packages/react-core/src/components/Wizard/Wizard.tsx +++ b/packages/react-core/src/components/Wizard/Wizard.tsx @@ -8,7 +8,6 @@ import { WizardStepType, isCustomWizardNav, WizardFooterType, - WizardFooterButtonsProps, WizardNavType, WizardStepChangeScope } from './types'; @@ -54,8 +53,6 @@ export interface WizardProps extends React.HTMLProps { onSave?: (event: React.MouseEvent) => void | Promise; /** Callback function to close the wizard */ onClose?: (event: React.MouseEvent) => void; - /** Interface for adding properties to footer buttons. */ - footerButtonsProps?: WizardFooterButtonsProps; } export const Wizard = ({ @@ -72,7 +69,6 @@ export const Wizard = ({ onStepChange, onSave, onClose, - footerButtonsProps, ...wrapperProps }: WizardProps) => { const [activeStepIndex, setActiveStepIndex] = React.useState(startIndex); @@ -170,7 +166,6 @@ export const Wizard = ({ goToStepById={goToStepById} goToStepByName={goToStepByName} goToStepByIndex={goToStepByIndex} - footerButtonsProps={footerButtonsProps} >
= ({ @@ -66,8 +59,7 @@ export const WizardContextProvider: React.FunctionComponent { const [currentSteps, setCurrentSteps] = React.useState(initialSteps); const [currentFooter, setCurrentFooter] = React.useState(); @@ -109,7 +101,6 @@ export const WizardContextProvider: React.FunctionComponent ); diff --git a/packages/react-core/src/components/Wizard/WizardFooter.tsx b/packages/react-core/src/components/Wizard/WizardFooter.tsx index da74da95c6c..b5046728d24 100644 --- a/packages/react-core/src/components/Wizard/WizardFooter.tsx +++ b/packages/react-core/src/components/Wizard/WizardFooter.tsx @@ -3,13 +3,15 @@ import React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Wizard/wizard'; -import { Button, ButtonVariant } from '../Button'; -import { isCustomWizardFooter, WizardFooterButtonsProps, WizardStepType } from './types'; +import { Button, ButtonProps, ButtonVariant } from '../Button'; +import { isCustomWizardFooter, WizardStepType } from './types'; /** * Hosts the standard structure of a footer with ties to the active step so that text for buttons can vary from step to step. */ +type FooterButtonProps = Omit; + export interface WizardFooterProps { /** The active step */ activeStep: WizardStepType; @@ -33,8 +35,12 @@ export interface WizardFooterProps { isBackHidden?: boolean; /** Flag to hide the cancel button */ isCancelHidden?: boolean; - /** Interface for adding properties to footer buttons. */ - footerButtonsProps?: WizardFooterButtonsProps; + /** Additional props for the Next button. */ + nextButtonProps?: Omit; + /** Additional props for the Back button. */ + backButtonProps?: Omit; + /** Additional props for the Cancel button. */ + cancelButtonProps?: FooterButtonProps; } /** @@ -65,16 +71,13 @@ const InternalWizardFooter = ({ nextButtonText = 'Next', backButtonText = 'Back', cancelButtonText = 'Cancel', - footerButtonsProps + nextButtonProps, + backButtonProps, + cancelButtonProps }: Omit) => ( {!isBackHidden && ( - )} @@ -84,14 +87,14 @@ const InternalWizardFooter = ({ type="submit" onClick={onNext} isDisabled={isNextDisabled} - {...footerButtonsProps?.nextButtonProps} + {...nextButtonProps} > {nextButtonText} {!isCancelHidden && (
-
diff --git a/packages/react-core/src/components/Wizard/types.tsx b/packages/react-core/src/components/Wizard/types.tsx index e545a96c08f..7be809dbf8f 100644 --- a/packages/react-core/src/components/Wizard/types.tsx +++ b/packages/react-core/src/components/Wizard/types.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { WizardNavProps, WizardNavItemProps, WizardFooterProps } from '.'; -import { ButtonProps } from '../Button'; /** Type used to define 'basic' steps, or in other words, steps that are neither parents or children of parents. */ export interface WizardBasicStep { @@ -58,18 +57,6 @@ export type WizardFooterType = Partial | CustomWizardFooterFu export type WizardNavType = Partial | CustomWizardNavFunction | React.ReactElement; export type WizardNavItemType = Partial | CustomWizardNavItemFunction | React.ReactElement; -type FooterButtonProps = Omit; - -/** Interface for adding properties to footer buttons. */ -export interface WizardFooterButtonsProps { - /** Additional props for the Next button. */ - nextButtonProps?: Omit; - /** Additional props for the Back button. */ - backButtonProps?: Omit; - /** Additional props for the Cancel button. */ - cancelButtonProps?: FooterButtonProps; -} - /** Callback for the Wizard's 'nav' property. Returns element which replaces the Wizard's default navigation. */ export type CustomWizardNavFunction = ( isExpanded: boolean, From e971c99cdf9e8644269b95bb3f5e47ea9ef9aeab Mon Sep 17 00:00:00 2001 From: adamviktora Date: Wed, 4 Oct 2023 13:32:14 +0200 Subject: [PATCH 4/6] test(Wizard): can add props to footer buttons --- .../Wizard/__tests__/Wizard.test.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/react-core/src/components/Wizard/__tests__/Wizard.test.tsx b/packages/react-core/src/components/Wizard/__tests__/Wizard.test.tsx index ed52e8ef8f7..f374905a11c 100644 --- a/packages/react-core/src/components/Wizard/__tests__/Wizard.test.tsx +++ b/packages/react-core/src/components/Wizard/__tests__/Wizard.test.tsx @@ -58,6 +58,27 @@ test('renders default footer with custom props', () => { expect(screen.getByRole('button', { name: 'Leave now!' })).toBeVisible(); }); +test('can add props to default footer buttons', () => { + render( + + + + ); + + const nextButton = screen.getByRole('button', { name: 'Next' }); + + expect(nextButton).toHaveProperty('id', 'next-button'); + expect(nextButton).toHaveClass('custom-class'); + expect(screen.getByRole('button', { name: 'Back' })).toHaveProperty('id', 'back-button'); + expect(screen.getByRole('button', { name: 'Cancel' })).toHaveProperty('id', 'cancel-button'); +}); + test('renders custom footer', () => { render( Some footer}> From 541693ee53f09c3c5ec677f4230317030685400d Mon Sep 17 00:00:00 2001 From: adamviktora Date: Mon, 23 Oct 2023 14:43:28 +0200 Subject: [PATCH 5/6] docs(WizardFooter): move comment so docs have correct description --- packages/react-core/src/components/Wizard/WizardFooter.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-core/src/components/Wizard/WizardFooter.tsx b/packages/react-core/src/components/Wizard/WizardFooter.tsx index b5046728d24..bce12e1b329 100644 --- a/packages/react-core/src/components/Wizard/WizardFooter.tsx +++ b/packages/react-core/src/components/Wizard/WizardFooter.tsx @@ -6,12 +6,12 @@ import styles from '@patternfly/react-styles/css/components/Wizard/wizard'; import { Button, ButtonProps, ButtonVariant } from '../Button'; import { isCustomWizardFooter, WizardStepType } from './types'; +type FooterButtonProps = Omit; + /** * Hosts the standard structure of a footer with ties to the active step so that text for buttons can vary from step to step. */ -type FooterButtonProps = Omit; - export interface WizardFooterProps { /** The active step */ activeStep: WizardStepType; From b13ca84ac921ef107d7aa6b0980bb979198fe958 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Mon, 30 Oct 2023 12:43:58 +0100 Subject: [PATCH 6/6] refactor(WizardFooter): move FooterButtonProps to types file --- .../src/components/Wizard/WizardFooter.tsx | 12 +++++------- packages/react-core/src/components/Wizard/types.tsx | 4 ++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/react-core/src/components/Wizard/WizardFooter.tsx b/packages/react-core/src/components/Wizard/WizardFooter.tsx index bce12e1b329..bd4596dc477 100644 --- a/packages/react-core/src/components/Wizard/WizardFooter.tsx +++ b/packages/react-core/src/components/Wizard/WizardFooter.tsx @@ -3,10 +3,8 @@ import React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Wizard/wizard'; -import { Button, ButtonProps, ButtonVariant } from '../Button'; -import { isCustomWizardFooter, WizardStepType } from './types'; - -type FooterButtonProps = Omit; +import { Button, ButtonVariant } from '../Button'; +import { isCustomWizardFooter, WizardFooterButtonProps, WizardStepType } from './types'; /** * Hosts the standard structure of a footer with ties to the active step so that text for buttons can vary from step to step. @@ -36,11 +34,11 @@ export interface WizardFooterProps { /** Flag to hide the cancel button */ isCancelHidden?: boolean; /** Additional props for the Next button. */ - nextButtonProps?: Omit; + nextButtonProps?: Omit; /** Additional props for the Back button. */ - backButtonProps?: Omit; + backButtonProps?: Omit; /** Additional props for the Cancel button. */ - cancelButtonProps?: FooterButtonProps; + cancelButtonProps?: WizardFooterButtonProps; } /** diff --git a/packages/react-core/src/components/Wizard/types.tsx b/packages/react-core/src/components/Wizard/types.tsx index 7be809dbf8f..0fde2151e5d 100644 --- a/packages/react-core/src/components/Wizard/types.tsx +++ b/packages/react-core/src/components/Wizard/types.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { WizardNavProps, WizardNavItemProps, WizardFooterProps } from '.'; +import { ButtonProps } from '../Button'; /** Type used to define 'basic' steps, or in other words, steps that are neither parents or children of parents. */ export interface WizardBasicStep { @@ -30,6 +31,9 @@ export enum WizardNavItemStatus { Error = 'error' } +/** Type for customizing a button (next, back or cancel) in a Wizard footer. It omits some props which either have a default value or are passed directly via WizardFooterProps. */ +export type WizardFooterButtonProps = Omit; + /** Type used to define parent steps. */ export interface WizardParentStep extends WizardBasicStep { /** Nested step IDs */