From 3b842e2ff19f37dddfb2e421355473419cdb4ec3 Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Tue, 25 Oct 2022 16:09:47 -0400 Subject: [PATCH 01/15] chore(Wizard): Convert examples to typescript --- .../src/components/Wizard/examples/Wizard.md | 983 +----------------- .../examples/WizardAnchorsForNavItems.tsx | 42 + .../Wizard/examples/WizardBasic.tsx | 14 + .../examples/WizardBasicWithDisabledSteps.tsx | 14 + .../WizardEnabledOnFormValidation.tsx | 106 ++ .../Wizard/examples/WizardExpandableSteps.tsx | 34 + .../Wizard/examples/WizardFinished.tsx | 29 + .../Wizard/examples/WizardGetCurrentStep.tsx | 36 + .../Wizard/examples/WizardInModal.tsx | 32 + .../WizardIncrementallyEnabledSteps.tsx | 65 ++ .../examples/WizardProgressiveSteps.tsx | 226 ++++ .../examples/WizardValidateOnButtonPress.tsx | 89 ++ .../Wizard/examples/WizardWithDrawer.tsx | 137 +++ 13 files changed, 836 insertions(+), 971 deletions(-) create mode 100644 packages/react-core/src/components/Wizard/examples/WizardAnchorsForNavItems.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardBasic.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardBasicWithDisabledSteps.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardExpandableSteps.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardFinished.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardGetCurrentStep.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardInModal.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardIncrementallyEnabledSteps.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx create mode 100644 packages/react-core/src/components/Wizard/examples/WizardWithDrawer.tsx diff --git a/packages/react-core/src/components/Wizard/examples/Wizard.md b/packages/react-core/src/components/Wizard/examples/Wizard.md index 75ee563df68..779301e6e70 100644 --- a/packages/react-core/src/components/Wizard/examples/Wizard.md +++ b/packages/react-core/src/components/Wizard/examples/Wizard.md @@ -20,374 +20,37 @@ If you seek a wizard solution that allows for more composition, see the [React n ### Basic -```js -import React from 'react'; -import { Button, Wizard } from '@patternfly/react-core'; - -class SimpleWizard extends React.Component { - constructor(props) { - super(props); - } - - render() { - const steps = [ - { name: 'First step', component:

Step 1 content

}, - { name: 'Second step', component:

Step 2 content

}, - { name: 'Third step', component:

Step 3 content

}, - { name: 'Fourth step', component:

Step 4 content

}, - { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } - ]; - const title = 'Basic wizard'; - return ; - } -} +```ts file="./WizardBasic.tsx" ``` ### Basic with disabled steps -```js -import React from 'react'; -import { Button, Wizard } from '@patternfly/react-core'; - -class SimpleWizard extends React.Component { - constructor(props) { - super(props); - } - - render() { - const steps = [ - { name: 'First step', component:

Step 1 content

}, - { name: 'Second step', component:

Step 2 content

, isDisabled: true }, - { name: 'Third step', component:

Step 3 content

}, - { name: 'Fourth step', component:

Step 4 content

, isDisabled: true }, - { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } - ]; - const title = 'Basic wizard'; - return ; - } -} +```ts file="./WizardBasicWithDisabledSteps.tsx" ``` ### Anchors for nav items -```js -import React from 'react'; -import { Button, Wizard } from '@patternfly/react-core'; -import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; -import SlackHashIcon from '@patternfly/react-icons/dist/esm/icons/slack-hash-icon'; - -class WizardWithNavAnchors extends React.Component { - constructor(props) { - super(props); - } - - render() { - const steps = [ - { - name: ( -
- PF3 -
- ), - component:

Step 1: Read about PF3

, - stepNavItemProps: { navItemComponent: 'a', href: 'https://www.patternfly.org/v3/', target: '_blank' } - }, - { - name: ( -
- PF4 -
- ), - component:

Step 2: Read about PF4

, - stepNavItemProps: { navItemComponent: 'a', href: 'https://www.patternfly.org/v4/', target: '_blank' } - }, - { - name: ( -
- Join us on slack -
- ), - component: ( - - ), - stepNavItemProps: { navItemComponent: 'a', href: 'https://patternfly.slack.com/', target: '_blank' } - } - ]; - const title = 'Anchor link wizard'; - return ; - } -} +```ts file="./WizardAnchorsForNavItems.tsx" ``` ### Incrementally enabled steps -```js -import React from 'react'; -import { Button, Wizard } from '@patternfly/react-core'; - -class IncrementallyEnabledStepsWizard extends React.Component { - constructor(props) { - super(props); - this.state = { - stepIdReached: 1 - }; - this.onNext = ({ id }) => { - const [, orderIndex] = id.split('-'); - - this.setState({ - stepIdReached: this.state.stepIdReached < orderIndex ? orderIndex : this.state.stepIdReached - }); - }; - this.closeWizard = () => { - console.log('close wizard'); - }; - } - - render() { - const { stepIdReached } = this.state; - - const steps = [ - { id: 'incrementallyEnabled-1', name: 'First step', component:

Step 1 content

}, - { - id: 'incrementallyEnabled-2', - name: 'Second step', - component:

Step 2 content

, - canJumpTo: stepIdReached >= 2 - }, - { - id: 'incrementallyEnabled-3', - name: 'Third step', - component:

Step 3 content

, - canJumpTo: stepIdReached >= 3 - }, - { - id: 'incrementallyEnabled-4', - name: 'Fourth step', - component:

Step 4 content

, - canJumpTo: stepIdReached >= 4 - }, - { - id: 'incrementallyEnabled-5', - name: 'Review', - component:

Review step content

, - nextButtonText: 'Finish', - canJumpTo: stepIdReached >= 5 - } - ]; - const title = 'Incrementally enabled wizard'; - return ( - - ); - } -} +```ts file="./WizardIncrementallyEnabledSteps.tsx" ``` ### Expandable steps -```js -import React from 'react'; -import { Button, Wizard } from '@patternfly/react-core'; - -class SimpleWizard extends React.Component { - constructor(props) { - super(props); - } - - render() { - const steps = [ - { - name: 'First step', - steps: [ - { name: 'Substep A', component:

Substep A content

}, - { name: 'Substep B', component:

Substep B content

} - ] - }, - { name: 'Second step', component:

Step 2 content

}, - { - name: 'Third step', - steps: [ - { name: 'Substep C', component:

Substep C content

}, - { name: 'Substep D', component:

Substep D content

} - ] - }, - { name: 'Fourth step', component:

Step 4 content

}, - { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } - ]; - const title = 'Expandable wizard'; - return ( - - ); - } -} +```ts file="./WizardExpandableSteps.tsx" ``` ### Finished -```js -import React from 'react'; -import { Button, Wizard } from '@patternfly/react-core'; -import FinishedStep from './examples/FinishedStep'; - -class FinishedStepWizard extends React.Component { - constructor(props) { - super(props); - - this.closeWizard = () => { - console.log('close wizard'); - }; - } - - render() { - const steps = [ - { name: 'First step', component:

Step 1 content

}, - { name: 'Second step', component:

Step 2 content

}, - { name: 'Third step', component:

Step 3 content

}, - { name: 'Fourth step', component:

Step 4 content

}, - { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' }, - { name: 'Finish', component: , isFinishedStep: true } - ]; - const title = 'Finished wizard'; - return ( - - ); - } -} +```ts file="./WizardFinished.tsx" ``` ### Enabled on form validation -```js -import React from 'react'; -import { Button, Wizard, Form, FormGroup, TextInput } from '@patternfly/react-core'; -import SampleForm from './examples/SampleForm'; - -class ValidationWizard extends React.Component { - constructor(props) { - super(props); - this.state = { - isFormValid: false, - formValue: 'Thirty', - allStepsValid: false, - stepIdReached: 1 - }; - - this.closeWizard = () => { - console.log('close wizard'); - }; - - this.onFormChange = (isValid, value) => { - this.setState( - { - isFormValid: isValid, - formValue: value - }, - this.areAllStepsValid - ); - }; - - this.areAllStepsValid = () => { - this.setState({ - allStepsValid: this.state.isFormValid - }); - }; - - this.onNext = ({ id, name }, { prevId, prevName }) => { - console.log(`current id: ${id}, current name: ${name}, previous id: ${prevId}, previous name: ${prevName}`); - const [, orderIndex] = id.split('-'); - - this.setState({ - stepIdReached: this.state.stepIdReached < orderIndex ? orderIndex : this.state.stepIdReached - }); - this.areAllStepsValid(); - }; - - this.onBack = ({ id, name }, { prevId, prevName }) => { - console.log(`current id: ${id}, current name: ${name}, previous id: ${prevId}, previous name: ${prevName}`); - this.areAllStepsValid(); - }; - - this.onGoToStep = ({ id, name }, { prevId, prevName }) => { - console.log(`current id: ${id}, current name: ${name}, previous id: ${prevId}, previous name: ${prevName}`); - }; - - this.onSave = () => { - console.log('Saved and closed the wizard'); - this.setState({ - isOpen: false - }); - }; - } - - render() { - const { isFormValid, formValue, allStepsValid, stepIdReached } = this.state; - - const steps = [ - { id: 'validated-1', name: 'Information', component:

Step 1 content

}, - { - name: 'Configuration', - steps: [ - { - id: 'validated-2', - name: 'Substep A with validation', - component: , - enableNext: isFormValid, - canJumpTo: stepIdReached >= 2 - }, - { id: 'validated-3', name: 'Substep B', component:

Substep B

, canJumpTo: stepIdReached >= 3 } - ] - }, - { - id: 'validated-4', - name: 'Additional', - component:

Step 3 content

, - enableNext: allStepsValid, - canJumpTo: stepIdReached >= 4 - }, - { - id: 'validated-5', - name: 'Review', - component:

Step 4 content

, - nextButtonText: 'Close', - canJumpTo: stepIdReached >= 5 - } - ]; - const title = 'Enabled on form validation wizard'; - return ( - - ); - } -} +```ts file="./WizardEnabledOnFormValidation.tsx" ``` ### Validate on button press @@ -407,647 +70,25 @@ interface WizardContext { } ``` -```js -import React from 'react'; -import { Button, Wizard, WizardFooter, WizardContextConsumer, Alert } from '@patternfly/react-core'; -import SampleForm from './examples/SampleForm'; -import FinishedStep from './examples/FinishedStep'; - -class ValidateButtonPressWizard extends React.Component { - constructor(props) { - super(props); - this.state = { - stepsValid: 0 - }; - - this.closeWizard = () => { - console.log('close wizard'); - }; - - this.validateLastStep = onNext => { - const { stepsValid } = this.state; - if (stepsValid !== 1) { - this.setState({ - stepsValid: 1 - }); - } else { - onNext(); - } - }; - } - - render() { - const { stepsValid } = this.state; - - const steps = [ - { name: 'First step', component:

Step 1 content

}, - { name: 'Second step', component:

Step 2 content

}, - { - name: 'Final Step', - component: ( - <> - {stepsValid === 1 && ( -
- -
- )} - - - ) - }, - { name: 'Finish', component: , isFinishedStep: true } - ]; - - const CustomFooter = ( - - - {({ activeStep, goToStepByName, goToStepById, onNext, onBack, onClose }) => { - if (activeStep.name !== 'Final Step') { - return ( - <> - - - - - ); - } - // Final step buttons - return ( - <> - - - - ); - }} - - - ); - const title = 'Validate on button press wizard'; - return ( - - ); - } -} +```ts file="./WizardValidateOnButtonPress.tsx" ``` ### Progressive steps -```js -import React from 'react'; -import { Button, Radio, Wizard, WizardFooter, WizardContextConsumer, Alert } from '@patternfly/react-core'; -import SampleForm from './examples/SampleForm'; -import FinishedStep from './examples/FinishedStep'; - -class ProgressiveWizard extends React.Component { - constructor(props) { - super(props); - this.state = { - showCreateStep: false, - showUpdateStep: false, - showOptionsStep: false, - showReviewStep: false, - getStartedStepRadio: 'Create', - createStepRadio: 'Quick', - updateStepRadio: 'Quick' - }; - this.closeWizard = () => { - console.log('close wizard'); - }; - this.onGoToStep = ({ id, name }, { prevId, prevName }) => { - // Remove steps after the currently clicked step - if (name === 'Get started') { - this.setState({ - showReviewStep: false, - showOptionsStep: false, - showCreateStep: false, - showUpdateStep: false - }); - } else if (name === 'Create options' || name === 'Update options') { - this.setState({ - showReviewStep: false, - showOptionsStep: false - }); - } else if (name.indexOf('Substep') > -1) { - this.setState({ - showReviewStep: false - }); - } - }; - this.getNextStep = (activeStep, callback) => { - if (activeStep.name === 'Get started') { - if (this.state.getStartedStepRadio === 'Create') { - this.setState( - { - showCreateStep: true, - showUpdateStep: false, - showOptionsStep: false, - showReviewStep: false - }, - () => { - callback(); - } - ); - } else { - this.setState( - { - showCreateStep: false, - showUpdateStep: true, - showOptionsStep: false, - showReviewStep: false - }, - () => { - callback(); - } - ); - } - } else if (activeStep.name === 'Create options' || activeStep.name === 'Update options') { - this.setState( - { - showOptionsStep: true, - showReviewStep: false - }, - () => { - callback(); - } - ); - } else if (activeStep.name === 'Substep 3') { - this.setState( - { - showReviewStep: true - }, - () => { - callback(); - } - ); - } else { - callback(); - } - }; - this.getPreviousStep = (activeStep, callback) => { - if (activeStep.name === 'Review') { - this.setState( - { - showReviewStep: false - }, - () => { - callback(); - } - ); - } else if (activeStep.name === 'Substep 1') { - this.setState( - { - showOptionsStep: false - }, - () => { - callback(); - } - ); - } else if (activeStep.name === 'Create options') { - this.setState( - { - showCreateStep: false - }, - () => { - callback(); - } - ); - } else if (activeStep.name === 'Update options') { - this.setState( - { - showUpdateStep: false - }, - () => { - callback(); - } - ); - } else { - callback(); - } - }; - } - - render() { - const { - stepsValid, - getStartedStepRadio, - createStepRadio, - updateStepRadio, - showCreateStep, - showUpdateStep, - showOptionsStep, - showReviewStep - } = this.state; - - const getStartedStep = { - name: 'Get started', - component: ( -
- this.setState({ getStartedStepRadio: event.currentTarget.value })} - label="Create a new thing" - name="radio-step-start" - id="radio-step-start-1" - />{' '} - this.setState({ getStartedStepRadio: event.currentTarget.value })} - label="Update an existing thing" - name="radio-step-start" - id="radio-step-start-2" - /> -
- ) - }; - - const createStep = { - name: 'Create options', - component: ( -
- this.setState({ createStepRadio: event.currentTarget.value })} - label="Quick create" - name="radio-step-create" - id="radio-step-create-1" - />{' '} - this.setState({ createStepRadio: event.currentTarget.value })} - label="Custom create" - name="radio-step-create" - id="radio-step-create-2" - /> -
- ) - }; - - const updateStep = { - name: 'Update options', - component: ( -
- this.setState({ updateStepRadio: event.currentTarget.value })} - label="Quick update" - name="radio-step-update" - id="radio-step-update-1" - />{' '} - this.setState({ updateStepRadio: event.currentTarget.value })} - label="Custom update" - name="radio-step-update" - id="radio-step-update-2" - /> -
- ) - }; - - const optionsStep = { - name: showCreateStep ? `${createStepRadio} Options` : `${updateStepRadio} Options`, - steps: [ - { - name: 'Substep 1', - component: 'Substep 1' - }, - { - name: 'Substep 2', - component: 'Substep 2' - }, - { - name: 'Substep 3', - component: 'Substep 3' - } - ] - }; - - const reviewStep = { - name: 'Review', - component: ( -
-
First choice: {getStartedStepRadio}
-
Second choice: {showCreateStep ? createStepRadio : updateStepRadio}
-
- ) - }; - - const steps = [ - getStartedStep, - ...(showCreateStep ? [createStep] : []), - ...(showUpdateStep ? [updateStep] : []), - ...(showOptionsStep ? [optionsStep] : []), - ...(showReviewStep ? [reviewStep] : []) - ]; - - const CustomFooter = ( - - - {({ activeStep, goToStepByName, goToStepById, onNext, onBack, onClose }) => { - return ( - <> - - - - - ); - }} - - - ); - const title = 'Progressive wizard'; - return ( - - ); - } -} +```ts file="./WizardProgressiveSteps.tsx" ``` ### Get current step -```js -import React from 'react'; -import { Button, Wizard } from '@patternfly/react-core'; - -class GetCurrentStepWizard extends React.Component { - constructor(props) { - super(props); - this.state = { - step: 1 - }; - this.onCurrentStepChanged = ({ id }) => { - this.setState({ - step: id - }); - }; - this.closeWizard = () => { - console.log('close wizard'); - }; - } - - render() { - const steps = [ - { id: 1, name: 'First step', component:

Step 1 content

}, - { id: 2, name: 'Second step', component:

Step 2 content

}, - { id: 3, name: 'Third step', component:

Step 3 content

}, - { id: 4, name: 'Fourth step', component:

Step 4 content

}, - { id: 5, name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } - ]; - const title = 'Get current step wizard'; - return ( - - ); - } -} +```ts file="./WizardGetCurrentStep.tsx" ``` ### Wizard in modal -```js -import React from 'react'; -import { Button, Wizard } from '@patternfly/react-core'; - -class WizardInModal extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false - }; - this.handleModalToggle = () => { - this.setState(({ isOpen }) => ({ - isOpen: !isOpen - })); - }; - } - - render() { - const { isOpen } = this.state; - - const steps = [ - { name: 'First step', component:

Step 1 content

}, - { name: 'Second step', component:

Step 2 content

}, - { name: 'Third step', component:

Step 3 content

}, - { name: 'Fourth step', component:

Step 4 content

}, - { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } - ]; - const title = 'Wizard in modal'; - return ( - - - - - ); - } -} +```ts file="./WizardInModal.tsx" ``` ### Wizard with drawer -```js -import React from 'react'; -import { - Button, - DrawerActions, - DrawerCloseButton, - DrawerHead, - DrawerPanelContent, - Text, - TextContent, - Wizard -} from '@patternfly/react-core'; - -class WizardWithDrawer extends React.Component { - constructor(props) { - super(props); - this.state = { - isOpen: false, - isDrawerExpanded: false, - sectionGray: false, - panelGray: true, - contentGray: false - }; - - this.drawerRef = React.createRef(); - - this.onExpand = () => { - this.drawerRef.current && this.drawerRef.current.focus(); - }; - - this.onOpenClick = () => { - this.setState({ - isDrawerExpanded: true - }); - }; - - this.onCloseClick = () => { - this.setState({ - isDrawerExpanded: false - }); - }; - } - - render() { - const { isDrawerExpanded } = this.state; - - const panel1Content = ( - - - - drawer-panel-1 content - - - - - - - ); - - const panel2Content = ( - - - - drawer-panel-2 content - - - - - - - ); - - const panel3Content = ( - - - - drawer-panel-3 content - - - - - - - ); - - const drawerToggleButton = ( - - ); - - const steps = [ - { - name: 'Information', - component:

Information step content

, - drawerPanelContent: panel1Content, - drawerToggleButton: drawerToggleButton - }, - { - name: 'Configuration', - steps: [ - { - name: 'Substep A', - component:

Substep A content

, - drawerPanelContent: panel2Content, - drawerToggleButton: drawerToggleButton - }, - { - name: 'Substep B', - component:

Substep B content

, - drawerPanelContent: panel2Content, - drawerToggleButton: drawerToggleButton - }, - { - name: 'Substep C', - component:

Substep C content

, - drawerPanelContent: panel2Content, - drawerToggleButton: drawerToggleButton - } - ] - }, - { - name: 'Additional', - component:

Additional step content

, - drawerPanelContent: panel3Content, - drawerToggleButton: drawerToggleButton - }, - { - name: 'Review', - component:

Review step content

, - nextButtonText: 'Finish' - } - ]; - - const title = 'Wizard with drawer'; - - return ( - - - - ); - } -} +```ts file="./WizardWithDrawer.tsx" ``` diff --git a/packages/react-core/src/components/Wizard/examples/WizardAnchorsForNavItems.tsx b/packages/react-core/src/components/Wizard/examples/WizardAnchorsForNavItems.tsx new file mode 100644 index 00000000000..76300fc3cba --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardAnchorsForNavItems.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { Button, Wizard } from '@patternfly/react-core'; +import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; +import SlackHashIcon from '@patternfly/react-icons/dist/esm/icons/slack-hash-icon'; + +export const WizardWithNavAnchors: React.FunctionComponent = () => { + const steps = [ + { + name: ( +
+ PF3 +
+ ), + component:

Step 1: Read about PF3

, + stepNavItemProps: { navItemComponent: 'a', href: 'https://www.patternfly.org/v3/', target: '_blank' } + }, + { + name: ( +
+ PF4 +
+ ), + component:

Step 2: Read about PF4

, + stepNavItemProps: { navItemComponent: 'a', href: 'https://www.patternfly.org/v4/', target: '_blank' } + }, + { + name: ( +
+ Join us on slack +
+ ), + component: ( + + ), + stepNavItemProps: { navItemComponent: 'a', href: 'https://patternfly.slack.com/', target: '_blank' } + } + ]; + const title = 'Anchor link wizard'; + return ; +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardBasic.tsx b/packages/react-core/src/components/Wizard/examples/WizardBasic.tsx new file mode 100644 index 00000000000..6dbc6582dc5 --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardBasic.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { Wizard } from '@patternfly/react-core'; + +export const SimpleWizard: React.FunctionComponent = () => { + const steps = [ + { name: 'First step', component:

Step 1 content

}, + { name: 'Second step', component:

Step 2 content

}, + { name: 'Third step', component:

Step 3 content

}, + { name: 'Fourth step', component:

Step 4 content

}, + { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } + ]; + const title = 'Basic wizard'; + return ; +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardBasicWithDisabledSteps.tsx b/packages/react-core/src/components/Wizard/examples/WizardBasicWithDisabledSteps.tsx new file mode 100644 index 00000000000..29a70a89ebe --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardBasicWithDisabledSteps.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { Wizard } from '@patternfly/react-core'; + +export const SimpleWizard: React.FunctionComponent = () => { + const steps = [ + { name: 'First step', component:

Step 1 content

}, + { name: 'Second step', component:

Step 2 content

, isDisabled: true }, + { name: 'Third step', component:

Step 3 content

}, + { name: 'Fourth step', component:

Step 4 content

, isDisabled: true }, + { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } + ]; + const title = 'Basic wizard'; + return ; +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx new file mode 100644 index 00000000000..9801b833ba0 --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx @@ -0,0 +1,106 @@ +import React from 'react'; +import { Wizard, WizardStep } from '@patternfly/react-core'; +import SampleForm from './SampleForm'; + +interface PrevStepInfo { + prevId?: string | number; + prevName: React.ReactNode; +} + +export const ValidationWizard: React.FunctionComponent = () => { + const [isFormValid, setIsFormValid] = React.useState(false); + const [formValue, setFormValue] = React.useState('Thirty'); + const [allStepsValid, setAllStepsValid] = React.useState(false); + const [stepIdReached, setStepIdReached] = React.useState(1); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [isOpen, setIsOpen] = React.useState(true); + + const closeWizard = () => { + // eslint-disable-next-line no-console + console.log('close wizard'); + }; + + const onFormChange = (isValid: boolean, value: string) => { + setIsFormValid(isValid); + setFormValue(value); + areAllStepsValid(); + }; + + const areAllStepsValid = () => { + setAllStepsValid(isFormValid); + }; + + const onNext = ({ id, name }: WizardStep, { prevId, prevName }: PrevStepInfo) => { + // eslint-disable-next-line no-console + console.log(`current id: ${id}, current name: ${name}, previous id: ${prevId}, previous name: ${prevName}`); + if (id) { + if (typeof id === 'string') { + id = parseInt(id); + } + setStepIdReached(stepIdReached < id ? id : stepIdReached); + } + areAllStepsValid(); + }; + + const onBack = ({ id, name }: WizardStep, { prevId, prevName }: PrevStepInfo) => { + // eslint-disable-next-line no-console + console.log(`current id: ${id}, current name: ${name}, previous id: ${prevId}, previous name: ${prevName}`); + areAllStepsValid(); + }; + + const onGoToStep = ({ id, name }: WizardStep, { prevId, prevName }: PrevStepInfo) => { + // eslint-disable-next-line no-console + console.log(`current id: ${id}, current name: ${name}, previous id: ${prevId}, previous name: ${prevName}`); + }; + + const onSave = () => { + // eslint-disable-next-line no-console + console.log('Saved and closed the wizard'); + setIsOpen(false); + }; + + const steps = [ + { id: 'validated-1', name: 'Information', component:

Step 1 content

}, + { + name: 'Configuration', + steps: [ + { + id: 'validated-2', + name: 'Substep A with validation', + component: , + enableNext: isFormValid, + canJumpTo: stepIdReached >= 2 + }, + { id: 'validated-3', name: 'Substep B', component:

Substep B

, canJumpTo: stepIdReached >= 3 } + ] + }, + { + id: 'validated-4', + name: 'Additional', + component:

Step 3 content

, + enableNext: allStepsValid, + canJumpTo: stepIdReached >= 4 + }, + { + id: 'validated-5', + name: 'Review', + component:

Step 4 content

, + nextButtonText: 'Close', + canJumpTo: stepIdReached >= 5 + } + ]; + const title = 'Enabled on form validation wizard'; + return ( + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardExpandableSteps.tsx b/packages/react-core/src/components/Wizard/examples/WizardExpandableSteps.tsx new file mode 100644 index 00000000000..adedcc6a64b --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardExpandableSteps.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { Wizard } from '@patternfly/react-core'; + +export const SimpleWizard: React.FunctionComponent = () => { + const steps = [ + { + name: 'First step', + steps: [ + { name: 'Substep A', component:

Substep A content

}, + { name: 'Substep B', component:

Substep B content

} + ] + }, + { name: 'Second step', component:

Step 2 content

}, + { + name: 'Third step', + steps: [ + { name: 'Substep C', component:

Substep C content

}, + { name: 'Substep D', component:

Substep D content

} + ] + }, + { name: 'Fourth step', component:

Step 4 content

}, + { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } + ]; + const title = 'Expandable wizard'; + return ( + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx new file mode 100644 index 00000000000..989e06b8427 --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Wizard } from '@patternfly/react-core'; +import FinishedStep from './FinishedStep'; + +export const FinishedStepWizard: React.FunctionComponent = () => { + const closeWizard = () => { + // eslint-disable-next-line no-console + console.log('close wizard'); + }; + + const steps = [ + { name: 'First step', component:

Step 1 content

}, + { name: 'Second step', component:

Step 2 content

}, + { name: 'Third step', component:

Step 3 content

}, + { name: 'Fourth step', component:

Step 4 content

}, + { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' }, + { name: 'Finish', component: , isFinishedStep: true } + ]; + const title = 'Finished wizard'; + return ( + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardGetCurrentStep.tsx b/packages/react-core/src/components/Wizard/examples/WizardGetCurrentStep.tsx new file mode 100644 index 00000000000..3dcbb22acec --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardGetCurrentStep.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Wizard, WizardStep } from '@patternfly/react-core'; + +export const GetCurrentStepWizard: React.FunctionComponent = () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [step, setStep] = React.useState(1); + const onCurrentStepChanged = ({ id }: WizardStep) => { + if (id) { + setStep(typeof id === 'string' ? parseInt(id) : id); + } + }; + const closeWizard = () => { + // eslint-disable-next-line no-console + console.log('close wizard'); + }; + + const steps = [ + { id: 1, name: 'First step', component:

Step 1 content

}, + { id: 2, name: 'Second step', component:

Step 2 content

}, + { id: 3, name: 'Third step', component:

Step 3 content

}, + { id: 4, name: 'Fourth step', component:

Step 4 content

}, + { id: 5, name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } + ]; + const title = 'Get current step wizard'; + return ( + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardInModal.tsx b/packages/react-core/src/components/Wizard/examples/WizardInModal.tsx new file mode 100644 index 00000000000..55cd3edd2ab --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardInModal.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Button, Wizard } from '@patternfly/react-core'; + +export const WizardInModal: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = React.useState(false); + const handleModalToggle = () => { + setIsOpen(!isOpen); + }; + const steps = [ + { name: 'First step', component:

Step 1 content

}, + { name: 'Second step', component:

Step 2 content

}, + { name: 'Third step', component:

Step 3 content

}, + { name: 'Fourth step', component:

Step 4 content

}, + { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } + ]; + const title = 'Wizard in modal'; + return ( + + + + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardIncrementallyEnabledSteps.tsx b/packages/react-core/src/components/Wizard/examples/WizardIncrementallyEnabledSteps.tsx new file mode 100644 index 00000000000..d3ba86ea743 --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardIncrementallyEnabledSteps.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { Wizard, WizardStep } from '@patternfly/react-core'; + +export const IncrementallyEnabledStepsWizard: React.FunctionComponent = () => { + const [stepIdReached, setStepIdReached] = React.useState(1); + + const onNext = ({ id }: WizardStep) => { + if (id) { + if (typeof id === 'string') { + const [, orderIndex] = id.split('-'); + id = parseInt(orderIndex); + } + setStepIdReached(stepIdReached < id ? id : stepIdReached); + } + }; + + // const onNext = ({ id }: {id: number}) => { + // setStepIdReached((stepIdReached < id ? id : stepIdReached) as number) + // }; + + const closeWizard = () => { + // eslint-disable-next-line no-console + console.log('close wizard'); + }; + + const steps = [ + { id: 'incrementallyEnabled-1', name: 'First step', component:

Step 1 content

}, + { + id: 'incrementallyEnabled-2', + name: 'Second step', + component:

Step 2 content

, + canJumpTo: stepIdReached >= 2 + }, + { + id: 'incrementallyEnabled-3', + name: 'Third step', + component:

Step 3 content

, + canJumpTo: stepIdReached >= 3 + }, + { + id: 'incrementallyEnabled-4', + name: 'Fourth step', + component:

Step 4 content

, + canJumpTo: stepIdReached >= 4 + }, + { + id: 'incrementallyEnabled-5', + name: 'Review', + component:

Review step content

, + nextButtonText: 'Finish', + canJumpTo: stepIdReached >= 5 + } + ]; + const title = 'Incrementally enabled wizard'; + return ( + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx b/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx new file mode 100644 index 00000000000..04fd5917282 --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx @@ -0,0 +1,226 @@ +import React from 'react'; +import { Button, Radio, Wizard, WizardFooter, WizardContextConsumer, WizardStep } from '@patternfly/react-core'; + +interface PrevStepInfo { + prevId?: string | number; + prevName: React.ReactNode; +} + +export const ProgressiveWizard: React.FunctionComponent = () => { + const [showCreateStep, setShowCreateStep] = React.useState(false); + const [showUpdateStep, setShowUpdateStep] = React.useState(false); + const [showOptionsStep, setShowOptionsStep] = React.useState(false); + const [showReviewStep, setShowReviewStep] = React.useState(false); + const [getStartedStepRadio, setGetStartedStepRadio] = React.useState('Create'); + const [createStepRadio] = React.useState('Quick'); + const [updateStepRadio] = React.useState('Quick'); + const closeWizard = () => { + // eslint-disable-next-line no-console + console.log('close wizard'); + }; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const onGoToStep = ({ id, name }: WizardStep, { prevId, prevName }: PrevStepInfo) => { + // Remove steps after the currently clicked step + if (name === 'Get started') { + setShowCreateStep(false); + setShowUpdateStep(false); + setShowOptionsStep(false); + setShowReviewStep(false); + } else if (name === 'Create options' || name === 'Update options') { + setShowOptionsStep(false); + setShowReviewStep(false); + } else if (String(name).indexOf('Substep') > -1) { + setShowReviewStep(false); + } + }; + const getNextStep = (activeStep: WizardStep, callback: () => void) => { + if (activeStep.name === 'Get started') { + if (getStartedStepRadio === 'Create') { + setShowCreateStep(true); + setShowUpdateStep(false); + setShowOptionsStep(false); + setShowReviewStep(false); + callback(); + } else { + setShowCreateStep(false); + setShowUpdateStep(true); + setShowOptionsStep(false); + setShowReviewStep(false); + callback(); + } + } else if (activeStep.name === 'Create options' || activeStep.name === 'Update options') { + setShowReviewStep(false); + setShowOptionsStep(true); + callback(); + } else if (activeStep.name === 'Substep 3') { + setShowReviewStep(true); + callback(); + } + }; + + const getPreviousStep = (activeStep: WizardStep, callback: () => void) => { + if (activeStep.name === 'Review') { + setShowReviewStep(false); + callback(); + } else if (activeStep.name === 'Substep 1') { + setShowOptionsStep(false); + callback(); + } else if (activeStep.name === 'Create options') { + setShowCreateStep(false); + callback(); + } else if (activeStep.name === 'Update options') { + setShowUpdateStep(false); + callback(); + } else { + callback(); + } + }; + + const getStartedStep = { + name: 'Get started', + component: ( +
+ setGetStartedStepRadio(event.currentTarget.value)} + label="Create a new thing" + name="radio-step-start" + id="radio-step-start-1" + />{' '} + setGetStartedStepRadio(event.currentTarget.value)} + label="Update an existing thing" + name="radio-step-start" + id="radio-step-start-2" + /> +
+ ) + }; + + const createStep = { + name: 'Create options', + component: ( +
+ setGetStartedStepRadio(event.currentTarget.value)} + label="Quick create" + name="radio-step-create" + id="radio-step-create-1" + />{' '} + setGetStartedStepRadio(event.currentTarget.value)} + label="Custom create" + name="radio-step-create" + id="radio-step-create-2" + /> +
+ ) + }; + + const updateStep = { + name: 'Update options', + component: ( +
+ setGetStartedStepRadio(event.currentTarget.value)} + label="Quick update" + name="radio-step-update" + id="radio-step-update-1" + />{' '} + setGetStartedStepRadio(event.currentTarget.value)} + label="Custom update" + name="radio-step-update" + id="radio-step-update-2" + /> +
+ ) + }; + + const optionsStep = { + name: showCreateStep ? `${createStepRadio} Options` : `${updateStepRadio} Options`, + steps: [ + { + name: 'Substep 1', + component: 'Substep 1' + }, + { + name: 'Substep 2', + component: 'Substep 2' + }, + { + name: 'Substep 3', + component: 'Substep 3' + } + ] + }; + + const reviewStep = { + name: 'Review', + component: ( +
+
First choice: {getStartedStepRadio}
+
Second choice: {showCreateStep ? createStepRadio : updateStepRadio}
+
+ ) + }; + + const steps = [ + getStartedStep, + ...(showCreateStep ? [createStep] : []), + ...(showUpdateStep ? [updateStep] : []), + ...(showOptionsStep ? [optionsStep] : []), + ...(showReviewStep ? [reviewStep] : []) + ]; + + /* eslint-disable @typescript-eslint/no-unused-vars */ + const CustomFooter = ( + + + {({ activeStep, goToStepByName, goToStepById, onNext, onBack, onClose }) => ( + <> + + + + + )} + + + ); + /* eslint-enable @typescript-eslint/no-unused-vars */ + + const title = 'Progressive wizard'; + return ( + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx new file mode 100644 index 00000000000..92aa01611c5 --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { Button, Wizard, WizardFooter, WizardContextConsumer, Alert } from '@patternfly/react-core'; +import SampleForm from './SampleForm'; +import FinishedStep from './FinishedStep'; + +export const ValidateButtonPressWizard: React.FunctionComponent = () => { + const [stepsValid, setStepsValid] = React.useState(0); + + const closeWizard = () => { + // eslint-disable-next-line no-console + console.log('close wizard'); + }; + + const validateLastStep: (onNext: () => void) => void = onNext => { + if (stepsValid !== 1) { + setStepsValid(1); + } else { + onNext(); + } + }; + + const steps = [ + { name: 'First step', component:

Step 1 content

}, + { name: 'Second step', component:

Step 2 content

}, + { + name: 'Final Step', + component: ( + <> + {stepsValid === 1 && ( +
+ +
+ )} + + + ) + }, + { name: 'Finish', component: , isFinishedStep: true } + ]; + + /* eslint-disable @typescript-eslint/no-unused-vars */ + const CustomFooter = ( + + + {({ activeStep, goToStepByName, goToStepById, onNext, onBack, onClose }) => { + if (activeStep.name !== 'Final Step') { + return ( + <> + + + + + ); + } + // Final step buttons + return ( + <> + + + + ); + }} + + + ); + /* eslint-enable @typescript-eslint/no-unused-vars */ + + const title = 'Validate on button press wizard'; + return ( + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardWithDrawer.tsx b/packages/react-core/src/components/Wizard/examples/WizardWithDrawer.tsx new file mode 100644 index 00000000000..74aaddc0265 --- /dev/null +++ b/packages/react-core/src/components/Wizard/examples/WizardWithDrawer.tsx @@ -0,0 +1,137 @@ +import React from 'react'; +import { + Button, + DrawerActions, + DrawerCloseButton, + DrawerColorVariant, + DrawerHead, + DrawerPanelContent, + Wizard +} from '@patternfly/react-core'; + +export const WizardWithDrawer: React.FunctionComponent = () => { + /* eslint-disable @typescript-eslint/no-unused-vars */ + const [isOpen, setIsOpen] = React.useState(false); + const [isDrawerExpanded, setIsDrawerExpanded] = React.useState(false); + const [sectionGray, setSectionGray] = React.useState(false); + const [panelGray, setPanelGray] = React.useState(true); + const [contentGray, setContentGray] = React.useState(false); + /* eslint-enable @typescript-eslint/no-unused-vars */ + + const drawerRef = React.useRef(null); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const onExpand = () => { + drawerRef.current && drawerRef.current.focus(); + }; + + const onOpenClick = () => { + setIsDrawerExpanded(true); + }; + + const onCloseClick = () => { + setIsDrawerExpanded(false); + }; + + const panel1Content = ( + + + + drawer-panel-1 content + + + + + + + ); + + const panel2Content = ( + + + + drawer-panel-2 content + + + + + + + ); + + const panel3Content = ( + + + + drawer-panel-3 content + + + + + + + ); + + const drawerToggleButton = ( + + ); + + const steps = [ + { + name: 'Information', + component:

Information step content

, + drawerPanelContent: panel1Content, + drawerToggleButton + }, + { + name: 'Configuration', + steps: [ + { + name: 'Substep A', + component:

Substep A content

, + drawerPanelContent: panel2Content, + drawerToggleButton + }, + { + name: 'Substep B', + component:

Substep B content

, + drawerPanelContent: panel2Content, + drawerToggleButton + }, + { + name: 'Substep C', + component:

Substep C content

, + drawerPanelContent: panel2Content, + drawerToggleButton + } + ] + }, + { + name: 'Additional', + component:

Additional step content

, + drawerPanelContent: panel3Content, + drawerToggleButton + }, + { + name: 'Review', + component:

Review step content

, + nextButtonText: 'Finish' + } + ]; + + const title = 'Wizard with drawer'; + + return ( + + + + ); +}; From 634ed9061c0fae37912412f69fc50b37a4ed620d Mon Sep 17 00:00:00 2001 From: Xiangyu Shen Date: Wed, 26 Oct 2022 14:54:23 -0400 Subject: [PATCH 02/15] Fix import statements --- packages/react-core/src/components/Wizard/examples/Wizard.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/Wizard.md b/packages/react-core/src/components/Wizard/examples/Wizard.md index 779301e6e70..4e2a696f5f1 100644 --- a/packages/react-core/src/components/Wizard/examples/Wizard.md +++ b/packages/react-core/src/components/Wizard/examples/Wizard.md @@ -11,8 +11,8 @@ import { Button, Drawer, DrawerActions, DrawerCloseButton, DrawerColorVariant, DrawerContent, DrawerContentBody, DrawerHead, DrawerPanelContent, DrawerSection, Wizard, WizardFooter, WizardContextConsumer, ModalVariant, Alert, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStateSecondaryActions, Title, Progress } from '@patternfly/react-core'; import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; import SlackHashIcon from '@patternfly/react-icons/dist/esm/icons/slack-hash-icon'; -import FinishedStep from './FinishedStep'; -import SampleForm from './SampleForm'; +import FinishedStep from './FinishedStep.js'; +import SampleForm from './SampleForm.js'; If you seek a wizard solution that allows for more composition, see the [React next](/components/wizard/react-next) tab. From 33d43804e32336ec3fe7ab0a2bd55c91ec7856c9 Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Sun, 13 Nov 2022 17:58:38 -0500 Subject: [PATCH 03/15] Requested changes for cleanup --- .../src/components/Wizard/examples/Wizard.md | 4 ++-- .../Wizard/examples/WizardAnchorsForNavItems.tsx | 2 +- .../components/Wizard/examples/WizardBasic.tsx | 4 ++-- .../examples/WizardBasicWithDisabledSteps.tsx | 4 ++-- .../examples/WizardEnabledOnFormValidation.tsx | 15 +++------------ .../Wizard/examples/WizardExpandableSteps.tsx | 4 ++-- .../components/Wizard/examples/WizardFinished.tsx | 4 ++-- .../Wizard/examples/WizardGetCurrentStep.tsx | 4 ++-- .../components/Wizard/examples/WizardInModal.tsx | 2 +- .../examples/WizardIncrementallyEnabledSteps.tsx | 8 ++------ .../Wizard/examples/WizardProgressiveSteps.tsx | 12 ++++++------ .../examples/WizardValidateOnButtonPress.tsx | 8 +++----- .../Wizard/examples/WizardWithDrawer.tsx | 8 +------- 13 files changed, 29 insertions(+), 50 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/Wizard.md b/packages/react-core/src/components/Wizard/examples/Wizard.md index 779301e6e70..4e2a696f5f1 100644 --- a/packages/react-core/src/components/Wizard/examples/Wizard.md +++ b/packages/react-core/src/components/Wizard/examples/Wizard.md @@ -11,8 +11,8 @@ import { Button, Drawer, DrawerActions, DrawerCloseButton, DrawerColorVariant, DrawerContent, DrawerContentBody, DrawerHead, DrawerPanelContent, DrawerSection, Wizard, WizardFooter, WizardContextConsumer, ModalVariant, Alert, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStateSecondaryActions, Title, Progress } from '@patternfly/react-core'; import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; import SlackHashIcon from '@patternfly/react-icons/dist/esm/icons/slack-hash-icon'; -import FinishedStep from './FinishedStep'; -import SampleForm from './SampleForm'; +import FinishedStep from './FinishedStep.js'; +import SampleForm from './SampleForm.js'; If you seek a wizard solution that allows for more composition, see the [React next](/components/wizard/react-next) tab. diff --git a/packages/react-core/src/components/Wizard/examples/WizardAnchorsForNavItems.tsx b/packages/react-core/src/components/Wizard/examples/WizardAnchorsForNavItems.tsx index 76300fc3cba..6c26cd8e937 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardAnchorsForNavItems.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardAnchorsForNavItems.tsx @@ -37,6 +37,6 @@ export const WizardWithNavAnchors: React.FunctionComponent = () => { stepNavItemProps: { navItemComponent: 'a', href: 'https://patternfly.slack.com/', target: '_blank' } } ]; - const title = 'Anchor link wizard'; + const title = 'Anchor link wizard example'; return ; }; diff --git a/packages/react-core/src/components/Wizard/examples/WizardBasic.tsx b/packages/react-core/src/components/Wizard/examples/WizardBasic.tsx index 6dbc6582dc5..71eca4176f5 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardBasic.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardBasic.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Wizard } from '@patternfly/react-core'; -export const SimpleWizard: React.FunctionComponent = () => { +export const WizardBasic: React.FunctionComponent = () => { const steps = [ { name: 'First step', component:

Step 1 content

}, { name: 'Second step', component:

Step 2 content

}, @@ -9,6 +9,6 @@ export const SimpleWizard: React.FunctionComponent = () => { { name: 'Fourth step', component:

Step 4 content

}, { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } ]; - const title = 'Basic wizard'; + const title = 'Basic wizard example'; return ; }; diff --git a/packages/react-core/src/components/Wizard/examples/WizardBasicWithDisabledSteps.tsx b/packages/react-core/src/components/Wizard/examples/WizardBasicWithDisabledSteps.tsx index 29a70a89ebe..46b92e151e9 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardBasicWithDisabledSteps.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardBasicWithDisabledSteps.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Wizard } from '@patternfly/react-core'; -export const SimpleWizard: React.FunctionComponent = () => { +export const WizardBasicWithDisabledSteps: React.FunctionComponent = () => { const steps = [ { name: 'First step', component:

Step 1 content

}, { name: 'Second step', component:

Step 2 content

, isDisabled: true }, @@ -9,6 +9,6 @@ export const SimpleWizard: React.FunctionComponent = () => { { name: 'Fourth step', component:

Step 4 content

, isDisabled: true }, { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } ]; - const title = 'Basic wizard'; + const title = 'Basic wizard with disabled steps example'; return ; }; diff --git a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx index 9801b833ba0..901ffd61f41 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx @@ -7,13 +7,11 @@ interface PrevStepInfo { prevName: React.ReactNode; } -export const ValidationWizard: React.FunctionComponent = () => { +export const WizardFormValidation: React.FunctionComponent = () => { const [isFormValid, setIsFormValid] = React.useState(false); const [formValue, setFormValue] = React.useState('Thirty'); const [allStepsValid, setAllStepsValid] = React.useState(false); const [stepIdReached, setStepIdReached] = React.useState(1); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [isOpen, setIsOpen] = React.useState(true); const closeWizard = () => { // eslint-disable-next-line no-console @@ -53,12 +51,6 @@ export const ValidationWizard: React.FunctionComponent = () => { console.log(`current id: ${id}, current name: ${name}, previous id: ${prevId}, previous name: ${prevName}`); }; - const onSave = () => { - // eslint-disable-next-line no-console - console.log('Saved and closed the wizard'); - setIsOpen(false); - }; - const steps = [ { id: 'validated-1', name: 'Information', component:

Step 1 content

}, { @@ -85,17 +77,16 @@ export const ValidationWizard: React.FunctionComponent = () => { id: 'validated-5', name: 'Review', component:

Step 4 content

, - nextButtonText: 'Close', + nextButtonText: 'Finish', canJumpTo: stepIdReached >= 5 } ]; - const title = 'Enabled on form validation wizard'; + const title = 'Wizard enabled on form validation example'; return ( { +export const WizardExpandableSteps: React.FunctionComponent = () => { const steps = [ { name: 'First step', @@ -21,7 +21,7 @@ export const SimpleWizard: React.FunctionComponent = () => { { name: 'Fourth step', component:

Step 4 content

}, { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } ]; - const title = 'Expandable wizard'; + const title = 'Expandable wizard example'; return ( { +export const WizardFinished: React.FunctionComponent = () => { const closeWizard = () => { // eslint-disable-next-line no-console console.log('close wizard'); @@ -16,7 +16,7 @@ export const FinishedStepWizard: React.FunctionComponent = () => { { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' }, { name: 'Finish', component: , isFinishedStep: true } ]; - const title = 'Finished wizard'; + const title = 'Finished wizard example'; return ( { +export const WizardGetCurrentStep: React.FunctionComponent = () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const [step, setStep] = React.useState(1); const onCurrentStepChanged = ({ id }: WizardStep) => { @@ -21,7 +21,7 @@ export const GetCurrentStepWizard: React.FunctionComponent = () => { { id: 4, name: 'Fourth step', component:

Step 4 content

}, { id: 5, name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } ]; - const title = 'Get current step wizard'; + const title = 'Get current step wizard example'; return ( { { name: 'Fourth step', component:

Step 4 content

}, { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' } ]; - const title = 'Wizard in modal'; + const title = 'Wizard in modal example'; return ( @@ -209,9 +210,8 @@ export const ProgressiveWizard: React.FunctionComponent = () => { ); - /* eslint-enable @typescript-eslint/no-unused-vars */ - const title = 'Progressive wizard'; + const title = 'Progressive wizard example'; return ( { +export const WizardValidateButtonPress: React.FunctionComponent = () => { const [stepsValid, setStepsValid] = React.useState(0); const closeWizard = () => { @@ -38,11 +38,10 @@ export const ValidateButtonPressWizard: React.FunctionComponent = () => { { name: 'Finish', component: , isFinishedStep: true } ]; - /* eslint-disable @typescript-eslint/no-unused-vars */ const CustomFooter = ( - {({ activeStep, goToStepByName, goToStepById, onNext, onBack, onClose }) => { + {({ activeStep, goToStepByName, onNext, onBack, onClose }) => { if (activeStep.name !== 'Final Step') { return ( <> @@ -73,9 +72,8 @@ export const ValidateButtonPressWizard: React.FunctionComponent = () => { ); - /* eslint-enable @typescript-eslint/no-unused-vars */ - const title = 'Validate on button press wizard'; + const title = 'Validate on button press wizard example'; return ( { - /* eslint-disable @typescript-eslint/no-unused-vars */ - const [isOpen, setIsOpen] = React.useState(false); const [isDrawerExpanded, setIsDrawerExpanded] = React.useState(false); - const [sectionGray, setSectionGray] = React.useState(false); - const [panelGray, setPanelGray] = React.useState(true); - const [contentGray, setContentGray] = React.useState(false); - /* eslint-enable @typescript-eslint/no-unused-vars */ const drawerRef = React.useRef(null); @@ -121,7 +115,7 @@ export const WizardWithDrawer: React.FunctionComponent = () => { } ]; - const title = 'Wizard with drawer'; + const title = 'Wizard with drawer example'; return ( From a3a1dcb3780dd39686bfa9e6a211694c6d14bd89 Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Tue, 29 Nov 2022 19:59:38 -0500 Subject: [PATCH 04/15] Integrate FinishedStep and SampleForm into examples directly --- .../Wizard/examples/FinishedStep.js | 70 ------------ .../components/Wizard/examples/SampleForm.js | 59 ---------- .../src/components/Wizard/examples/Wizard.md | 5 +- .../WizardEnabledOnFormValidation.tsx | 45 +++++++- .../Wizard/examples/WizardFinished.tsx | 59 +++++++++- .../examples/WizardValidateOnButtonPress.tsx | 107 +++++++++++++++++- 6 files changed, 203 insertions(+), 142 deletions(-) delete mode 100644 packages/react-core/src/components/Wizard/examples/FinishedStep.js delete mode 100644 packages/react-core/src/components/Wizard/examples/SampleForm.js diff --git a/packages/react-core/src/components/Wizard/examples/FinishedStep.js b/packages/react-core/src/components/Wizard/examples/FinishedStep.js deleted file mode 100644 index 6adfd128f09..00000000000 --- a/packages/react-core/src/components/Wizard/examples/FinishedStep.js +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { - EmptyState, - EmptyStateIcon, - EmptyStateBody, - EmptyStateSecondaryActions, - Title, - Progress, - Button -} from '@patternfly/react-core'; -// eslint-disable-next-line patternfly-react/import-tokens-icons -import { CogsIcon } from '@patternfly/react-icons'; - -const propTypes = { - onClose: PropTypes.func.isRequired -}; - -class FinishedStep extends React.Component { - constructor(props) { - super(props); - this.state = { percent: 0 }; - } - - tick() { - if (this.state.percent < 100) { - this.setState(prevState => ({ - percent: prevState.percent + 20 - })); - } - } - - componentDidMount() { - this.interval = setInterval(() => this.tick(), 1000); - } - - componentWillUnmount() { - clearInterval(this.interval); - } - - render() { - const { percent } = this.state; - return ( -
- - - - {percent === 100 ? 'Validation complete' : 'Validating credentials'} - - - - - - Description can be used to further elaborate on the validation step, or give the user a better idea of how - long the process will take. - - - - - -
- ); - } -} - -FinishedStep.propTypes = propTypes; - -export default FinishedStep; diff --git a/packages/react-core/src/components/Wizard/examples/SampleForm.js b/packages/react-core/src/components/Wizard/examples/SampleForm.js deleted file mode 100644 index 9992752f404..00000000000 --- a/packages/react-core/src/components/Wizard/examples/SampleForm.js +++ /dev/null @@ -1,59 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Form, FormGroup, TextInput } from '@patternfly/react-core'; - -const propTypes = { - formValue: PropTypes.string, - isFormValid: PropTypes.bool, - onChange: PropTypes.func -}; - -const defaultProps = { - formValue: '', - isFormValid: false, - onChange: () => undefined -}; - -class SampleForm extends React.Component { - static propTypes = propTypes; - static defaultProps = defaultProps; - - state = { - value: this.props.formValue, - isValid: this.props.isFormValid - }; - - handleTextInputChange = value => { - const isValid = /^\d+$/.test(value); - this.setState({ value, isValid }); - this.props.onChange && this.props.onChange(isValid, value); - }; - - render() { - const { value, isValid } = this.state; - const validated = isValid ? 'default' : 'error'; - - return ( -
- - - -
- ); - } -} - -export default SampleForm; diff --git a/packages/react-core/src/components/Wizard/examples/Wizard.md b/packages/react-core/src/components/Wizard/examples/Wizard.md index 4e2a696f5f1..946dfa22a02 100644 --- a/packages/react-core/src/components/Wizard/examples/Wizard.md +++ b/packages/react-core/src/components/Wizard/examples/Wizard.md @@ -8,11 +8,10 @@ ouia: true --- import { Button, Drawer, DrawerActions, DrawerCloseButton, DrawerColorVariant, -DrawerContent, DrawerContentBody, DrawerHead, DrawerPanelContent, DrawerSection, Wizard, WizardFooter, WizardContextConsumer, ModalVariant, Alert, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStateSecondaryActions, Title, Progress } from '@patternfly/react-core'; +DrawerContent, DrawerContentBody, DrawerHead, DrawerPanelContent, DrawerSection, Wizard, WizardFooter, WizardContextConsumer, ModalVariant, Alert, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStateSecondaryActions, Title, Progress, Form, FormGroup, TextInput } from '@patternfly/react-core'; import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; import SlackHashIcon from '@patternfly/react-icons/dist/esm/icons/slack-hash-icon'; -import FinishedStep from './FinishedStep.js'; -import SampleForm from './SampleForm.js'; + If you seek a wizard solution that allows for more composition, see the [React next](/components/wizard/react-next) tab. diff --git a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx index 901ffd61f41..762b9c39cfc 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx @@ -1,7 +1,5 @@ import React from 'react'; -import { Wizard, WizardStep } from '@patternfly/react-core'; -import SampleForm from './SampleForm'; - +import { Form, FormGroup, TextInput, Wizard, WizardStep } from '@patternfly/react-core'; interface PrevStepInfo { prevId?: string | number; prevName: React.ReactNode; @@ -95,3 +93,44 @@ export const WizardFormValidation: React.FunctionComponent = () => { /> ); }; + +interface sampleFormProps { + formValue: string; + isFormValid: boolean; + onChange?: (isValid: boolean, value: string) => void; +} + +const SampleForm: React.FunctionComponent = (props: sampleFormProps) => { + const [value, setValue] = React.useState(props.formValue); + const [isValid, setIsValid] = React.useState(props.isFormValid); + + const handleTextInputChange = (value: string) => { + const valid = /^\d+$/.test(value); + setValue(value); + setIsValid(valid); + props.onChange && props.onChange(isValid, value); + }; + + const validated = isValid ? 'default' : 'error'; + + return ( +
+ + + +
+ ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx index 64ee19f4c92..d62535db82b 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx @@ -1,6 +1,16 @@ -import React from 'react'; -import { Wizard } from '@patternfly/react-core'; -import FinishedStep from './FinishedStep'; +import React, { useEffect } from 'react'; +import { + EmptyState, + EmptyStateIcon, + EmptyStateBody, + EmptyStateSecondaryActions, + Title, + Progress, + Button, + Wizard +} from '@patternfly/react-core'; +// eslint-disable-next-line patternfly-react/import-tokens-icons +import { CogsIcon } from '@patternfly/react-icons'; export const WizardFinished: React.FunctionComponent = () => { const closeWizard = () => { @@ -27,3 +37,46 @@ export const WizardFinished: React.FunctionComponent = () => { /> ); }; + +interface finishedProps { + onClose: () => void; +} + +const FinishedStep: React.FunctionComponent = (props: finishedProps) => { + const [percent, setPercent] = React.useState(0); + + const tick = () => { + if (percent < 100) { + setPercent(percent + 20); + } + }; + + useEffect(() => { + const interval = setInterval(() => tick(), 1000); + + return () => clearInterval(interval); + }, []); + + return ( +
+ + + + {percent === 100 ? 'Validation complete' : 'Validating credentials'} + + + + + + Description can be used to further elaborate on the validation step, or give the user a better idea of how + long the process will take. + + + + + +
+ ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx index 153a09dfbe2..2178b40e494 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx @@ -1,7 +1,22 @@ -import React from 'react'; -import { Button, Wizard, WizardFooter, WizardContextConsumer, Alert } from '@patternfly/react-core'; -import SampleForm from './SampleForm'; -import FinishedStep from './FinishedStep'; +import React, { useEffect } from 'react'; +import { + EmptyState, + EmptyStateIcon, + EmptyStateBody, + EmptyStateSecondaryActions, + Title, + Form, + FormGroup, + TextInput, + Progress, + Button, + Wizard, + WizardFooter, + WizardContextConsumer, + Alert +} from '@patternfly/react-core'; +// eslint-disable-next-line patternfly-react/import-tokens-icons +import { CogsIcon } from '@patternfly/react-icons'; export const WizardValidateButtonPress: React.FunctionComponent = () => { const [stepsValid, setStepsValid] = React.useState(0); @@ -85,3 +100,87 @@ export const WizardValidateButtonPress: React.FunctionComponent = () => { /> ); }; + +interface finishedProps { + onClose: () => void; +} + +const FinishedStep: React.FunctionComponent = (props: finishedProps) => { + const [percent, setPercent] = React.useState(0); + + const tick = () => { + if (percent < 100) { + setPercent(percent + 20); + } + }; + + useEffect(() => { + const interval = setInterval(() => tick(), 1000); + + return () => clearInterval(interval); + }, []); + + return ( +
+ + + + {percent === 100 ? 'Validation complete' : 'Validating credentials'} + + + + + + Description can be used to further elaborate on the validation step, or give the user a better idea of how + long the process will take. + + + + + +
+ ); +}; + +interface sampleFormProps { + formValue: string; + isFormValid: boolean; + onChange?: (isValid: boolean, value: string) => void; +} + +const SampleForm: React.FunctionComponent = (props: sampleFormProps) => { + const [value, setValue] = React.useState(props.formValue); + const [isValid, setIsValid] = React.useState(props.isFormValid); + + const handleTextInputChange = (value: string) => { + const valid = /^\d+$/.test(value); + setValue(value); + setIsValid(valid); + props.onChange && props.onChange(isValid, value); + }; + + const validated = isValid ? 'default' : 'error'; + + return ( +
+ + + +
+ ); +}; From 94d2d5d8fde04deb1bf5edb0888ede13490965a5 Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Tue, 29 Nov 2022 20:00:28 -0500 Subject: [PATCH 05/15] Remove unused onExpand function --- .../src/components/Wizard/examples/WizardWithDrawer.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/WizardWithDrawer.tsx b/packages/react-core/src/components/Wizard/examples/WizardWithDrawer.tsx index 9e8ab19a0f9..9a1e134fa9b 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardWithDrawer.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardWithDrawer.tsx @@ -14,11 +14,6 @@ export const WizardWithDrawer: React.FunctionComponent = () => { const drawerRef = React.useRef(null); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const onExpand = () => { - drawerRef.current && drawerRef.current.focus(); - }; - const onOpenClick = () => { setIsDrawerExpanded(true); }; From 178087c33824a6496d1bcf35f5551c5bc65b4d9a Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Tue, 29 Nov 2022 20:42:33 -0500 Subject: [PATCH 06/15] Fix useEffect not defined --- .../src/components/Wizard/examples/WizardFinished.tsx | 4 ++-- .../Wizard/examples/WizardValidateOnButtonPress.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx index d62535db82b..4709c10f71f 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import { EmptyState, EmptyStateIcon, @@ -51,7 +51,7 @@ const FinishedStep: React.FunctionComponent = (props: finishedPro } }; - useEffect(() => { + React.useEffect(() => { const interval = setInterval(() => tick(), 1000); return () => clearInterval(interval); diff --git a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx index 2178b40e494..33732264a44 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import { EmptyState, EmptyStateIcon, @@ -114,7 +114,7 @@ const FinishedStep: React.FunctionComponent = (props: finishedPro } }; - useEffect(() => { + React.useEffect(() => { const interval = setInterval(() => tick(), 1000); return () => clearInterval(interval); From f336d86c8a12f87a160a0904d96d611ecaf8390a Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Wed, 30 Nov 2022 11:43:10 -0500 Subject: [PATCH 07/15] Import CogsIcon --- packages/react-core/src/components/Wizard/examples/Wizard.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-core/src/components/Wizard/examples/Wizard.md b/packages/react-core/src/components/Wizard/examples/Wizard.md index 946dfa22a02..5c309a85253 100644 --- a/packages/react-core/src/components/Wizard/examples/Wizard.md +++ b/packages/react-core/src/components/Wizard/examples/Wizard.md @@ -11,6 +11,7 @@ import { Button, Drawer, DrawerActions, DrawerCloseButton, DrawerColorVariant, DrawerContent, DrawerContentBody, DrawerHead, DrawerPanelContent, DrawerSection, Wizard, WizardFooter, WizardContextConsumer, ModalVariant, Alert, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStateSecondaryActions, Title, Progress, Form, FormGroup, TextInput } from '@patternfly/react-core'; import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; import SlackHashIcon from '@patternfly/react-icons/dist/esm/icons/slack-hash-icon'; +import CogsIcon from '@patternfly/react-icons/dist/esm/icons/cogs-icon'; If you seek a wizard solution that allows for more composition, see the [React next](/components/wizard/react-next) tab. From e07a51b334607fee92c89b4b42f705f4d5222f7f Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Wed, 30 Nov 2022 15:36:26 -0500 Subject: [PATCH 08/15] a11y fixes for FinishedStep and SampleForm conversions --- .../Wizard/examples/WizardEnabledOnFormValidation.tsx | 2 +- .../src/components/Wizard/examples/WizardFinished.tsx | 2 +- .../Wizard/examples/WizardValidateOnButtonPress.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx index 762b9c39cfc..787cbdd21d2 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx @@ -126,7 +126,7 @@ const SampleForm: React.FunctionComponent = (props: sampleFormP diff --git a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx index 4709c10f71f..dc3ac5a0187 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx @@ -65,7 +65,7 @@ const FinishedStep: React.FunctionComponent = (props: finishedPro {percent === 100 ? 'Validation complete' : 'Validating credentials'} - + Description can be used to further elaborate on the validation step, or give the user a better idea of how diff --git a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx index 33732264a44..6c2d79dc0b6 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx @@ -128,7 +128,7 @@ const FinishedStep: React.FunctionComponent = (props: finishedPro {percent === 100 ? 'Validation complete' : 'Validating credentials'} - + Description can be used to further elaborate on the validation step, or give the user a better idea of how @@ -176,7 +176,7 @@ const SampleForm: React.FunctionComponent = (props: sampleFormP From a3495f7cbe72764468d592a985042bfc6a01a1ce Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Wed, 30 Nov 2022 16:46:34 -0500 Subject: [PATCH 09/15] a11y fixes --- .../WizardEnabledOnFormValidation.tsx | 91 +++++----- .../Wizard/examples/WizardFinished.tsx | 52 +++--- .../examples/WizardValidateOnButtonPress.tsx | 168 +++++++++--------- 3 files changed, 157 insertions(+), 154 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx index 787cbdd21d2..0b520b96744 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx @@ -5,12 +5,57 @@ interface PrevStepInfo { prevName: React.ReactNode; } +interface sampleFormProps { + formValue: string; + isFormValid: boolean; + onChange?: (isValid: boolean, value: string) => void; +} + +const SampleForm: React.FunctionComponent = (props: sampleFormProps) => { + const [value, setValue] = React.useState(props.formValue); + const [isValid, setIsValid] = React.useState(props.isFormValid); + + const handleTextInputChange = (value: string) => { + const valid = /^\d+$/.test(value); + setValue(value); + setIsValid(valid); + props.onChange && props.onChange(isValid, value); + }; + + const validated = isValid ? 'default' : 'error'; + + return ( +
+ + + +
+ ); +}; + export const WizardFormValidation: React.FunctionComponent = () => { const [isFormValid, setIsFormValid] = React.useState(false); const [formValue, setFormValue] = React.useState('Thirty'); const [allStepsValid, setAllStepsValid] = React.useState(false); const [stepIdReached, setStepIdReached] = React.useState(1); + React.useEffect(() => { + setAllStepsValid(isFormValid); + }, [isFormValid, stepIdReached]); + const closeWizard = () => { // eslint-disable-next-line no-console console.log('close wizard'); @@ -19,7 +64,6 @@ export const WizardFormValidation: React.FunctionComponent = () => { const onFormChange = (isValid: boolean, value: string) => { setIsFormValid(isValid); setFormValue(value); - areAllStepsValid(); }; const areAllStepsValid = () => { @@ -31,11 +75,11 @@ export const WizardFormValidation: React.FunctionComponent = () => { console.log(`current id: ${id}, current name: ${name}, previous id: ${prevId}, previous name: ${prevName}`); if (id) { if (typeof id === 'string') { - id = parseInt(id); + const [, orderIndex] = id.split('-'); + id = parseInt(orderIndex); } setStepIdReached(stepIdReached < id ? id : stepIdReached); } - areAllStepsValid(); }; const onBack = ({ id, name }: WizardStep, { prevId, prevName }: PrevStepInfo) => { @@ -93,44 +137,3 @@ export const WizardFormValidation: React.FunctionComponent = () => { /> ); }; - -interface sampleFormProps { - formValue: string; - isFormValid: boolean; - onChange?: (isValid: boolean, value: string) => void; -} - -const SampleForm: React.FunctionComponent = (props: sampleFormProps) => { - const [value, setValue] = React.useState(props.formValue); - const [isValid, setIsValid] = React.useState(props.isFormValid); - - const handleTextInputChange = (value: string) => { - const valid = /^\d+$/.test(value); - setValue(value); - setIsValid(valid); - props.onChange && props.onChange(isValid, value); - }; - - const validated = isValid ? 'default' : 'error'; - - return ( -
- - - -
- ); -}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx index dc3ac5a0187..86c8d1cad0a 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx @@ -12,32 +12,6 @@ import { // eslint-disable-next-line patternfly-react/import-tokens-icons import { CogsIcon } from '@patternfly/react-icons'; -export const WizardFinished: React.FunctionComponent = () => { - const closeWizard = () => { - // eslint-disable-next-line no-console - console.log('close wizard'); - }; - - const steps = [ - { name: 'First step', component:

Step 1 content

}, - { name: 'Second step', component:

Step 2 content

}, - { name: 'Third step', component:

Step 3 content

}, - { name: 'Fourth step', component:

Step 4 content

}, - { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' }, - { name: 'Finish', component: , isFinishedStep: true } - ]; - const title = 'Finished wizard example'; - return ( - - ); -}; - interface finishedProps { onClose: () => void; } @@ -80,3 +54,29 @@ const FinishedStep: React.FunctionComponent = (props: finishedPro ); }; + +export const WizardFinished: React.FunctionComponent = () => { + const closeWizard = () => { + // eslint-disable-next-line no-console + console.log('close wizard'); + }; + + const steps = [ + { name: 'First step', component:

Step 1 content

}, + { name: 'Second step', component:

Step 2 content

}, + { name: 'Third step', component:

Step 3 content

}, + { name: 'Fourth step', component:

Step 4 content

}, + { name: 'Review', component:

Review step content

, nextButtonText: 'Finish' }, + { name: 'Finish', component: , isFinishedStep: true } + ]; + const title = 'Finished wizard example'; + return ( + + ); +}; diff --git a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx index 6c2d79dc0b6..2ea3a376fc0 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx @@ -18,89 +18,6 @@ import { // eslint-disable-next-line patternfly-react/import-tokens-icons import { CogsIcon } from '@patternfly/react-icons'; -export const WizardValidateButtonPress: React.FunctionComponent = () => { - const [stepsValid, setStepsValid] = React.useState(0); - - const closeWizard = () => { - // eslint-disable-next-line no-console - console.log('close wizard'); - }; - - const validateLastStep: (onNext: () => void) => void = onNext => { - if (stepsValid !== 1) { - setStepsValid(1); - } else { - onNext(); - } - }; - - const steps = [ - { name: 'First step', component:

Step 1 content

}, - { name: 'Second step', component:

Step 2 content

}, - { - name: 'Final Step', - component: ( - <> - {stepsValid === 1 && ( -
- -
- )} - - - ) - }, - { name: 'Finish', component: , isFinishedStep: true } - ]; - - const CustomFooter = ( - - - {({ activeStep, goToStepByName, onNext, onBack, onClose }) => { - if (activeStep.name !== 'Final Step') { - return ( - <> - - - - - ); - } - // Final step buttons - return ( - <> - - - - ); - }} - - - ); - - const title = 'Validate on button press wizard example'; - return ( - - ); -}; - interface finishedProps { onClose: () => void; } @@ -176,7 +93,7 @@ const SampleForm: React.FunctionComponent = (props: sampleFormP @@ -184,3 +101,86 @@ const SampleForm: React.FunctionComponent = (props: sampleFormP ); }; + +export const WizardValidateButtonPress: React.FunctionComponent = () => { + const [stepsValid, setStepsValid] = React.useState(0); + + const closeWizard = () => { + // eslint-disable-next-line no-console + console.log('close wizard'); + }; + + const validateLastStep: (onNext: () => void) => void = onNext => { + if (stepsValid !== 1) { + setStepsValid(1); + } else { + onNext(); + } + }; + + const steps = [ + { name: 'First step', component:

Step 1 content

}, + { name: 'Second step', component:

Step 2 content

}, + { + name: 'Final Step', + component: ( + <> + {stepsValid === 1 && ( +
+ +
+ )} + + + ) + }, + { name: 'Finish', component: , isFinishedStep: true } + ]; + + const CustomFooter = ( + + + {({ activeStep, goToStepByName, onNext, onBack, onClose }) => { + if (activeStep.name !== 'Final Step') { + return ( + <> + + + + + ); + } + // Final step buttons + return ( + <> + + + + ); + }} + + + ); + + const title = 'Validate on button press wizard example'; + return ( + + ); +}; From 81d7ec1cc2901edd90cbd76f917d75f44d44f07f Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Thu, 1 Dec 2022 15:01:43 -0500 Subject: [PATCH 10/15] Bug Fixes --- .../examples/WizardEnabledOnFormValidation.tsx | 2 +- .../Wizard/examples/WizardFinished.tsx | 16 ++++++++++++---- .../examples/WizardValidateOnButtonPress.tsx | 18 +++++++++++++----- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx index 0b520b96744..9121779a59e 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardEnabledOnFormValidation.tsx @@ -19,7 +19,7 @@ const SampleForm: React.FunctionComponent = (props: sampleFormP const valid = /^\d+$/.test(value); setValue(value); setIsValid(valid); - props.onChange && props.onChange(isValid, value); + props.onChange && props.onChange(valid, value); }; const validated = isValid ? 'default' : 'error'; diff --git a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx index 86c8d1cad0a..072d1098f46 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardFinished.tsx @@ -20,16 +20,24 @@ const FinishedStep: React.FunctionComponent = (props: finishedPro const [percent, setPercent] = React.useState(0); const tick = () => { - if (percent < 100) { - setPercent(percent + 20); - } + setPercent(prevPercent => { + if (prevPercent < 100) { + return prevPercent + 20; + } else { + return prevPercent; + } + }); }; React.useEffect(() => { const interval = setInterval(() => tick(), 1000); + if (percent >= 100) { + clearInterval(interval); + } + return () => clearInterval(interval); - }, []); + }, [percent]); return (
diff --git a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx index 2ea3a376fc0..f1f1446bfbf 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx @@ -26,16 +26,24 @@ const FinishedStep: React.FunctionComponent = (props: finishedPro const [percent, setPercent] = React.useState(0); const tick = () => { - if (percent < 100) { - setPercent(percent + 20); - } + setPercent(prevPercent => { + if (prevPercent < 100) { + return prevPercent + 20; + } else { + return prevPercent; + } + }); }; React.useEffect(() => { const interval = setInterval(() => tick(), 1000); + if (percent >= 100) { + clearInterval(interval); + } + return () => clearInterval(interval); - }, []); + }, [percent]); return (
@@ -75,7 +83,7 @@ const SampleForm: React.FunctionComponent = (props: sampleFormP const valid = /^\d+$/.test(value); setValue(value); setIsValid(valid); - props.onChange && props.onChange(isValid, value); + props.onChange && props.onChange(valid, value); }; const validated = isValid ? 'default' : 'error'; From 54db8d18b74052a3ead72084f6f3a644360dc4b9 Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Mon, 5 Dec 2022 10:18:48 -0500 Subject: [PATCH 11/15] Fixed incorrect Radio button state setting --- .../Wizard/examples/WizardProgressiveSteps.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx b/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx index 6bbdcab27f5..3a818137162 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx @@ -12,8 +12,8 @@ export const WizardProgressiveSteps: React.FunctionComponent = () => { const [showOptionsStep, setShowOptionsStep] = React.useState(false); const [showReviewStep, setShowReviewStep] = React.useState(false); const [getStartedStepRadio, setGetStartedStepRadio] = React.useState('Create'); - const [createStepRadio] = React.useState('Quick'); - const [updateStepRadio] = React.useState('Quick'); + const [createStepRadio, setCreateStepRadio] = React.useState('Quick'); + const [updateStepRadio, setUpdateStepRadio] = React.useState('Quick'); const closeWizard = () => { // eslint-disable-next-line no-console console.log('close wizard'); @@ -110,7 +110,7 @@ export const WizardProgressiveSteps: React.FunctionComponent = () => { setGetStartedStepRadio(event.currentTarget.value)} + onChange={(_, event) => setCreateStepRadio(event.currentTarget.value)} label="Quick create" name="radio-step-create" id="radio-step-create-1" @@ -118,7 +118,7 @@ export const WizardProgressiveSteps: React.FunctionComponent = () => { setGetStartedStepRadio(event.currentTarget.value)} + onChange={(_, event) => setCreateStepRadio(event.currentTarget.value)} label="Custom create" name="radio-step-create" id="radio-step-create-2" @@ -134,7 +134,7 @@ export const WizardProgressiveSteps: React.FunctionComponent = () => { setGetStartedStepRadio(event.currentTarget.value)} + onChange={(_, event) => setUpdateStepRadio(event.currentTarget.value)} label="Quick update" name="radio-step-update" id="radio-step-update-1" @@ -142,7 +142,7 @@ export const WizardProgressiveSteps: React.FunctionComponent = () => { setGetStartedStepRadio(event.currentTarget.value)} + onChange={(_, event) => setUpdateStepRadio(event.currentTarget.value)} label="Custom update" name="radio-step-update" id="radio-step-update-2" From dfa29b0314b852b403159e0950c9626ce36bc876 Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Tue, 6 Dec 2022 18:54:05 -0500 Subject: [PATCH 12/15] Revert Progressive Steps example change --- .../src/components/Wizard/examples/Wizard.md | 285 +++++++++++++++++- .../examples/WizardProgressiveSteps.tsx | 226 -------------- 2 files changed, 284 insertions(+), 227 deletions(-) delete mode 100644 packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx diff --git a/packages/react-core/src/components/Wizard/examples/Wizard.md b/packages/react-core/src/components/Wizard/examples/Wizard.md index 5c309a85253..1cbafaf5932 100644 --- a/packages/react-core/src/components/Wizard/examples/Wizard.md +++ b/packages/react-core/src/components/Wizard/examples/Wizard.md @@ -75,7 +75,290 @@ interface WizardContext { ### Progressive steps -```ts file="./WizardProgressiveSteps.tsx" +```js +import React from 'react'; +import { Button, Radio, Wizard, WizardFooter, WizardContextConsumer, Alert } from '@patternfly/react-core'; +import SampleForm from './examples/SampleForm'; +import FinishedStep from './examples/FinishedStep'; +class ProgressiveWizard extends React.Component { + constructor(props) { + super(props); + this.state = { + showCreateStep: false, + showUpdateStep: false, + showOptionsStep: false, + showReviewStep: false, + getStartedStepRadio: 'Create', + createStepRadio: 'Quick', + updateStepRadio: 'Quick' + }; + this.closeWizard = () => { + console.log('close wizard'); + }; + this.onGoToStep = ({ id, name }, { prevId, prevName }) => { + // Remove steps after the currently clicked step + if (name === 'Get started') { + this.setState({ + showReviewStep: false, + showOptionsStep: false, + showCreateStep: false, + showUpdateStep: false + }); + } else if (name === 'Create options' || name === 'Update options') { + this.setState({ + showReviewStep: false, + showOptionsStep: false + }); + } else if (name.indexOf('Substep') > -1) { + this.setState({ + showReviewStep: false + }); + } + }; + this.getNextStep = (activeStep, callback) => { + if (activeStep.name === 'Get started') { + if (this.state.getStartedStepRadio === 'Create') { + this.setState( + { + showCreateStep: true, + showUpdateStep: false, + showOptionsStep: false, + showReviewStep: false + }, + () => { + callback(); + } + ); + } else { + this.setState( + { + showCreateStep: false, + showUpdateStep: true, + showOptionsStep: false, + showReviewStep: false + }, + () => { + callback(); + } + ); + } + } else if (activeStep.name === 'Create options' || activeStep.name === 'Update options') { + this.setState( + { + showOptionsStep: true, + showReviewStep: false + }, + () => { + callback(); + } + ); + } else if (activeStep.name === 'Substep 3') { + this.setState( + { + showReviewStep: true + }, + () => { + callback(); + } + ); + } else { + callback(); + } + }; + this.getPreviousStep = (activeStep, callback) => { + if (activeStep.name === 'Review') { + this.setState( + { + showReviewStep: false + }, + () => { + callback(); + } + ); + } else if (activeStep.name === 'Substep 1') { + this.setState( + { + showOptionsStep: false + }, + () => { + callback(); + } + ); + } else if (activeStep.name === 'Create options') { + this.setState( + { + showCreateStep: false + }, + () => { + callback(); + } + ); + } else if (activeStep.name === 'Update options') { + this.setState( + { + showUpdateStep: false + }, + () => { + callback(); + } + ); + } else { + callback(); + } + }; + } + render() { + const { + stepsValid, + getStartedStepRadio, + createStepRadio, + updateStepRadio, + showCreateStep, + showUpdateStep, + showOptionsStep, + showReviewStep + } = this.state; + const getStartedStep = { + name: 'Get started', + component: ( +
+ this.setState({ getStartedStepRadio: event.currentTarget.value })} + label="Create a new thing" + name="radio-step-start" + id="radio-step-start-1" + />{' '} + this.setState({ getStartedStepRadio: event.currentTarget.value })} + label="Update an existing thing" + name="radio-step-start" + id="radio-step-start-2" + /> +
+ ) + }; + const createStep = { + name: 'Create options', + component: ( +
+ this.setState({ createStepRadio: event.currentTarget.value })} + label="Quick create" + name="radio-step-create" + id="radio-step-create-1" + />{' '} + this.setState({ createStepRadio: event.currentTarget.value })} + label="Custom create" + name="radio-step-create" + id="radio-step-create-2" + /> +
+ ) + }; + const updateStep = { + name: 'Update options', + component: ( +
+ this.setState({ updateStepRadio: event.currentTarget.value })} + label="Quick update" + name="radio-step-update" + id="radio-step-update-1" + />{' '} + this.setState({ updateStepRadio: event.currentTarget.value })} + label="Custom update" + name="radio-step-update" + id="radio-step-update-2" + /> +
+ ) + }; + const optionsStep = { + name: showCreateStep ? `${createStepRadio} Options` : `${updateStepRadio} Options`, + steps: [ + { + name: 'Substep 1', + component: 'Substep 1' + }, + { + name: 'Substep 2', + component: 'Substep 2' + }, + { + name: 'Substep 3', + component: 'Substep 3' + } + ] + }; + const reviewStep = { + name: 'Review', + component: ( +
+
First choice: {getStartedStepRadio}
+
Second choice: {showCreateStep ? createStepRadio : updateStepRadio}
+
+ ) + }; + const steps = [ + getStartedStep, + ...(showCreateStep ? [createStep] : []), + ...(showUpdateStep ? [updateStep] : []), + ...(showOptionsStep ? [optionsStep] : []), + ...(showReviewStep ? [reviewStep] : []) + ]; + const CustomFooter = ( + + + {({ activeStep, goToStepByName, goToStepById, onNext, onBack, onClose }) => { + return ( + <> + + + + + ); + }} + + + ); + const title = 'Progressive wizard'; + return ( + + ); + } +} ``` ### Get current step diff --git a/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx b/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx deleted file mode 100644 index 3a818137162..00000000000 --- a/packages/react-core/src/components/Wizard/examples/WizardProgressiveSteps.tsx +++ /dev/null @@ -1,226 +0,0 @@ -import React from 'react'; -import { Button, Radio, Wizard, WizardFooter, WizardContextConsumer, WizardStep } from '@patternfly/react-core'; - -interface PrevStepInfo { - prevId?: string | number; - prevName: React.ReactNode; -} - -export const WizardProgressiveSteps: React.FunctionComponent = () => { - const [showCreateStep, setShowCreateStep] = React.useState(false); - const [showUpdateStep, setShowUpdateStep] = React.useState(false); - const [showOptionsStep, setShowOptionsStep] = React.useState(false); - const [showReviewStep, setShowReviewStep] = React.useState(false); - const [getStartedStepRadio, setGetStartedStepRadio] = React.useState('Create'); - const [createStepRadio, setCreateStepRadio] = React.useState('Quick'); - const [updateStepRadio, setUpdateStepRadio] = React.useState('Quick'); - const closeWizard = () => { - // eslint-disable-next-line no-console - console.log('close wizard'); - }; - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const onGoToStep = ({ id, name }: WizardStep, { prevId, prevName }: PrevStepInfo) => { - // Remove steps after the currently clicked step - if (name === 'Get started') { - setShowCreateStep(false); - setShowUpdateStep(false); - setShowOptionsStep(false); - setShowReviewStep(false); - } else if (name === 'Create options' || name === 'Update options') { - setShowOptionsStep(false); - setShowReviewStep(false); - } else if (String(name).indexOf('Substep') > -1) { - setShowReviewStep(false); - } - }; - const getNextStep = (activeStep: WizardStep, callback: () => void) => { - if (activeStep.name === 'Get started') { - if (getStartedStepRadio === 'Create') { - setShowCreateStep(true); - setShowUpdateStep(false); - setShowOptionsStep(false); - setShowReviewStep(false); - callback(); - } else { - setShowCreateStep(false); - setShowUpdateStep(true); - setShowOptionsStep(false); - setShowReviewStep(false); - callback(); - } - } else if (activeStep.name === 'Create options' || activeStep.name === 'Update options') { - setShowReviewStep(false); - setShowOptionsStep(true); - callback(); - } else if (activeStep.name === 'Substep 3') { - setShowReviewStep(true); - callback(); - } else { - callback(); - } - }; - - const getPreviousStep = (activeStep: WizardStep, callback: () => void) => { - if (activeStep.name === 'Review') { - setShowReviewStep(false); - callback(); - } else if (activeStep.name === 'Substep 1') { - setShowOptionsStep(false); - callback(); - } else if (activeStep.name === 'Create options') { - setShowCreateStep(false); - callback(); - } else if (activeStep.name === 'Update options') { - setShowUpdateStep(false); - callback(); - } else { - callback(); - } - }; - - const getStartedStep = { - name: 'Get started', - component: ( -
- setGetStartedStepRadio(event.currentTarget.value)} - label="Create a new thing" - name="radio-step-start" - id="radio-step-start-1" - />{' '} - setGetStartedStepRadio(event.currentTarget.value)} - label="Update an existing thing" - name="radio-step-start" - id="radio-step-start-2" - /> -
- ) - }; - - const createStep = { - name: 'Create options', - component: ( -
- setCreateStepRadio(event.currentTarget.value)} - label="Quick create" - name="radio-step-create" - id="radio-step-create-1" - />{' '} - setCreateStepRadio(event.currentTarget.value)} - label="Custom create" - name="radio-step-create" - id="radio-step-create-2" - /> -
- ) - }; - - const updateStep = { - name: 'Update options', - component: ( -
- setUpdateStepRadio(event.currentTarget.value)} - label="Quick update" - name="radio-step-update" - id="radio-step-update-1" - />{' '} - setUpdateStepRadio(event.currentTarget.value)} - label="Custom update" - name="radio-step-update" - id="radio-step-update-2" - /> -
- ) - }; - - const optionsStep = { - name: showCreateStep ? `${createStepRadio} Options` : `${updateStepRadio} Options`, - steps: [ - { - name: 'Substep 1', - component: 'Substep 1' - }, - { - name: 'Substep 2', - component: 'Substep 2' - }, - { - name: 'Substep 3', - component: 'Substep 3' - } - ] - }; - - const reviewStep = { - name: 'Review', - component: ( -
-
First choice: {getStartedStepRadio}
-
Second choice: {showCreateStep ? createStepRadio : updateStepRadio}
-
- ) - }; - - const steps = [ - getStartedStep, - ...(showCreateStep ? [createStep] : []), - ...(showUpdateStep ? [updateStep] : []), - ...(showOptionsStep ? [optionsStep] : []), - ...(showReviewStep ? [reviewStep] : []) - ]; - - const CustomFooter = ( - - - {({ activeStep, onNext, onBack, onClose }) => ( - <> - - - - - )} - - - ); - - const title = 'Progressive wizard example'; - return ( - - ); -}; From cecdb45b04553e8dec51218bba28351996a1b39a Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Wed, 7 Dec 2022 22:44:55 -0500 Subject: [PATCH 13/15] Fix Validate on Button Press for Wizard --- .../examples/WizardValidateOnButtonPress.tsx | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx index f1f1446bfbf..d13172d8f61 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardValidateOnButtonPress.tsx @@ -111,17 +111,27 @@ const SampleForm: React.FunctionComponent = (props: sampleFormP }; export const WizardValidateButtonPress: React.FunctionComponent = () => { + const [isFormValid, setIsFormValid] = React.useState(false); + const [formValue, setFormValue] = React.useState('Validating on button press'); const [stepsValid, setStepsValid] = React.useState(0); + const [errorText, setErrorText] = React.useState(false); const closeWizard = () => { // eslint-disable-next-line no-console console.log('close wizard'); }; + const onFormChange = (isValid: boolean, value: string) => { + setIsFormValid(isValid); + setFormValue(value); + }; + const validateLastStep: (onNext: () => void) => void = onNext => { - if (stepsValid !== 1) { - setStepsValid(1); + if (stepsValid !== 1 && !isFormValid) { + setErrorText(true); } else { + setStepsValid(1); + setErrorText(false); onNext(); } }; @@ -133,12 +143,12 @@ export const WizardValidateButtonPress: React.FunctionComponent = () => { name: 'Final Step', component: ( <> - {stepsValid === 1 && ( + {errorText && (
)} - + ) }, @@ -158,7 +168,7 @@ export const WizardValidateButtonPress: React.FunctionComponent = () => { @@ -172,7 +182,7 @@ export const WizardValidateButtonPress: React.FunctionComponent = () => { return ( <> - + ); }} From 0a9841bb072cb3afeef0147d512eadd845d3fc1e Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Thu, 8 Dec 2022 10:33:57 -0500 Subject: [PATCH 14/15] Fix import in example --- packages/react-core/src/components/Wizard/examples/Wizard.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/Wizard.md b/packages/react-core/src/components/Wizard/examples/Wizard.md index 1cbafaf5932..56cc069554c 100644 --- a/packages/react-core/src/components/Wizard/examples/Wizard.md +++ b/packages/react-core/src/components/Wizard/examples/Wizard.md @@ -78,8 +78,7 @@ interface WizardContext { ```js import React from 'react'; import { Button, Radio, Wizard, WizardFooter, WizardContextConsumer, Alert } from '@patternfly/react-core'; -import SampleForm from './examples/SampleForm'; -import FinishedStep from './examples/FinishedStep'; + class ProgressiveWizard extends React.Component { constructor(props) { super(props); From 40a558e9b930d16769a74a2ae2e52762bcf9248a Mon Sep 17 00:00:00 2001 From: XiangyuShen Date: Thu, 8 Dec 2022 16:48:12 -0500 Subject: [PATCH 15/15] Remove unnecessary step state --- .../components/Wizard/examples/WizardGetCurrentStep.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/react-core/src/components/Wizard/examples/WizardGetCurrentStep.tsx b/packages/react-core/src/components/Wizard/examples/WizardGetCurrentStep.tsx index d1b4ed4e827..f41edaa0f34 100644 --- a/packages/react-core/src/components/Wizard/examples/WizardGetCurrentStep.tsx +++ b/packages/react-core/src/components/Wizard/examples/WizardGetCurrentStep.tsx @@ -2,12 +2,9 @@ import React from 'react'; import { Wizard, WizardStep } from '@patternfly/react-core'; export const WizardGetCurrentStep: React.FunctionComponent = () => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [step, setStep] = React.useState(1); const onCurrentStepChanged = ({ id }: WizardStep) => { - if (id) { - setStep(typeof id === 'string' ? parseInt(id) : id); - } + // eslint-disable-next-line no-console + console.log(id); }; const closeWizard = () => { // eslint-disable-next-line no-console