From 97ed6d8ee4e1f4008d890b41f8556c6b106774d9 Mon Sep 17 00:00:00 2001 From: Eric Olkowski Date: Tue, 18 Apr 2023 15:36:08 -0400 Subject: [PATCH 1/5] chore(Wizard): updated demos to use new Wizard --- .../react-core/src/demos/Wizard/WizardDemo.md | 508 +++++------------- 1 file changed, 142 insertions(+), 366 deletions(-) diff --git a/packages/react-core/src/demos/Wizard/WizardDemo.md b/packages/react-core/src/demos/Wizard/WizardDemo.md index 6fc75a9a179..4e87cfef88c 100644 --- a/packages/react-core/src/demos/Wizard/WizardDemo.md +++ b/packages/react-core/src/demos/Wizard/WizardDemo.md @@ -25,18 +25,20 @@ import { NavList, PageSection, Modal, - ModalVariant + ModalVariant, + Wizard, + WizardHeader, + WizardStep } from '@patternfly/react-core'; -import { Wizard as WizardDeprecated } from '@patternfly/react-core/deprecated'; import DashboardWrapper from '@patternfly/react-core/src/demos/examples/DashboardWrapper'; -class BasicWizardDemo extends React.Component { +class WizardInModalDemo extends React.Component { constructor(props) { super(props); this.state = { activeItem: 0 }; - this.onNavSelect = result => { + this.onNavSelect = (result) => { this.setState({ activeItem: result.itemId }); @@ -45,28 +47,6 @@ class BasicWizardDemo extends React.Component { render() { const { activeItem } = this.state; - const steps = [ - { id: 0, name: 'Information', component:

Step 1 content

}, - { - id: 1, - name: 'Configuration', - steps: [ - { - id: 2, - name: 'Substep A', - component:

Configuration substep A

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

Configuration substep B

- } - ], - component:

Step 2 content

- }, - { id: 4, name: 'Additional', component:

Step 3 content

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

Review step content

, nextButtonText: 'Finish' } - ]; const title = 'Basic wizard'; return ( @@ -91,16 +71,32 @@ class BasicWizardDemo extends React.Component { aria-describedby="wiz-modal-demo-description" aria-labelledby="wiz-modal-demo-title" > - } height={400} - /> + > + +

Step 1 content

+
+ +

Configuration substep A

+
, + +

Configuration substep B

+
+ ]} + /> + +

Step 3 content

+
+ +

Review step content

+
+
); @@ -114,14 +110,18 @@ class BasicWizardDemo extends React.Component { import React from 'react'; import { Button, + Drawer, DrawerActions, DrawerCloseButton, + DrawerContent, DrawerPanelContent, DrawerHead, Modal, - ModalVariant + ModalVariant, + Wizard, + WizardHeader, + WizardStep } from '@patternfly/react-core'; -import { Wizard as WizardDeprecated } from '@patternfly/react-core/deprecated'; class WizardModalWithDrawerDemo extends React.Component { constructor(props) { @@ -151,131 +151,30 @@ class WizardModalWithDrawerDemo extends React.Component { render() { const { isDrawerExpanded } = this.state; - const informationPanelContent = ( - - - - Information panel content - - - - - - - ); - - const configSubstepAPanelContent = ( - - - - Configuration substep A content - - - - - - - ); - - const configSubstepBPanelContent = ( - - - - Configuration substep B content - - - - - - - ); - - const additionalPanelContent = ( - - - - Additional panel content - - - - - - - ); - - const reviewPanelContent = ( - - - - Review panel content - - - - - - - ); - - const drawerToggleButton = ( - - ); - - const steps = [ - { - id: 0, - name: 'Information', - component:

Step 1 content

, - drawerPanelContent: informationPanelContent, - drawerToggleButton: drawerToggleButton - }, - { - id: 1, - name: 'Configuration', - steps: [ - { - id: 2, - name: 'Substep A', - component:

Configuration substep A

, - drawerPanelContent: configSubstepAPanelContent, - drawerToggleButton: drawerToggleButton - }, - { - id: 3, - name: 'Substep B', - component:

Configuration substep B

, - drawerPanelContent: configSubstepBPanelContent, - drawerToggleButton: drawerToggleButton + const createStepContentWithDrawer = (stepName) => ( + + + + + Drawer content: {stepName} + + + + + + } - ] - }, - { - id: 4, - name: 'Additional', - component:

Step 3 content

, - drawerPanelContent: additionalPanelContent, - drawerToggleButton: drawerToggleButton - }, - { - id: 5, - name: 'Review', - component:

Review step content

, - drawerPanelContent: reviewPanelContent, - drawerToggleButton: drawerToggleButton, - nextButtonText: 'Finish' - } - ]; - const title = 'Wizard modal with Drawer'; - - const panelContent = ( - - - - drawer-panel - - - + > + {!isDrawerExpanded && ( + + )} +
{stepName} content
+
+
); return ( @@ -287,19 +186,32 @@ class WizardModalWithDrawerDemo extends React.Component { aria-describedby="wiz-modal-demo-description" aria-labelledby="wiz-modal-demo-title" > - } height={400} - /> + > + + {createStepContentWithDrawer('Information step')} + + + {createStepContentWithDrawer('Configuration substep A')} + , + + {createStepContentWithDrawer('Configuration substep B')} + + ]} + /> + + {createStepContentWithDrawer('Additional step')} + + + {createStepContentWithDrawer('Review step')} + + ); } @@ -312,18 +224,22 @@ class WizardModalWithDrawerDemo extends React.Component { import React from 'react'; import { Button, + Drawer, DrawerActions, DrawerCloseButton, + DrawerContent, DrawerPanelContent, DrawerHead, Modal, ModalVariant, Text, - TextContent + TextContent, + Wizard, + WizardHeader, + WizardStep } from '@patternfly/react-core'; -import { Wizard as WizardDeprecated } from '@patternfly/react-core/deprecated'; -class WizardModalWithDrawerDemo extends React.Component { +class WizardModalWithDrawerInfoStepDemo extends React.Component { constructor(props) { super(props); this.state = { @@ -351,84 +267,24 @@ class WizardModalWithDrawerDemo extends React.Component { render() { const { isDrawerExpanded } = this.state; - const informationPanelContent = ( - - - - Information panel content - - - - - - - ); - - const configSubstepAPanelContent = ( - - - - Configuration substep A content - - - - - - - ); - - const configSubstepBPanelContent = ( - - - - Configuration substep B content - - - - - - - ); - - const additionalPanelContent = ( - - - - Additional panel content - - - - - - - ); - - const reviewPanelContent = ( - - - - Review panel content - - - - - - - ); - - const drawerToggleButton = ( - - ); - - const steps = [ - { - id: 0, - name: 'Information', - component: ( + const createStepContentWithDrawer = (stepName) => ( + + + + + Drawer content: {stepName} + + + + + + + } + > - Information step content + {stepName} content

Wizard description goes here. If you need more assistance,{' '} - in the side drawer. -

-
- ), - drawerPanelContent: configSubstepAPanelContent - }, - { - id: 3, - name: 'Substep B', - component: ( - - Configuration substep B content -

- Wizard description goes here. If you need more assistance, - - in the side drawer. -

-
- ), - drawerPanelContent: configSubstepBPanelContent - } - ] - }, - { - id: 4, - name: 'Additional', - component: ( - - Additional step content -

- Wizard description goes here. If you need more assistance, - - in the side drawer. -

-
- ), - drawerPanelContent: additionalPanelContent - }, - { - id: 5, - name: 'Review', - component: ( - - Review step content -

- Wizard description goes here. If you need more assistance, - - in the side drawer. -

-
- ), - nextButtonText: 'Finish', - drawerPanelContent: reviewPanelContent - } - ]; - - const title = 'Wizard modal with Drawer'; - - const panelContent = ( - - - - drawer-panel - - - +
+
); return ( @@ -538,19 +306,34 @@ class WizardModalWithDrawerDemo extends React.Component { aria-describedby="wiz-modal-demo-description" aria-labelledby="wiz-modal-demo-title" > - + } height={400} - /> + > + + {createStepContentWithDrawer('Information step')} + + + {createStepContentWithDrawer('Configuration substep A')} + , + + {createStepContentWithDrawer('Configuration substep B')} + + ]} + /> + + {createStepContentWithDrawer('Additional step')} + + + {createStepContentWithDrawer('Review step')} + + ); } @@ -561,14 +344,7 @@ class WizardModalWithDrawerDemo extends React.Component { ```js isFullscreen import React from 'react'; -import { - Nav, - NavItem, - NavList, - PageSection, - PageSectionTypes, - PageSectionVariants -} from '@patternfly/react-core'; +import { Nav, NavItem, NavList, PageSection, PageSectionTypes, PageSectionVariants } from '@patternfly/react-core'; import { Wizard as WizardDeprecated } from '@patternfly/react-core/deprecated'; import imgBrand from './imgBrand.svg'; import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; @@ -580,7 +356,7 @@ class FullPageWizard extends React.Component { this.state = { activeItem: 0 }; - this.onNavSelect = result => { + this.onNavSelect = (result) => { this.setState({ activeItem: result.itemId }); @@ -687,7 +463,7 @@ class FullPageWizard extends React.Component { isDrawerExpanded: false }); }; - this.onNavSelect = result => { + this.onNavSelect = (result) => { this.setState({ activeItem: result.itemId }); @@ -955,7 +731,7 @@ class FullPageWizard extends React.Component { isDrawerExpanded: false }); }; - this.onNavSelect = result => { + this.onNavSelect = (result) => { this.setState({ activeItem: result.itemId }); From 74366a75cc684608146a2fa7a8d47d0ba38b6002 Mon Sep 17 00:00:00 2001 From: Eric Olkowski Date: Tue, 18 Apr 2023 16:08:34 -0400 Subject: [PATCH 2/5] Updated non-modal demos --- .../react-core/src/demos/Wizard/WizardDemo.md | 476 ++++++------------ 1 file changed, 145 insertions(+), 331 deletions(-) diff --git a/packages/react-core/src/demos/Wizard/WizardDemo.md b/packages/react-core/src/demos/Wizard/WizardDemo.md index 4e87cfef88c..77ec6137f35 100644 --- a/packages/react-core/src/demos/Wizard/WizardDemo.md +++ b/packages/react-core/src/demos/Wizard/WizardDemo.md @@ -197,18 +197,18 @@ class WizardModalWithDrawerDemo extends React.Component { name="Configuration" id="wizard-step-2" steps={[ - + {createStepContentWithDrawer('Configuration substep A')} , - + {createStepContentWithDrawer('Configuration substep B')} ]} /> - + {createStepContentWithDrawer('Additional step')} - + {createStepContentWithDrawer('Review step')} @@ -319,18 +319,18 @@ class WizardModalWithDrawerInfoStepDemo extends React.Component { name="Configuration" id="wizard-step-2" steps={[ - + {createStepContentWithDrawer('Configuration substep A')} , - + {createStepContentWithDrawer('Configuration substep B')} ]} /> - + {createStepContentWithDrawer('Additional step')} - + {createStepContentWithDrawer('Review step')} @@ -344,13 +344,21 @@ class WizardModalWithDrawerInfoStepDemo extends React.Component { ```js isFullscreen import React from 'react'; -import { Nav, NavItem, NavList, PageSection, PageSectionTypes, PageSectionVariants } from '@patternfly/react-core'; -import { Wizard as WizardDeprecated } from '@patternfly/react-core/deprecated'; +import { + Nav, + NavItem, + NavList, + PageSection, + PageSectionTypes, + PageSectionVariants, + Wizard, + WizardStep +} from '@patternfly/react-core'; import imgBrand from './imgBrand.svg'; import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; import DashboardWrapper from '@patternfly/react-core/src/demos/examples/DashboardWrapper'; -class FullPageWizard extends React.Component { +class WizardFullPage extends React.Component { constructor(props) { super(props); this.state = { @@ -365,35 +373,33 @@ class FullPageWizard extends React.Component { render() { const { activeItem } = this.state; - const steps = [ - { id: 0, name: 'Information', component:

Step 1 content

}, - { - id: 1, - name: 'Configuration', - steps: [ - { - id: 2, - name: 'Substep A', - component:

Configuration substep A

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

Configuration substep B

- } - ], - component:

Step 2 content

- }, - { id: 4, name: 'Additional', component:

Step 3 content

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

Review step content

, nextButtonText: 'Finish' } - ]; - const title = 'Basic wizard'; - return ( - + + +

Step 1 content

+
+ +

Configuration substep A

+
, + +

Configuration substep B

+
+ ]} + /> + +

Step 3 content

+
+ +

Review step content

+
+
@@ -411,10 +417,12 @@ import { Breadcrumb, BreadcrumbItem, Button, + Drawer, DrawerActions, DrawerCloseButton, - DrawerHead, + DrawerContent, DrawerPanelContent, + DrawerHead, Nav, NavItem, NavList, @@ -432,13 +440,14 @@ import { PageToggleButton, MastheadToggle, MastheadMain, - MastheadBrand + MastheadBrand, + Wizard, + WizardStep } from '@patternfly/react-core'; -import { Wizard as WizardDeprecated } from '@patternfly/react-core/deprecated'; import imgBrand from './imgBrand.svg'; import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; -class FullPageWizard extends React.Component { +class WizardFullPageWithDrawerDemo extends React.Component { constructor(props) { super(props); this.state = { @@ -520,122 +529,31 @@ class FullPageWizard extends React.Component { ); - const informationPanelContent = ( - - - - Information panel content - - - - - - - ); - - const configSubstepAPanelContent = ( - - - - Configuration substep A content - - - - - - - ); - - const configSubstepBPanelContent = ( - - - - Configuration substep B content - - - - - - - ); - - const additionalPanelContent = ( - - - - Additional panel content - - - - - - - ); - - const reviewPanelContent = ( - - - - Review panel content - - - - - - - ); - - const drawerToggleButton = ( - - ); - - const steps = [ - { - id: 0, - name: 'Information', - component:

Step 1 content

, - drawerPanelContent: informationPanelContent, - drawerToggleButton: drawerToggleButton - }, - { - id: 1, - name: 'Configuration', - steps: [ - { - id: 2, - name: 'Substep A', - component:

Configuration substep A

, - drawerPanelContent: configSubstepAPanelContent, - drawerToggleButton: drawerToggleButton - }, - { - id: 3, - name: 'Substep B', - component:

Configuration substep B

, - drawerPanelContent: configSubstepBPanelContent, - drawerToggleButton: drawerToggleButton + const createStepContentWithDrawer = (stepName) => ( + + + + + Drawer content: {stepName} + + + + + + } - ] - }, - { - id: 4, - name: 'Additional', - component:

Step 3 content

, - drawerPanelContent: additionalPanelContent, - drawerToggleButton: drawerToggleButton - }, - { - id: 5, - name: 'Review', - component:

Review step content

, - nextButtonText: 'Finish', - drawerPanelContent: reviewPanelContent, - drawerToggleButton: drawerToggleButton - } - ]; - const title = 'Basic wizard'; + > + {!isDrawerExpanded && ( + + )} +
{stepName} content
+
+
+ ); return ( @@ -654,14 +572,29 @@ class FullPageWizard extends React.Component { - + + + {createStepContentWithDrawer('Information step')} + + + {createStepContentWithDrawer('Configuration substep A')} + , + + {createStepContentWithDrawer('Configuration substep B')} + + ]} + /> + + {createStepContentWithDrawer('Additional step')} + + + {createStepContentWithDrawer('Review step')} + + @@ -679,8 +612,10 @@ import { Breadcrumb, BreadcrumbItem, Button, + Drawer, DrawerActions, DrawerCloseButton, + DrawerContent, DrawerHead, DrawerPanelContent, Nav, @@ -700,13 +635,14 @@ import { PageToggleButton, MastheadToggle, MastheadMain, - MastheadBrand + MastheadBrand, + Wizard, + WizardStep } from '@patternfly/react-core'; -import { Wizard as WizardDeprecated } from '@patternfly/react-core/deprecated'; import imgBrand from './imgBrand.svg'; import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; -class FullPageWizard extends React.Component { +class WizardFullPageWithDrawerInfoStepDemo extends React.Component { constructor(props) { super(props); this.state = { @@ -788,84 +724,24 @@ class FullPageWizard extends React.Component { ); - const informationPanelContent = ( - - - - Information panel content - - - - - - - ); - - const configSubstepAPanelContent = ( - - - - Configuration substep A content - - - - - - - ); - - const configSubstepBPanelContent = ( - - - - Configuration substep B content - - - - - - - ); - - const additionalPanelContent = ( - - - - Additional panel content - - - - - - - ); - - const reviewPanelContent = ( - - - - Review panel content - - - - - - - ); - - const drawerToggleButton = ( - - ); - - const steps = [ - { - id: 0, - name: 'Information', - component: ( + const createStepContentWithDrawer = (stepName) => ( + + + + + Drawer content: {stepName} + + + + + + + } + > - Information step content + {stepName} content

Wizard description goes here. If you need more assistance,{' '} - in the side drawer. -

-
- ), - drawerPanelContent: configSubstepAPanelContent - }, - { - id: 3, - name: 'Substep B', - component: ( - - Configuration substep B content -

- Wizard description goes here. If you need more assistance, - - in the side drawer. -

-
- ), - drawerPanelContent: configSubstepBPanelContent - } - ] - }, - { - id: 4, - name: 'Additional', - component: ( - - Additional step content -

- Wizard description goes here. If you need more assistance, - - in the side drawer. -

-
- ), - drawerPanelContent: additionalPanelContent - }, - { - id: 5, - name: 'Review', - component: ( - - Review step content -

- Wizard description goes here. If you need more assistance, - - in the side drawer. -

-
- ), - nextButtonText: 'Finish', - drawerPanelContent: reviewPanelContent - } - ]; - const title = 'Basic wizard'; +
+
+ ); return ( @@ -972,14 +771,29 @@ class FullPageWizard extends React.Component { - + + + {createStepContentWithDrawer('Information step')} + + + {createStepContentWithDrawer('Configuration substep A')} + , + + {createStepContentWithDrawer('Configuration substep B')} + + ]} + /> + + {createStepContentWithDrawer('Additional step')} + + + {createStepContentWithDrawer('Review step')} + + From f2ecd99e3a0dc8a9b3929c54a32e17ce96e78a70 Mon Sep 17 00:00:00 2001 From: Eric Olkowski Date: Wed, 19 Apr 2023 09:34:43 -0400 Subject: [PATCH 3/5] Updated integration tests --- .../cypress/integration/wizard.spec.ts | 46 ++-- .../integration/wizarddeprecated.spec.ts | 43 ++++ .../demo-app-ts/src/Demos.ts | 5 + .../demos/WizardDemo/WizardDemo.tsx | 239 ++++++++++-------- .../WizardDeprecatedDemo.tsx | 142 +++++++++++ .../demo-app-ts/src/components/demos/index.ts | 8 +- 6 files changed, 354 insertions(+), 129 deletions(-) create mode 100644 packages/react-integration/cypress/integration/wizarddeprecated.spec.ts create mode 100644 packages/react-integration/demo-app-ts/src/components/demos/WizardDeprecatedDemo/WizardDeprecatedDemo.tsx diff --git a/packages/react-integration/cypress/integration/wizard.spec.ts b/packages/react-integration/cypress/integration/wizard.spec.ts index 027dbf5603d..6454874f1af 100644 --- a/packages/react-integration/cypress/integration/wizard.spec.ts +++ b/packages/react-integration/cypress/integration/wizard.spec.ts @@ -6,7 +6,7 @@ describe('Wizard Demo Test', () => { it('Verify wizard in modal launches in a dialog and has a custom width', () => { cy.get('#launchWiz').click(); cy.get('#modalWizId.pf-c-wizard').should('exist'); - cy.get('.pf-c-modal-box').should('have.attr', 'style', 'width: 710px;'); + cy.get('#modalWizId.pf-c-wizard').should('have.attr', 'style', 'width: 710px;'); cy.focused().click(); }); @@ -21,27 +21,31 @@ describe('Wizard Demo Test', () => { cy.get('#inPageWizId.pf-c-wizard').should('exist'); }); - it('Verify wizard step content is focusable only if content overflows', () => { - cy.get('#wizard-focusable-overflow .pf-c-wizard__main').should('not.have.attr', 'tabindex'); - cy.get('#wizard-focusable-overflow .pf-c-wizard__main').click(); - cy.get('#wizard-focusable-overflow .pf-c-wizard__main').should('not.have.focus'); - cy.get('#wizard-focusable-overflow button.pf-c-wizard__nav-link') - .last() - .click(); - cy.get('#wizard-focusable-overflow .pf-c-wizard__main').should('have.attr', 'tabindex'); - cy.get('#wizard-focusable-overflow .pf-c-wizard__main').click(); - cy.get('#wizard-focusable-overflow .pf-c-wizard__main').should('have.focus'); + it('Verify in-page wizard step content is focusable and has role only if content overflows', () => { + cy.get('#inPageWizWithOverflow .pf-c-wizard__main').should('not.have.attr', 'tabindex'); + cy.get('#inPageWizWithOverflow .pf-c-wizard__main').should('not.have.attr', 'role'); + cy.get('#inPageWizWithOverflow .pf-c-wizard__main').click(); + cy.get('#inPageWizWithOverflow .pf-c-wizard__main').should('not.have.focus'); + cy.get('#inPageWizWithOverflow button.pf-c-wizard__nav-link').last().click(); + cy.get('#inPageWizWithOverflow .pf-c-wizard__main').should('have.attr', 'tabindex'); + cy.get('#inPageWizWithOverflow .pf-c-wizard__main').should('have.attr', 'role').and('eq', 'region'); + cy.get('#inPageWizWithOverflow .pf-c-wizard__main').click(); + cy.get('#inPageWizWithOverflow .pf-c-wizard__main').should('have.focus'); }); - it('Verify role attribute is applied correctly', () => { - cy.get('#wizard-correct-role .pf-c-wizard__main').should('not.have.attr', 'role'); - cy.get('#wizard-correct-role button.pf-c-wizard__nav-link') - .last() - .click(); - cy.get('#wizard-correct-role .pf-c-wizard__main').should('have.attr', 'role'); - cy.get('#wizard-correct-role .pf-c-wizard__main button').click(); - // Within a modal, wizard body uses the
element and should not have a role applied - cy.get('#wizard-correct-role .pf-c-wizard__main').should('not.have.attr', 'role'); - cy.get('#wizard-correct-role .pf-c-wizard__close').click(); + it('Verify modal wizard step content with main element is focusable only if content overflows', () => { + cy.get('#launchWizOverflow').click(); + cy.get('#inModalWizWithOverflow.pf-c-wizard').should('exist'); + cy.get('#inModalWizWithOverflow .pf-c-wizard__main').should('not.have.attr', 'tabindex'); + cy.get('#inModalWizWithOverflow .pf-c-wizard__main').should('not.have.attr', 'role'); + cy.get('#inModalWizWithOverflow .pf-c-wizard__main').click(); + cy.get('#inModalWizWithOverflow .pf-c-wizard__main').should('not.have.focus'); + cy.get('#inModalWizWithOverflow button.pf-c-wizard__nav-link').last().click(); + cy.get('#inModalWizWithOverflow main.pf-c-wizard__main').should('exist'); + cy.get('#inModalWizWithOverflow main.pf-c-wizard__main').should('have.attr', 'tabindex'); + // When WizardBody component is not a div, it should not have a role applied + cy.get('#inModalWizWithOverflow main.pf-c-wizard__main').should('not.have.attr', 'role'); + cy.get('#inModalWizWithOverflow main.pf-c-wizard__main').click(); + cy.get('#inModalWizWithOverflow main.pf-c-wizard__main').should('have.focus'); }); }); diff --git a/packages/react-integration/cypress/integration/wizarddeprecated.spec.ts b/packages/react-integration/cypress/integration/wizarddeprecated.spec.ts new file mode 100644 index 00000000000..c32a1d91c86 --- /dev/null +++ b/packages/react-integration/cypress/integration/wizarddeprecated.spec.ts @@ -0,0 +1,43 @@ +describe('Wizard Deprecated Demo Test', () => { + it('Navigate to demo section', () => { + cy.visit('http://localhost:3000/wizard-deprecated-demo-nav-link'); + }); + + it('Verify wizard in modal launches in a dialog and has a custom width', () => { + cy.get('#launchWiz').click(); + cy.get('#modalWizId.pf-c-wizard').should('exist'); + cy.get('.pf-c-modal-box').should('have.attr', 'style', 'width: 710px;'); + cy.focused().click(); + }); + + it('Verify wizard in modal sends focus to the new content', () => { + cy.get('#launchWiz').click(); + cy.get('#modalWizId.pf-c-wizard').should('exist'); + cy.focused().should('have.class', 'pf-c-wizard__close'); + cy.focused().click(); + }); + + it('Verify in page wizard displays on page render', () => { + cy.get('#inPageWizId.pf-c-wizard').should('exist'); + }); + + it('Verify wizard step content is focusable only if content overflows', () => { + cy.get('#wizard-focusable-overflow .pf-c-wizard__main').should('not.have.attr', 'tabindex'); + cy.get('#wizard-focusable-overflow .pf-c-wizard__main').click(); + cy.get('#wizard-focusable-overflow .pf-c-wizard__main').should('not.have.focus'); + cy.get('#wizard-focusable-overflow button.pf-c-wizard__nav-link').last().click(); + cy.get('#wizard-focusable-overflow .pf-c-wizard__main').should('have.attr', 'tabindex'); + cy.get('#wizard-focusable-overflow .pf-c-wizard__main').click(); + cy.get('#wizard-focusable-overflow .pf-c-wizard__main').should('have.focus'); + }); + + it('Verify role attribute is applied correctly', () => { + cy.get('#wizard-correct-role .pf-c-wizard__main').should('not.have.attr', 'role'); + cy.get('#wizard-correct-role button.pf-c-wizard__nav-link').last().click(); + cy.get('#wizard-correct-role .pf-c-wizard__main').should('have.attr', 'role'); + cy.get('#wizard-correct-role .pf-c-wizard__main button').click(); + // Within a modal, wizard body uses the
element and should not have a role applied + cy.get('#wizard-correct-role .pf-c-wizard__main').should('not.have.attr', 'role'); + cy.get('#wizard-correct-role .pf-c-wizard__close').click(); + }); +}); diff --git a/packages/react-integration/demo-app-ts/src/Demos.ts b/packages/react-integration/demo-app-ts/src/Demos.ts index 3e9b9d9ad96..638f4410a72 100644 --- a/packages/react-integration/demo-app-ts/src/Demos.ts +++ b/packages/react-integration/demo-app-ts/src/Demos.ts @@ -511,6 +511,11 @@ export const Demos: DemoInterface[] = [ id: 'wizard-demo', name: 'Wizard Demo', componentType: Examples.WizardDemo + }, + { + id: 'wizard-deprecated-demo', + name: 'Wizard Deprecated Demo', + componentType: Examples.WizardDeprecatedDemo } ]; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/WizardDemo/WizardDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/WizardDemo/WizardDemo.tsx index 35c8c31ebc3..7211e39f757 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/WizardDemo/WizardDemo.tsx +++ b/packages/react-integration/demo-app-ts/src/components/demos/WizardDemo/WizardDemo.tsx @@ -1,6 +1,7 @@ -import { Button } from '@patternfly/react-core'; -import { Wizard, WizardStep } from '@patternfly/react-core/deprecated' import React from 'react'; +import { Button, Modal, Wizard, WizardHeader, WizardStep } 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'; interface WizardDemoState { isOpen: boolean; @@ -28,114 +29,144 @@ export class WizardDemo extends React.Component, } render() { - const steps: WizardStep[] = [ - { name: 'A', component:

Step 1

}, - { - name: 'B', - steps: [ - { - name: 'B-1', - component:

Step 2

, - enableNext: true - }, - { - name: 'B-2', - component:

Step 3

, - enableNext: false, - canJumpTo: false - } - ] - }, - { name: 'C', component:

Step 4

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

Step 5

} - ]; - const stepsWithAnchorLinks: WizardStep[] = [ - { - name: 'Read about PF3', - component:

Step 1

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

Step 2

, - stepNavItemProps: { navItemComponent: 'a', href: 'https://www.patternfly.org/v4/', target: '_blank' } - }, - { - name: 'Review', - component:

Step 3

, - stepNavItemProps: { navItemComponent: 'button', href: 'hhttps://www.patternfly.org/v4/' } - } - ]; + const { isOpen, isOpenWithRole } = this.state; - const stepsOnOverflow: WizardStep[] = [ - { - name: 'Step without overflow', - component:

Step 1

- }, - { - name: 'Step with overflow', - component: ( -
-

Step 2

- -
- ) - } - ]; return ( - - - - - + + + } + > + +

Step 1

+
+ +

Step 2

+
, + +

Step 3

+
+ ]} + /> + +

Step 4

+
+ +

Step 5

+
+
+
+ + +

Step 1

+
+ +

Step 2

+
, + +

Step 3

+
+ ]} + /> + +

Step 4

+
+ +

Step 5

+
+
+ + + Read about PF3 + + } + id="wizard-anchor-pf3" + navItem={{ component: 'a', href: 'https://www.patternfly.org/v3', target: '_blank' }} + > +

Step 1

+
+ + Read about PF4 + + } + id="wizard-anchor-pf4" + navItem={{ component: 'a', href: 'https://www.patternfly.org/v4', target: '_blank' }} + > +

Step 2

+
+ + Join us on Slack + + } + id="wizard-anchor-slack" + navItem={{ component: 'a', href: 'https://patternfly.slack.com', target: '_blank' }} + > +

Step 3

+
+
+ + +

Step 1

+
+ +
+

Step 2

+
+
+
+ + + + } + > + +

Step 1

+
+ +
+

Step 2

+
+
+
+
); } diff --git a/packages/react-integration/demo-app-ts/src/components/demos/WizardDeprecatedDemo/WizardDeprecatedDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/WizardDeprecatedDemo/WizardDeprecatedDemo.tsx new file mode 100644 index 00000000000..a090bfca972 --- /dev/null +++ b/packages/react-integration/demo-app-ts/src/components/demos/WizardDeprecatedDemo/WizardDeprecatedDemo.tsx @@ -0,0 +1,142 @@ +import { Button } from '@patternfly/react-core'; +import { Wizard, WizardStep } from '@patternfly/react-core/deprecated'; +import React from 'react'; + +interface WizardDeprecatedDemoState { + isOpen: boolean; + isOpenWithRole: boolean; +} + +export class WizardDeprecatedDemo extends React.Component, WizardDeprecatedDemoState> { + static displayName = 'WizardDemo'; + state = { + isOpen: false, + isOpenWithRole: false + }; + + handleModalToggle = () => { + this.setState(({ isOpen }) => ({ + isOpen: !isOpen + })); + }; + + handleRoleWizardToggle = () => { + this.setState(({ isOpenWithRole }) => ({ isOpenWithRole: !isOpenWithRole })); + }; + componentDidMount() { + window.scrollTo(0, 0); + } + + render() { + const steps: WizardStep[] = [ + { name: 'A', component:

Step 1

}, + { + name: 'B', + steps: [ + { + name: 'B-1', + component:

Step 2

, + enableNext: true + }, + { + name: 'B-2', + component:

Step 3

, + enableNext: false, + canJumpTo: false + } + ] + }, + { name: 'C', component:

Step 4

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

Step 5

} + ]; + const stepsWithAnchorLinks: WizardStep[] = [ + { + name: 'Read about PF3', + component:

Step 1

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

Step 2

, + stepNavItemProps: { navItemComponent: 'a', href: 'https://www.patternfly.org/v4/', target: '_blank' } + }, + { + name: 'Review', + component:

Step 3

, + stepNavItemProps: { navItemComponent: 'button', href: 'hhttps://www.patternfly.org/v4/' } + } + ]; + + const stepsOnOverflow: WizardStep[] = [ + { + name: 'Step without overflow', + component:

Step 1

+ }, + { + name: 'Step with overflow', + component: ( +
+

Step 2

+ +
+ ) + } + ]; + return ( + + + + + + + + + ); + } +} diff --git a/packages/react-integration/demo-app-ts/src/components/demos/index.ts b/packages/react-integration/demo-app-ts/src/components/demos/index.ts index 56c861ff4f1..2eadd9a9609 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/index.ts +++ b/packages/react-integration/demo-app-ts/src/components/demos/index.ts @@ -19,10 +19,9 @@ export * from './ClipboardCopyDemo/ClipboardCopyDemo'; export * from './DataListDemo/DataListDemo'; export * from './DataListDemo/DataListDraggableDemo'; export * from './DataListDemo/DataListCompactDemo'; -export * from './ToolbarDemo/ToolbarDemo'; +export * from './DatePickerDemo/DatePickerDemo'; export * from './DescriptionListDemo/DescriptionListDemo'; export * from './DescriptionListDemo/DescriptionListBreakpointsDemo'; -export * from './ToolbarDemo/ToolbarVisibilityDemo'; export * from './DrawerDemo/DrawerDemo'; export * from './DrawerDemo/DrawerResizeDemo'; export * from './DropdownDeprecatedDemo/DropdownDeprecatedDemo'; @@ -35,6 +34,7 @@ export * from './ExpandableSectionDemo/ExpandableSectionTruncateDemo'; export * from './FileUploadDemo/FileUploadDemo'; export * from './FormDemo/FormDemo'; export * from './InputGroupDemo/InputGroupDemo'; +export * from './JumpLinksDemo/JumpLinksDemo'; export * from './LabelDemo/LabelDemo'; export * from './LabelGroupDemo/LabelGroupEditableDemo'; export * from './LabelGroupDemo/LabelGroupVerticalDemo'; @@ -94,8 +94,8 @@ export * from './TextAreaDemo/TextAreaDemo'; export * from './TextInputDemo/TextInputDemo'; export * from './ToggleGroupDemo/ToggleGroupDemo'; export * from './ToolbarDemo/ToolbarDemo'; +export * from './ToolbarDemo/ToolbarVisibilityDemo'; export * from './TooltipDemo/TooltipDemo'; export * from './TreeViewDemo/TreeViewDemo'; export * from './WizardDemo/WizardDemo'; -export * from './JumpLinksDemo/JumpLinksDemo'; -export * from './DatePickerDemo/DatePickerDemo'; +export * from './WizardDeprecatedDemo/WizardDeprecatedDemo'; From 6111614ceb766345efc12e7fde2b0c365ec9865f Mon Sep 17 00:00:00 2001 From: Eric Olkowski Date: Wed, 19 Apr 2023 11:40:46 -0400 Subject: [PATCH 4/5] Fixed a11y errors --- .../react-core/src/demos/Wizard/WizardDemo.md | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/react-core/src/demos/Wizard/WizardDemo.md b/packages/react-core/src/demos/Wizard/WizardDemo.md index 77ec6137f35..fb368717cdb 100644 --- a/packages/react-core/src/demos/Wizard/WizardDemo.md +++ b/packages/react-core/src/demos/Wizard/WizardDemo.md @@ -72,7 +72,15 @@ class WizardInModalDemo extends React.Component { aria-labelledby="wiz-modal-demo-title" > } + header={ + + } height={400} > @@ -187,7 +195,15 @@ class WizardModalWithDrawerDemo extends React.Component { aria-labelledby="wiz-modal-demo-title" > } + header={ + + } height={400} > @@ -308,7 +324,13 @@ class WizardModalWithDrawerInfoStepDemo extends React.Component { > + } height={400} > From 955d20933a54bd57e072da26bd71157d374b588f Mon Sep 17 00:00:00 2001 From: Eric Olkowski Date: Thu, 20 Apr 2023 09:25:40 -0400 Subject: [PATCH 5/5] Fixed errors and unused imports --- .../react-core/src/demos/Wizard/WizardDemo.md | 55 +++---------------- 1 file changed, 8 insertions(+), 47 deletions(-) diff --git a/packages/react-core/src/demos/Wizard/WizardDemo.md b/packages/react-core/src/demos/Wizard/WizardDemo.md index fb368717cdb..1aa820fdc87 100644 --- a/packages/react-core/src/demos/Wizard/WizardDemo.md +++ b/packages/react-core/src/demos/Wizard/WizardDemo.md @@ -7,7 +7,6 @@ source: react-demos import imgBrand from './imgBrand.svg'; import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; import DashboardWrapper from '@patternfly/react-core/src/demos/examples/DashboardWrapper'; -import { Wizard as WizardDeprecated } from '@patternfly/react-core/deprecated'; ## Demos @@ -20,9 +19,6 @@ import { CardBody, Gallery, GalleryItem, - Nav, - NavItem, - NavList, PageSection, Modal, ModalVariant, @@ -35,19 +31,9 @@ import DashboardWrapper from '@patternfly/react-core/src/demos/examples/Dashboar class WizardInModalDemo extends React.Component { constructor(props) { super(props); - this.state = { - activeItem: 0 - }; - this.onNavSelect = (result) => { - this.setState({ - activeItem: result.itemId - }); - }; } - render() { - const { activeItem } = this.state; - const title = 'Basic wizard'; + render() { return ( @@ -101,7 +87,7 @@ class WizardInModalDemo extends React.Component {

Step 3 content

- +

Review step content

@@ -224,7 +210,7 @@ class WizardModalWithDrawerDemo extends React.Component { {createStepContentWithDrawer('Additional step')} - + {createStepContentWithDrawer('Review step')}
@@ -352,7 +338,7 @@ class WizardModalWithDrawerInfoStepDemo extends React.Component { {createStepContentWithDrawer('Additional step')} - + {createStepContentWithDrawer('Review step')}
@@ -366,35 +352,14 @@ class WizardModalWithDrawerInfoStepDemo extends React.Component { ```js isFullscreen import React from 'react'; -import { - Nav, - NavItem, - NavList, - PageSection, - PageSectionTypes, - PageSectionVariants, - Wizard, - WizardStep -} from '@patternfly/react-core'; -import imgBrand from './imgBrand.svg'; -import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; +import { PageSection, PageSectionTypes, PageSectionVariants, Wizard, WizardStep } from '@patternfly/react-core'; import DashboardWrapper from '@patternfly/react-core/src/demos/examples/DashboardWrapper'; class WizardFullPage extends React.Component { constructor(props) { super(props); - this.state = { - activeItem: 0 - }; - this.onNavSelect = (result) => { - this.setState({ - activeItem: result.itemId - }); - }; } render() { - const { activeItem } = this.state; - return ( @@ -418,7 +383,7 @@ class WizardFullPage extends React.Component {

Step 3 content

- +

Review step content

@@ -453,11 +418,9 @@ import { PageSectionTypes, PageSectionVariants, PageSidebar, - Progress, SkipToContent, Text, TextContent, - Title, Masthead, PageToggleButton, MastheadToggle, @@ -613,7 +576,7 @@ class WizardFullPageWithDrawerDemo extends React.Component { {createStepContentWithDrawer('Additional step')} - + {createStepContentWithDrawer('Review step')} @@ -648,11 +611,9 @@ import { PageSectionTypes, PageSectionVariants, PageSidebar, - Progress, SkipToContent, Text, TextContent, - Title, Masthead, PageToggleButton, MastheadToggle, @@ -812,7 +773,7 @@ class WizardFullPageWithDrawerInfoStepDemo extends React.Component { {createStepContentWithDrawer('Additional step')} - + {createStepContentWithDrawer('Review step')}