diff --git a/packages/react-core/src/components/Wizard/WizardNavItem.tsx b/packages/react-core/src/components/Wizard/WizardNavItem.tsx index dc891a42bf1..fe33bbe504d 100644 --- a/packages/react-core/src/components/Wizard/WizardNavItem.tsx +++ b/packages/react-core/src/components/Wizard/WizardNavItem.tsx @@ -4,6 +4,7 @@ import styles from '@patternfly/react-styles/css/components/Wizard/wizard'; import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon'; import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon'; +import ExclamationTriangleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon'; import { OUIAProps, useOUIAProps } from '../../helpers'; import { WizardNavItemStatus } from './types'; @@ -38,7 +39,7 @@ export interface WizardNavItemProps /** The id for the navigation item */ id?: string | number; /** Used to determine the icon displayed next to content. Default has no icon. */ - status?: 'default' | 'error' | 'success'; + status?: 'default' | 'error' | 'success' | 'warning'; } export const WizardNavItem = ({ @@ -97,7 +98,8 @@ export const WizardNavItem = ({ isCurrent && styles.modifiers.current, isDisabled && styles.modifiers.disabled, status === WizardNavItemStatus.Error && styles.modifiers.danger, - status === WizardNavItemStatus.Success && styles.modifiers.success + status === WizardNavItemStatus.Success && styles.modifiers.success, + status === WizardNavItemStatus.Warning && styles.modifiers.warning )} aria-disabled={isDisabled ? true : null} aria-current={isCurrent && !children ? 'step' : false} @@ -110,6 +112,7 @@ export const WizardNavItem = ({ {status === WizardNavItemStatus.Error && } {status === WizardNavItemStatus.Success && } + {status === WizardNavItemStatus.Warning && } )} diff --git a/packages/react-core/src/components/Wizard/WizardStep.tsx b/packages/react-core/src/components/Wizard/WizardStep.tsx index bc0ead2a6c3..6cb5d648bda 100644 --- a/packages/react-core/src/components/Wizard/WizardStep.tsx +++ b/packages/react-core/src/components/Wizard/WizardStep.tsx @@ -28,7 +28,7 @@ export interface WizardStepProps { /** Replaces the step's footer. The step's footer takes precedence over the wizard's footer. */ footer?: React.ReactElement | Partial; /** Used to determine icon next to the step's navigation item */ - status?: 'default' | 'error' | 'success'; + status?: 'default' | 'error' | 'success' | 'warning'; /** Flag to determine whether parent steps can expand or not. Defaults to false. */ isExpandable?: boolean; } diff --git a/packages/react-core/src/components/Wizard/__tests__/WizardNavItem.test.tsx b/packages/react-core/src/components/Wizard/__tests__/WizardNavItem.test.tsx index b80db9bb689..bf3ff225b63 100644 --- a/packages/react-core/src/components/Wizard/__tests__/WizardNavItem.test.tsx +++ b/packages/react-core/src/components/Wizard/__tests__/WizardNavItem.test.tsx @@ -63,3 +63,9 @@ test(`Renders screen reader text and success icon when status is success`, () => expect(screen.getByRole('button')).toHaveClass(styles.modifiers.success); expect(screen.getByText(', success')).toBeInTheDocument(); }); + +test(`Renders screen reader text and warning icon when status is warning`, () => { + render(); + expect(screen.getByRole('button')).toHaveClass(styles.modifiers.warning); + expect(screen.getByText(', warning')).toBeInTheDocument(); +}); diff --git a/packages/react-core/src/components/Wizard/__tests__/WizardStep.test.tsx b/packages/react-core/src/components/Wizard/__tests__/WizardStep.test.tsx index ca68cfba932..804f0331a19 100644 --- a/packages/react-core/src/components/Wizard/__tests__/WizardStep.test.tsx +++ b/packages/react-core/src/components/Wizard/__tests__/WizardStep.test.tsx @@ -70,4 +70,6 @@ test('updates "status" in context when the value changes', () => { expect(setStep).toHaveBeenCalledWith({ ...testStepProps, status: 'error', isVisited: true }); render(); expect(setStep).toHaveBeenCalledWith({ ...testStepProps, status: 'success', isVisited: true }); + render(); + expect(setStep).toHaveBeenCalledWith({ ...testStepProps, status: 'warning', isVisited: true }); }); diff --git a/packages/react-core/src/components/Wizard/examples/WizardStepStatus.tsx b/packages/react-core/src/components/Wizard/examples/WizardStepStatus.tsx index 63c99c37073..32cfd9c56f8 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardStepStatus.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardStepStatus.tsx @@ -6,8 +6,10 @@ interface SomeContextProps { setErrorMessage(error: string | undefined): void; successMessage: string | undefined; setSuccessMessage(error: string | undefined): void; + warningMessage: string | undefined; + setWarningMessage(error: string | undefined): void; } -type SomeContextRenderProps = Pick; +type SomeContextRenderProps = Pick; interface SomeContextProviderProps { children: (context: SomeContextRenderProps) => React.ReactElement; } @@ -17,16 +19,20 @@ const SomeContext: React.Context = createContext({} as SomeCon const SomeContextProvider = ({ children }: SomeContextProviderProps) => { const [errorMessage, setErrorMessage] = useState(); const [successMessage, setSuccessMessage] = useState(); + const [warningMessage, setWarningMessage] = useState(); return ( - - {children({ errorMessage, successMessage })} + + {children({ errorMessage, successMessage, warningMessage })} ); }; const StepContentWithAction = () => { - const { errorMessage, setErrorMessage, successMessage, setSuccessMessage } = useContext(SomeContext); + const { errorMessage, setErrorMessage, successMessage, setSuccessMessage, warningMessage, setWarningMessage } = + useContext(SomeContext); return ( <> @@ -35,7 +41,8 @@ const StepContentWithAction = () => { isChecked={!!errorMessage} onChange={(_event, checked) => { setErrorMessage(checked ? 'Some error message' : undefined); - setSuccessMessage(!checked ? 'Some error message' : undefined); + setSuccessMessage(checked ? undefined : successMessage); + setWarningMessage(checked ? undefined : warningMessage); }} id="toggle-error-checkbox" name="Toggle Status" @@ -45,23 +52,37 @@ const StepContentWithAction = () => { isChecked={!!successMessage} onChange={(_event, checked) => { setSuccessMessage(checked ? 'Some success message' : undefined); - setErrorMessage(!checked ? 'Some success message' : undefined); + setErrorMessage(checked ? undefined : errorMessage); + setWarningMessage(checked ? undefined : warningMessage); }} id="toggle-success-checkbox" name="Toggle Status" /> + { + setWarningMessage(checked ? 'Some warning message' : undefined); + setErrorMessage(checked ? undefined : errorMessage); + setSuccessMessage(checked ? undefined : successMessage); + }} + id="toggle-warning-checkbox" + name="Toggle Status" + /> ); }; export const WizardStepStatus: React.FunctionComponent = () => ( - {({ errorMessage, successMessage }) => { + {({ errorMessage, successMessage, warningMessage }) => { let status = 'default'; if (errorMessage) { status = 'error'; } else if (successMessage) { status = 'success'; + } else if (warningMessage) { + status = 'warning'; } return ( diff --git a/packages/react-core/src/components/Wizard/types.tsx b/packages/react-core/src/components/Wizard/types.tsx index 77ba6c57512..4d368932e9d 100644 --- a/packages/react-core/src/components/Wizard/types.tsx +++ b/packages/react-core/src/components/Wizard/types.tsx @@ -23,13 +23,14 @@ export interface WizardBasicStep { /** Replaces the step's footer. The step's footer takes precedence over the wizard's footer. */ footer?: React.ReactElement | Partial; /** Used to determine icon next to the step's navItem */ - status?: 'default' | 'error' | 'success'; + status?: 'default' | 'error' | 'success' | 'warning'; } export enum WizardNavItemStatus { Default = 'default', Error = 'error', - Success = 'success' + Success = 'success', + Warning = 'warning' } /** 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. */