diff --git a/packages/react-core/src/components/Alert/AlertActionLink.tsx b/packages/react-core/src/components/Alert/AlertActionLink.tsx index f4a54d124f0..b881e861fd9 100644 --- a/packages/react-core/src/components/Alert/AlertActionLink.tsx +++ b/packages/react-core/src/components/Alert/AlertActionLink.tsx @@ -6,8 +6,8 @@ import { Button, ButtonVariant, ButtonProps } from '../Button'; */ export interface AlertActionLinkProps extends ButtonProps { - /** Content rendered inside the alert action link. */ - children?: string; + /** Content rendered inside the alert action link. Interactive content such as anchor elements should not be passed in. */ + children?: React.ReactNode; /** Additional classes added to the alert action link. */ className?: string; } diff --git a/packages/react-core/src/components/Alert/__tests__/AlertActionLink.test.tsx b/packages/react-core/src/components/Alert/__tests__/AlertActionLink.test.tsx index 49f06bd1cce..3e22ee03c5e 100644 --- a/packages/react-core/src/components/Alert/__tests__/AlertActionLink.test.tsx +++ b/packages/react-core/src/components/Alert/__tests__/AlertActionLink.test.tsx @@ -20,6 +20,18 @@ test('Renders children', () => { expect(screen.getByRole('button')).toBeVisible(); }); +test('Renders ReactNode as children', () => { + render( + +
+ Learn More +
+
+ ); + + expect(screen.getByText('Learn More')).toBeVisible(); +}); + test('Renders with custom class names provided via prop', () => { render(Test); diff --git a/packages/react-core/src/components/Card/__tests__/CardSelectableActions.test.tsx b/packages/react-core/src/components/Card/__tests__/CardSelectableActions.test.tsx new file mode 100644 index 00000000000..f07d0e95c3e --- /dev/null +++ b/packages/react-core/src/components/Card/__tests__/CardSelectableActions.test.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { CardSelectableActions } from '../CardSelectableActions'; + +test('Matches the snapshot', () => { + const { asFragment } = render(Test); + expect(asFragment()).toMatchSnapshot(); +}); + +test('Renders without children', () => { + render(); + + expect(screen.getByTestId('card-selectable-actions')).toBeVisible(); +}); + +test('Renders children', () => { + render(Test); + + expect(screen.getByText('Test')).toBeVisible(); +}); + +test('Renders with class name pf-v5-c-card__selectable-actions', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('pf-v5-c-card__selectable-actions'); +}); + +test('Renders with custom class names provided via prop', () => { + render(Test); + + expect(screen.getByText('Test')).toHaveClass('test-class'); +}); diff --git a/packages/react-core/src/components/Card/__tests__/__snapshots__/CardSelectableActions.test.tsx.snap b/packages/react-core/src/components/Card/__tests__/__snapshots__/CardSelectableActions.test.tsx.snap new file mode 100644 index 00000000000..d3c07ec4969 --- /dev/null +++ b/packages/react-core/src/components/Card/__tests__/__snapshots__/CardSelectableActions.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
+ Test +
+
+`; diff --git a/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx index 3c21de56481..c01022d93cb 100644 --- a/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx +++ b/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx @@ -22,7 +22,11 @@ test('renders dropdown', () => { }); test('passes children', () => { - render( toggle(toggleRef)}>{dropdownChildren}); + render( + toggle(toggleRef)}> + {dropdownChildren} + + ); expect(screen.getByText('Dropdown children')).toBeVisible(); }); @@ -112,7 +116,7 @@ test('passes zIndex to popper', () => { test('does not pass isOpen to popper by default', () => { render( toggle(toggleRef)}>{dropdownChildren}); - expect(screen.getByText('isOpen: undefined')).toBeVisible(); + expect(screen.getByText('isVisible: undefined')).toBeVisible(); }); test('passes isOpen to popper', () => { @@ -122,7 +126,7 @@ test('passes isOpen to popper', () => { ); - expect(screen.getByText('isOpen: true')).toBeVisible(); + expect(screen.getByText('isVisible: true')).toBeVisible(); }); /* no default tests for callback props @@ -134,7 +138,7 @@ test('passes onSelect callback', async () => { const onSelect = jest.fn(); render( - toggle(toggleRef)}> + toggle(toggleRef)}> {dropdownChildren} ); diff --git a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap index 902d054c70b..c2da5ee3693 100644 --- a/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap +++ b/packages/react-core/src/components/Dropdown/__tests__/__snapshots__/Dropdown.test.tsx.snap @@ -2,40 +2,62 @@ exports[`match snapshot 1`] = ` -
+
-
+
- Dropdown children +
+ Dropdown children +
+
+ Mock item +
+

+ isPlain: true +

+

+ isScrollable: true +

+

+ minWidth: undefined +

-
- Mock item -

- isPlain: true + zIndex: 9999 +

+

+ isVisible: true +

+

+ enableFlip: undefined

- isScrollable: true + placement: undefined +

+

+ appendTo: undefined +

+

+ distance: undefined +

+

+ flipBehavior: undefined

minWidth: undefined

-
-

- zIndex: 9999 -

-

- isOpen: true -

-
diff --git a/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx b/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx index 1607d0de06c..4eb9c2e333f 100644 --- a/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx +++ b/packages/react-core/src/components/ExpandableSection/ExpandableSection.tsx @@ -4,7 +4,7 @@ import { css } from '@patternfly/react-styles'; import lineClamp from '@patternfly/react-tokens/dist/esm/c_expandable_section_m_truncate__content_LineClamp'; import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; import { PickOptional } from '../../helpers/typeUtils'; -import { debounce } from '../../helpers/util'; +import { debounce, getUniqueId } from '../../helpers/util'; import { getResizeObserver } from '../../helpers/resizeObserver'; export enum ExpandableSectionVariant { @@ -23,6 +23,12 @@ export interface ExpandableSectionProps extends React.HTMLProps * property's value should match the contenId property of the expandable section toggle sub-component. */ contentId?: string; + /** Id of the toggle of the expandable section, which provides an accessible name to the + * expandable section content via the aria-labelledby attribute. When the isDetached property + * is also passed in, the value of this property must match the toggleId property of the + * expandable section toggle sub-component. + */ + toggleId?: string; /** Display size variant. Set to "lg" for disclosure styling. */ displaySize?: 'default' | 'lg'; /** Forces active state. */ @@ -102,7 +108,6 @@ export class ExpandableSection extends React.Component onToggle(event, !propOrStateIsExpanded)} > {variant !== ExpandableSectionVariant.truncate && ( @@ -250,7 +268,9 @@ export class ExpandableSection extends React.Component
diff --git a/packages/react-core/src/components/ExpandableSection/ExpandableSectionToggle.tsx b/packages/react-core/src/components/ExpandableSection/ExpandableSectionToggle.tsx index f9f94de0680..ebb416aca45 100644 --- a/packages/react-core/src/components/ExpandableSection/ExpandableSectionToggle.tsx +++ b/packages/react-core/src/components/ExpandableSection/ExpandableSectionToggle.tsx @@ -16,6 +16,10 @@ export interface ExpandableSectionToggleProps extends React.HTMLProps onToggle(!isExpanded)} + id={toggleId} > {!hasTruncatedContent && ( { const { asFragment } = render(test ); @@ -14,7 +14,12 @@ test('ExpandableSection', () => { }); test('Renders ExpandableSection expanded', () => { - const { asFragment } = render( test ); + const { asFragment } = render( + + {' '} + test{' '} + + ); expect(asFragment()).toMatchSnapshot(); }); @@ -29,17 +34,22 @@ test('ExpandableSection onToggle called', async () => { }); test('Renders Uncontrolled ExpandableSection', () => { - const { asFragment } = render( test ); + const { asFragment } = render( + + {' '} + test{' '} + + ); expect(asFragment()).toMatchSnapshot(); }); test('Detached ExpandableSection renders successfully', () => { const { asFragment } = render( - + test - + Toggle text @@ -58,7 +68,7 @@ test('Disclosure ExpandableSection', () => { test('Renders ExpandableSection indented', () => { const { asFragment } = render( - + {' '} test{' '} @@ -67,27 +77,56 @@ test('Renders ExpandableSection indented', () => { }); test('Does not render with pf-m-truncate class when variant is not passed', () => { - render(test); + render(test); expect(screen.getByText('test').parentElement).not.toHaveClass('pf-m-truncate'); }); test('Does not render with pf-m-truncate class when variant is not truncate', () => { + render(test); + + expect(screen.getByText('test').parentElement).not.toHaveClass('pf-m-truncate'); +}); + +test('Renders with pf-m-truncate class when variant is truncate', () => { + render(test); + + expect(screen.getByText('test').parentElement).toHaveClass('pf-m-truncate'); +}); + +test('Renders with value passed to contentId', () => { render( - - test + + Test ); - expect(screen.getByText('test').parentElement).not.toHaveClass('pf-m-truncate'); + const wrapper = screen.getByTestId('test-id'); + const content = wrapper.querySelector('#custom-id'); + expect(content).toBeInTheDocument(); }); -test('Renders with pf-m-truncate class when variant is truncate', () => { +test('Renders with value passed to toggleId', () => { render( - - test + + Test ); - expect(screen.getByText('test').parentElement).toHaveClass('pf-m-truncate'); + const wrapper = screen.getByTestId('test-id'); + const toggle = wrapper.querySelector('#custom-id'); + expect(toggle).toBeVisible(); +}); + +test('Renders with ARIA attributes when contentId and toggleId are passed', () => { + render( + + Test + + ); + + const wrapper = screen.getByTestId('test-id'); + + expect(wrapper).toContainHTML('aria-labelledby="toggle-id"'); + expect(wrapper).toContainHTML('aria-controls="content-id"'); }); diff --git a/packages/react-core/src/components/ExpandableSection/__tests__/__snapshots__/ExpandableSection.test.tsx.snap b/packages/react-core/src/components/ExpandableSection/__tests__/__snapshots__/ExpandableSection.test.tsx.snap index 7fbd3c8aab6..d87bc00aaa6 100644 --- a/packages/react-core/src/components/ExpandableSection/__tests__/__snapshots__/ExpandableSection.test.tsx.snap +++ b/packages/react-core/src/components/ExpandableSection/__tests__/__snapshots__/ExpandableSection.test.tsx.snap @@ -6,8 +6,10 @@ exports[`Detached ExpandableSection renders successfully 1`] = ` class="pf-v5-c-expandable-section pf-m-expanded pf-m-detached" >
test
@@ -16,9 +18,10 @@ exports[`Detached ExpandableSection renders successfully 1`] = ` class="pf-v5-c-expandable-section pf-m-expanded pf-m-detached" > @@ -95,7 +102,9 @@ exports[`ExpandableSection 1`] = ` class="pf-v5-c-expandable-section" > @@ -136,8 +147,10 @@ exports[`Renders ExpandableSection expanded 1`] = ` class="pf-v5-c-expandable-section pf-m-expanded" >
test
@@ -177,8 +192,10 @@ exports[`Renders ExpandableSection indented 1`] = ` class="pf-v5-c-expandable-section pf-m-expanded pf-m-indented" >
test
@@ -218,7 +237,9 @@ exports[`Renders Uncontrolled ExpandableSection 1`] = ` class="pf-v5-c-expandable-section" > diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md index 03be97cc34e..f7f3a30f1d4 100644 --- a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSection.md @@ -12,31 +12,39 @@ import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle ### Basic ```ts file="ExpandableSectionBasic.tsx" + ``` ### Uncontrolled ```ts file="ExpandableSectionUncontrolled.tsx" + ``` ### Uncontrolled with dynamic toggle text ```ts file="ExpandableSectionUncontrolledDynamicToggleText.tsx" + ``` ### Detached +When passing the `isDetached` property into ``, you must also manually pass in the same `toggleId` and `contentId` properties to both `` and ``. This will link the content to the toggle via ARIA attributes. + ```ts file="ExpandableSectionDetached.tsx" + ``` ### Disclosure variation ```ts file="ExpandableSectionDisclosure.tsx" + ``` ### Indented ```ts file="ExpandableSectionIndented.tsx" + ``` ### With custom toggle content @@ -44,6 +52,7 @@ import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle By using the `toggleContent` prop, you can pass in content other than a simple string such as an icon or a badge. When passing in custom content in this way, you should not pass in any interactive element such as a button. ```ts file="ExpandableSectionCustomToggle.tsx" + ``` ### Truncate expansion @@ -51,4 +60,5 @@ By using the `toggleContent` prop, you can pass in content other than a simple s By passing in `variant="truncate"`, the expandable content will be visible up to a maximum number of lines before being truncated, with the toggle revealing or hiding the truncated content. By default the expandable content will truncate after 3 lines, and this can be customized by also passing in the `truncateMaxLines` prop. ```ts file="ExpandableSectionTruncateExpansion.tsx" isBeta + ``` diff --git a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDetached.tsx b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDetached.tsx index 178d62ce82d..bcba03935c2 100644 --- a/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDetached.tsx +++ b/packages/react-core/src/components/ExpandableSection/examples/ExpandableSectionDetached.tsx @@ -8,16 +8,23 @@ export const ExpandableSectionDetached: React.FunctionComponent = () => { setIsExpanded(isExpanded); }; - const contentId = 'detached-toggle-content'; + const contentId = 'detached-expandable-section-content'; + const toggleId = 'detached-expandable-section-toggle'; return ( - + This content is visible only when the component is expanded. - + {isExpanded ? 'Show less' : 'Show more'} diff --git a/packages/react-core/src/components/JumpLinks/JumpLinks.tsx b/packages/react-core/src/components/JumpLinks/JumpLinks.tsx index b8560f4f28f..dc66f560ff4 100644 --- a/packages/react-core/src/components/JumpLinks/JumpLinks.tsx +++ b/packages/react-core/src/components/JumpLinks/JumpLinks.tsx @@ -189,6 +189,7 @@ export const JumpLinks: React.FunctionComponent = ({ scrollableElement.scrollTo(0, newScrollItem.offsetTop - offset); } newScrollItem.focus(); + window.history.pushState('', '', ev.currentTarget.href); ev.preventDefault(); setActiveIndex(itemIndex); } diff --git a/packages/react-core/src/components/Menu/MenuItem.tsx b/packages/react-core/src/components/Menu/MenuItem.tsx index 6791897b237..bc8e94b7da7 100644 --- a/packages/react-core/src/components/Menu/MenuItem.tsx +++ b/packages/react-core/src/components/Menu/MenuItem.tsx @@ -25,6 +25,10 @@ export interface MenuItemProps extends Omit, 'onC itemId?: any; /** Target navigation link. Should not be used if the flyout prop is defined. */ to?: string; + /** Navigation link target. Only set when the to property is present. If isExternalLink is also passed in, this property will be set to "_blank". */ + target?: string; + /** Navigation link relationship. Only set when the to property is present. */ + rel?: string; /** Flag indicating the item has a checkbox */ hasCheckbox?: boolean; /** Flag indicating whether the item is active */ @@ -113,6 +117,8 @@ const MenuItemBase: React.FunctionComponent = ({ id, 'aria-label': ariaLabel, tooltipProps, + rel, + target, ...props }: MenuItemProps) => { const { @@ -264,7 +270,8 @@ const MenuItemBase: React.FunctionComponent = ({ 'aria-disabled': isDisabled || isAriaDisabled ? true : null, // prevent invalid 'disabled' attribute on tags disabled: null, - target: isExternalLink ? '_blank' : null + target: isExternalLink ? '_blank' : target, + rel }; } else if (Component === 'button') { additionalProps = { @@ -428,13 +435,7 @@ const MenuItemBase: React.FunctionComponent = ({ {...(hasCheckbox && { 'aria-label': ariaLabel })} {...props} > - {tooltipProps ? ( - - {renderItem} - - ) : ( - renderItem - )} + {tooltipProps ? {renderItem} : renderItem} ); }; diff --git a/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadButton.tsx b/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadButton.tsx index ce623864cac..24de44aee0a 100644 --- a/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadButton.tsx +++ b/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadButton.tsx @@ -9,19 +9,26 @@ export interface MultipleFileUploadButtonProps extends React.HTMLProps = ({ className, 'aria-label': ariaLabel, + browseButtonText = "Upload", ...props }: MultipleFileUploadButtonProps) => { + if (!ariaLabel && !browseButtonText) { + // eslint-disable-next-line no-console + console.warn("For accessibility reasons an aria-label should be specified on MultipleFileUploadButton if a browseButtonText isn't"); + } const { open } = React.useContext(MultipleFileUploadContext); return (
); diff --git a/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadMain.tsx b/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadMain.tsx index 3a0ed196dae..daae1aec256 100644 --- a/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadMain.tsx +++ b/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadMain.tsx @@ -21,6 +21,8 @@ export interface MultipleFileUploadMainProps extends React.HTMLProps = ({ @@ -30,6 +32,7 @@ export const MultipleFileUploadMain: React.FunctionComponent { const showTitle = !!titleIcon || !!titleText || !!titleTextSeparator; @@ -37,7 +40,7 @@ export const MultipleFileUploadMain: React.FunctionComponent {showTitle && } - {isUploadButtonHidden || } + {isUploadButtonHidden || } {!!infoText && {infoText}}
); diff --git a/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadStatus.tsx b/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadStatus.tsx index eb832f83140..10ec7937fff 100644 --- a/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadStatus.tsx +++ b/packages/react-core/src/components/MultipleFileUpload/MultipleFileUploadStatus.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/MultipleFileUpload/multiple-file-upload'; import { css } from '@patternfly/react-styles'; import { ExpandableSection } from '../ExpandableSection'; +import { GenerateId } from '../../helpers/GenerateId/GenerateId'; import InProgressIcon from '@patternfly/react-icons/dist/esm/icons/in-progress-icon'; import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon'; import TimesCircleIcon from '@patternfly/react-icons/dist/esm/icons/times-circle-icon'; @@ -65,11 +66,21 @@ export const MultipleFileUploadStatus: React.FunctionComponent - -
    - {children} -
-
+ + {(expandableSectionId) => ( + +
    + {children} +
+
+ )} +
); }; diff --git a/packages/react-core/src/components/MultipleFileUpload/__tests__/MultipleFileUploadButton.test.tsx b/packages/react-core/src/components/MultipleFileUpload/__tests__/MultipleFileUploadButton.test.tsx index 8da9c11ec60..86f5138fcd5 100644 --- a/packages/react-core/src/components/MultipleFileUpload/__tests__/MultipleFileUploadButton.test.tsx +++ b/packages/react-core/src/components/MultipleFileUpload/__tests__/MultipleFileUploadButton.test.tsx @@ -17,4 +17,9 @@ describe('MultipleFileUploadButton', () => { const { asFragment } = render(Foo); expect(asFragment()).toMatchSnapshot(); }); + + test('renders with label applied to the button', () => { + const { asFragment } = render(Foo); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/packages/react-core/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadButton.test.tsx.snap b/packages/react-core/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadButton.test.tsx.snap index 91793b6de6f..df657e92220 100644 --- a/packages/react-core/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadButton.test.tsx.snap +++ b/packages/react-core/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadButton.test.tsx.snap @@ -57,3 +57,22 @@ exports[`MultipleFileUploadButton renders with expected class names 1`] = `
`; + +exports[`MultipleFileUploadButton renders with label applied to the button 1`] = ` + +
+ +
+
+`; diff --git a/packages/react-core/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadStatus.test.tsx.snap b/packages/react-core/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadStatus.test.tsx.snap index b908d1a93b0..9a7b3827354 100644 --- a/packages/react-core/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadStatus.test.tsx.snap +++ b/packages/react-core/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUploadStatus.test.tsx.snap @@ -9,8 +9,10 @@ exports[`MultipleFileUploadStatus renders custom class names 1`] = ` class="pf-v5-c-expandable-section pf-m-expanded" >
          { isBreadcrumbGrouped?: boolean; /** Additional content of the group */ additionalGroupedContent?: React.ReactNode; + /** HTML component used as main component of the page. Defaults to 'main', only pass in 'div' if another 'main' element already exists. */ + mainComponent?: 'main' | 'div'; /** Additional props of the group */ groupProps?: PageGroupProps; /** Additional props of the breadcrumb */ @@ -104,6 +106,7 @@ export class Page extends React.Component { mainTabIndex: -1, isNotificationDrawerExpanded: false, onNotificationDrawerExpand: () => null, + mainComponent: 'main', getBreakpoint, getVerticalBreakpoint }; @@ -229,6 +232,7 @@ export class Page extends React.Component { getVerticalBreakpoint, mainAriaLabel, mainTabIndex, + mainComponent, tertiaryNav, isTertiaryNavGrouped, isBreadcrumbGrouped, @@ -288,8 +292,10 @@ export class Page extends React.Component { ) : null; + const Component: keyof JSX.IntrinsicElements = mainComponent; + const main = ( -
          { {!isTertiaryNavGrouped && nav} {!isBreadcrumbGrouped && crumb} {children} -
          + ); const panelContent = {notificationDrawer}; diff --git a/packages/react-core/src/components/Slider/Slider.tsx b/packages/react-core/src/components/Slider/Slider.tsx index f5e48ae0244..a889032e3a3 100644 --- a/packages/react-core/src/components/Slider/Slider.tsx +++ b/packages/react-core/src/components/Slider/Slider.tsx @@ -423,9 +423,6 @@ export const Slider: React.FunctionComponent = ({ {buildSteps()}
        )} - {isInputVisible && inputPosition === 'aboveThumb' && ( -
        {displayInput()}
        - )} {hasTooltipOverThumb ? ( {thumbComponent} @@ -433,6 +430,9 @@ export const Slider: React.FunctionComponent = ({ ) : ( thumbComponent )} + {isInputVisible && inputPosition === 'aboveThumb' && ( +
        {displayInput()}
        + )}
      {isInputVisible && inputPosition === 'right' &&
      {displayInput()}
      } {rightActions &&
      {rightActions}
      } diff --git a/packages/react-core/src/components/Slider/_tests_/__snapshots__/Slider.test.tsx.snap b/packages/react-core/src/components/Slider/_tests_/__snapshots__/Slider.test.tsx.snap index c5ab99866f7..23fdc8e4ba3 100644 --- a/packages/react-core/src/components/Slider/_tests_/__snapshots__/Slider.test.tsx.snap +++ b/packages/react-core/src/components/Slider/_tests_/__snapshots__/Slider.test.tsx.snap @@ -492,6 +492,17 @@ exports[`slider renders slider with input above thumb 1`] = `
+
@@ -526,17 +537,6 @@ exports[`slider renders slider with input above thumb 1`] = `
-
diff --git a/packages/react-core/src/components/Tooltip/__tests__/Generated/TooltipArrow.test.tsx b/packages/react-core/src/components/Tooltip/__tests__/Generated/TooltipArrow.test.tsx deleted file mode 100644 index f287f2e83a6..00000000000 --- a/packages/react-core/src/components/Tooltip/__tests__/Generated/TooltipArrow.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { render } from '@testing-library/react'; -import { TooltipArrow } from '../../TooltipArrow'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('TooltipArrow should match snapshot (auto-generated)', () => { - const { asFragment } = render(); - expect(asFragment()).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Tooltip/__tests__/Generated/TooltipContent.test.tsx b/packages/react-core/src/components/Tooltip/__tests__/Generated/TooltipContent.test.tsx deleted file mode 100644 index 7eb9dee9bc8..00000000000 --- a/packages/react-core/src/components/Tooltip/__tests__/Generated/TooltipContent.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -/** - * This test was generated - */ -import * as React from 'react'; -import { render } from '@testing-library/react'; -import { TooltipContent } from '../../TooltipContent'; -// any missing imports can usually be resolved by adding them here -import {} from '../..'; - -it('TooltipContent should match snapshot (auto-generated)', () => { - const { asFragment } = render( - ReactNode} isLeftAligned={true} /> - ); - expect(asFragment()).toMatchSnapshot(); -}); diff --git a/packages/react-core/src/components/Tooltip/__tests__/Generated/__snapshots__/TooltipArrow.test.tsx.snap b/packages/react-core/src/components/Tooltip/__tests__/Generated/__snapshots__/TooltipArrow.test.tsx.snap deleted file mode 100644 index be054814faa..00000000000 --- a/packages/react-core/src/components/Tooltip/__tests__/Generated/__snapshots__/TooltipArrow.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`TooltipArrow should match snapshot (auto-generated) 1`] = ` - -
- -`; diff --git a/packages/react-core/src/components/Tooltip/__tests__/Generated/__snapshots__/TooltipContent.test.tsx.snap b/packages/react-core/src/components/Tooltip/__tests__/Generated/__snapshots__/TooltipContent.test.tsx.snap deleted file mode 100644 index f4aa189e4f9..00000000000 --- a/packages/react-core/src/components/Tooltip/__tests__/Generated/__snapshots__/TooltipContent.test.tsx.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`TooltipContent should match snapshot (auto-generated) 1`] = ` - -
-
- ReactNode -
-
-
-`; diff --git a/packages/react-core/src/components/Tooltip/__tests__/Tooltip.test.tsx b/packages/react-core/src/components/Tooltip/__tests__/Tooltip.test.tsx index 5b8ff267fe1..d090f6ca5b9 100644 --- a/packages/react-core/src/components/Tooltip/__tests__/Tooltip.test.tsx +++ b/packages/react-core/src/components/Tooltip/__tests__/Tooltip.test.tsx @@ -1,43 +1,206 @@ -import * as React from 'react'; -import { render } from '@testing-library/react'; +import React from 'react'; +import { render, screen } from '@testing-library/react'; import { Tooltip } from '../Tooltip'; +import userEvent from '@testing-library/user-event'; +import styles from '@patternfly/react-styles/css/components/Tooltip/tooltip'; -test('tooltip renders', () => { - const ref = React.createRef(); - const { asFragment } = render( - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis. -
- } - > -
Toggle tooltip
+jest.mock('../../../helpers/Popper/Popper'); + +test('Renders with class name pf-v5-c-tooltip by default', async () => { + render(); + + const tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveClass(styles.tooltip); +}); + +test('Renders with custom class names provided via prop', async () => { + render(); + + const tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveClass('test-class'); +}); + +test('Renders with aria-live of off by default when triggerRef is not passed', async () => { + render(); + + const tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveAttribute('aria-live', 'off'); +}); + +test('Renders with aria-live of polite by default when triggerRef is passed', async () => { + const triggerRef = React.createRef(); + render(); + + const tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveAttribute('aria-live', 'polite'); +}); + +test('Renders with value passed to aria-live prop', async () => { + render(); + + const tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveAttribute('aria-live', 'polite'); +}); + +test('Renders with value passed to id prop', async () => { + render(); + + const tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveAttribute('id', 'custom-id'); +}); + +test('Renders with maxWidth styling applied when maxWidth is passed', async () => { + render(); + + const tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toHaveStyle('max-width: 100px'); +}); + +test('Renders with aria-describedby on trigger by default', async () => { + render( + + + + ); + + await screen.findByRole('tooltip'); + expect(screen.getByRole('button')).toHaveAccessibleDescription('Test content'); +}); + +test('Renders with aria-labelledby on trigger when aria="labelledby" is passed', async () => { + render( + + ); - expect(asFragment()).toMatchSnapshot(); -}); - -test('tooltip renders in strict mode', () => { - const consoleError = jest.spyOn(console, 'error'); - const ref = React.createRef(); - const { asFragment } = render( - - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis. - - } - > -
Toggle tooltip
+ + await screen.findByRole('tooltip'); + expect(screen.getByRole('button')).toHaveAccessibleName('Test content'); +}); + +test('Renders without aria-labelledby or aria-describedby on trigger when aria="none" is passed', async () => { + render( + + + + ); + + await screen.findByRole('tooltip'); + expect(screen.getByRole('button')).not.toHaveAccessibleName('Test content'); + expect(screen.getByRole('button')).not.toHaveAccessibleDescription('Test content'); +}); + +test('Does not call onTooltipHidden before tooltip is hidden', async () => { + const onTooltipHiddenMock = jest.fn(); + const user = userEvent.setup(); + + const TooltipCallback = () => { + const [isVisible, setIsVisible] = React.useState(false); + + return ( + + -
+ ); + }; + render(); + + await user.click(screen.getByRole('button')); + await screen.findByRole('tooltip'); + expect(onTooltipHiddenMock).not.toHaveBeenCalled(); +}); + +test('Calls onTooltipHidden when tooltip is hidden', async () => { + const onTooltipHiddenMock = jest.fn(); + const user = userEvent.setup(); + + const TooltipCallback = () => { + const [isVisible, setIsVisible] = React.useState(true); + + return ( + + + + ); + }; + render(); + + await screen.findByRole('tooltip'); + await user.click(screen.getByRole('button')); + await screen.findByText('isVisible: false'); + expect(onTooltipHiddenMock).toHaveBeenCalled(); +}); + +test('Does not pass isVisible to Popper by default', async () => { + render(); + + const contentPassedToPopper = await screen.findByText('isVisible: false'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Passes isVisible to Popper', async () => { + render(); + + const contentPassedToPopper = await screen.findByText('isVisible: true'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Passes zIndex to Popper', async () => { + render(); + + const contentPassedToPopper = await screen.findByText('zIndex: 10'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Passes enableFlip to Popper', async () => { + render(); + + const contentPassedToPopper = await screen.findByText('enableFlip: true'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Passes position as placement to Popper', async () => { + render(); + + const contentPassedToPopper = await screen.findByText('placement: left-start'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Passes appendTo to Popper', async () => { + render( document.body} content="Test content" />); + + const contentPassedToPopper = await screen.findByText('appendTo: () => document.body'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Passes distance to Popper', async () => { + render(); + + const contentPassedToPopper = await screen.findByText('distance: 5'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Passes flipBehavior to Popper', async () => { + render(); + + const contentPassedToPopper = await screen.findByText('flipBehavior: flip'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Passes minWidth to Popper', async () => { + render(); + + const contentPassedToPopper = await screen.findByText('minWidth: 100px'); + expect(contentPassedToPopper).toBeVisible(); +}); + +test('Matches snapshot', async () => { + render( + + + ); - expect(consoleError).not.toHaveBeenCalled(); - expect(asFragment()).toMatchSnapshot(); + + const tooltip = await screen.findByRole('tooltip'); + expect(tooltip).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Tooltip/__tests__/TooltipArrow.test.tsx b/packages/react-core/src/components/Tooltip/__tests__/TooltipArrow.test.tsx new file mode 100644 index 00000000000..8854a2dbe9f --- /dev/null +++ b/packages/react-core/src/components/Tooltip/__tests__/TooltipArrow.test.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { TooltipArrow } from '../TooltipArrow'; +import styles from '@patternfly/react-styles/css/components/Tooltip/tooltip'; + +test('Renders without children', () => { + render(); + + expect(screen.getByTestId('tooltipArrow')).toBeVisible(); +}); + +test('Renders with class name pf-v5-c-tooltip__arrow by default', () => { + render(); + + expect(screen.getByTestId('tooltipArrow')).toHaveClass(styles.tooltipArrow); +}); + +test('Renders with custom class names provided via prop', () => { + render(); + + expect(screen.getByTestId('tooltipArrow')).toHaveClass('test-class'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Tooltip/__tests__/TooltipContent.test.tsx b/packages/react-core/src/components/Tooltip/__tests__/TooltipContent.test.tsx new file mode 100644 index 00000000000..8a80a3e61f3 --- /dev/null +++ b/packages/react-core/src/components/Tooltip/__tests__/TooltipContent.test.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { TooltipContent } from '../TooltipContent'; +import styles from '@patternfly/react-styles/css/components/Tooltip/tooltip'; + +test('Renders with children', () => { + render(Test content); + + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with class name pf-v5-c-tooltip__content by default', () => { + render(Test content); + + expect(screen.getByText('Test content')).toHaveClass(styles.tooltipContent); +}); + +test('Renders with custom class names provided via prop', () => { + render(Test content); + + expect(screen.getByText('Test content')).toHaveClass('test-class'); +}); + +test('Does not render with class pf-m-text-align-left when isLeftAligned is not passed', () => { + render(Test content); + + expect(screen.getByText('Test content')).not.toHaveClass('pf-m-text-align-left'); +}); + +test('Renders with class pf-m-text-align-left when isLeftAligned is passed', () => { + render(Test content); + + expect(screen.getByText('Test content')).toHaveClass('pf-m-text-align-left'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render(Test content); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Tooltip/__tests__/__snapshots__/Tooltip.test.tsx.snap b/packages/react-core/src/components/Tooltip/__tests__/__snapshots__/Tooltip.test.tsx.snap index 14c149bf298..ff3491e7aef 100644 --- a/packages/react-core/src/components/Tooltip/__tests__/__snapshots__/Tooltip.test.tsx.snap +++ b/packages/react-core/src/components/Tooltip/__tests__/__snapshots__/Tooltip.test.tsx.snap @@ -1,17 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`tooltip renders 1`] = ` - -
- Toggle tooltip +exports[`Matches snapshot 1`] = ` +
- + Tooltip attached via selector ref
} - triggerRef={() => document.getElementById('tooltip-selector')} + id="tooltip-selector-content" + content={
Tooltip content attached via selector ref
} + triggerRef={() => document.getElementById('tooltip-selector-trigger')} />
+
+ Tooltip content with click trigger
}> + +
+ +
+ Tooltip content with custom delay
} + > + +
+ +
+ Tooltip content with animationDuration
} + > + +
+ ); } 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 7211e39f757..cdd9374622b 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 @@ -161,8 +161,99 @@ export class WizardDemo extends React.Component,

Step 1

-
-

Step 2

+
+ <> +

+ The content of this step overflows and creates a scrollbar, which causes a tabindex of "0", a role + of "region", and an aria-label or aria-labelledby to be applied. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer bibendum in neque nec pharetra. + Duis lacinia vel sapien ut imperdiet. Nunc ultrices mollis dictum. Duis tempus, massa nec tincidunt + tempor, enim ex porttitor odio, eu facilisis dolor tortor id sapien. Etiam sit amet molestie lacus. + Nulla facilisi. Duis eget finibus ipsum. Quisque dictum enim sed sodales porta. Curabitur eget orci + eu risus posuere pulvinar id nec turpis. Morbi mattis orci vel posuere tincidunt. Fusce bibendum et + libero a auctor. +

+

+ Proin elementum commodo sodales. Quisque eget libero mattis, ornare augue at, egestas nisi. Mauris + ultrices orci fringilla pretium mattis. Aliquam erat volutpat. Sed pharetra condimentum dui, nec + bibendum ante. Vestibulum sollicitudin, sem accumsan pharetra molestie, purus turpis lacinia lorem, + commodo sodales quam lectus a urna. Nam gravida, felis a lacinia varius, ex ipsum ultrices orci, non + egestas diam velit in mi. Ut sit amet commodo orci. Duis sed diam odio. Duis mi metus, dignissim in + odio nec, ornare aliquet libero. Sed luctus elit nibh. Quisque et felis diam. Integer ac metus + dolor. +

+ + <> +

+ The content of this step overflows and creates a scrollbar, which causes a tabindex of "0", a role + of "region", and an aria-label or aria-labelledby to be applied. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer bibendum in neque nec pharetra. + Duis lacinia vel sapien ut imperdiet. Nunc ultrices mollis dictum. Duis tempus, massa nec tincidunt + tempor, enim ex porttitor odio, eu facilisis dolor tortor id sapien. Etiam sit amet molestie lacus. + Nulla facilisi. Duis eget finibus ipsum. Quisque dictum enim sed sodales porta. Curabitur eget orci + eu risus posuere pulvinar id nec turpis. Morbi mattis orci vel posuere tincidunt. Fusce bibendum et + libero a auctor. +

+

+ Proin elementum commodo sodales. Quisque eget libero mattis, ornare augue at, egestas nisi. Mauris + ultrices orci fringilla pretium mattis. Aliquam erat volutpat. Sed pharetra condimentum dui, nec + bibendum ante. Vestibulum sollicitudin, sem accumsan pharetra molestie, purus turpis lacinia lorem, + commodo sodales quam lectus a urna. Nam gravida, felis a lacinia varius, ex ipsum ultrices orci, non + egestas diam velit in mi. Ut sit amet commodo orci. Duis sed diam odio. Duis mi metus, dignissim in + odio nec, ornare aliquet libero. Sed luctus elit nibh. Quisque et felis diam. Integer ac metus + dolor. +

+ + <> +

+ The content of this step overflows and creates a scrollbar, which causes a tabindex of "0", a role + of "region", and an aria-label or aria-labelledby to be applied. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer bibendum in neque nec pharetra. + Duis lacinia vel sapien ut imperdiet. Nunc ultrices mollis dictum. Duis tempus, massa nec tincidunt + tempor, enim ex porttitor odio, eu facilisis dolor tortor id sapien. Etiam sit amet molestie lacus. + Nulla facilisi. Duis eget finibus ipsum. Quisque dictum enim sed sodales porta. Curabitur eget orci + eu risus posuere pulvinar id nec turpis. Morbi mattis orci vel posuere tincidunt. Fusce bibendum et + libero a auctor. +

+

+ Proin elementum commodo sodales. Quisque eget libero mattis, ornare augue at, egestas nisi. Mauris + ultrices orci fringilla pretium mattis. Aliquam erat volutpat. Sed pharetra condimentum dui, nec + bibendum ante. Vestibulum sollicitudin, sem accumsan pharetra molestie, purus turpis lacinia lorem, + commodo sodales quam lectus a urna. Nam gravida, felis a lacinia varius, ex ipsum ultrices orci, non + egestas diam velit in mi. Ut sit amet commodo orci. Duis sed diam odio. Duis mi metus, dignissim in + odio nec, ornare aliquet libero. Sed luctus elit nibh. Quisque et felis diam. Integer ac metus + dolor. +

+ + <> +

+ The content of this step overflows and creates a scrollbar, which causes a tabindex of "0", a role + of "region", and an aria-label or aria-labelledby to be applied. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer bibendum in neque nec pharetra. + Duis lacinia vel sapien ut imperdiet. Nunc ultrices mollis dictum. Duis tempus, massa nec tincidunt + tempor, enim ex porttitor odio, eu facilisis dolor tortor id sapien. Etiam sit amet molestie lacus. + Nulla facilisi. Duis eget finibus ipsum. Quisque dictum enim sed sodales porta. Curabitur eget orci + eu risus posuere pulvinar id nec turpis. Morbi mattis orci vel posuere tincidunt. Fusce bibendum et + libero a auctor. +

+

+ Proin elementum commodo sodales. Quisque eget libero mattis, ornare augue at, egestas nisi. Mauris + ultrices orci fringilla pretium mattis. Aliquam erat volutpat. Sed pharetra condimentum dui, nec + bibendum ante. Vestibulum sollicitudin, sem accumsan pharetra molestie, purus turpis lacinia lorem, + commodo sodales quam lectus a urna. Nam gravida, felis a lacinia varius, ex ipsum ultrices orci, non + egestas diam velit in mi. Ut sit amet commodo orci. Duis sed diam odio. Duis mi metus, dignissim in + odio nec, ornare aliquet libero. Sed luctus elit nibh. Quisque et felis diam. Integer ac metus + dolor. +

+
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 index a090bfca972..9852c1be882 100644 --- 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 @@ -75,8 +75,96 @@ export class WizardDeprecatedDemo extends React.Component -

Step 2

+
+ <> +

+ The content of this step overflows and creates a scrollbar, which causes a tabindex of "0", a role of + "region", and an aria-label or aria-labelledby to be applied. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer bibendum in neque nec pharetra. Duis + lacinia vel sapien ut imperdiet. Nunc ultrices mollis dictum. Duis tempus, massa nec tincidunt tempor, + enim ex porttitor odio, eu facilisis dolor tortor id sapien. Etiam sit amet molestie lacus. Nulla + facilisi. Duis eget finibus ipsum. Quisque dictum enim sed sodales porta. Curabitur eget orci eu risus + posuere pulvinar id nec turpis. Morbi mattis orci vel posuere tincidunt. Fusce bibendum et libero a + auctor. +

+

+ Proin elementum commodo sodales. Quisque eget libero mattis, ornare augue at, egestas nisi. Mauris + ultrices orci fringilla pretium mattis. Aliquam erat volutpat. Sed pharetra condimentum dui, nec + bibendum ante. Vestibulum sollicitudin, sem accumsan pharetra molestie, purus turpis lacinia lorem, + commodo sodales quam lectus a urna. Nam gravida, felis a lacinia varius, ex ipsum ultrices orci, non + egestas diam velit in mi. Ut sit amet commodo orci. Duis sed diam odio. Duis mi metus, dignissim in odio + nec, ornare aliquet libero. Sed luctus elit nibh. Quisque et felis diam. Integer ac metus dolor. +

+ + <> +

+ The content of this step overflows and creates a scrollbar, which causes a tabindex of "0", a role of + "region", and an aria-label or aria-labelledby to be applied. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer bibendum in neque nec pharetra. Duis + lacinia vel sapien ut imperdiet. Nunc ultrices mollis dictum. Duis tempus, massa nec tincidunt tempor, + enim ex porttitor odio, eu facilisis dolor tortor id sapien. Etiam sit amet molestie lacus. Nulla + facilisi. Duis eget finibus ipsum. Quisque dictum enim sed sodales porta. Curabitur eget orci eu risus + posuere pulvinar id nec turpis. Morbi mattis orci vel posuere tincidunt. Fusce bibendum et libero a + auctor. +

+

+ Proin elementum commodo sodales. Quisque eget libero mattis, ornare augue at, egestas nisi. Mauris + ultrices orci fringilla pretium mattis. Aliquam erat volutpat. Sed pharetra condimentum dui, nec + bibendum ante. Vestibulum sollicitudin, sem accumsan pharetra molestie, purus turpis lacinia lorem, + commodo sodales quam lectus a urna. Nam gravida, felis a lacinia varius, ex ipsum ultrices orci, non + egestas diam velit in mi. Ut sit amet commodo orci. Duis sed diam odio. Duis mi metus, dignissim in odio + nec, ornare aliquet libero. Sed luctus elit nibh. Quisque et felis diam. Integer ac metus dolor. +

+ + <> +

+ The content of this step overflows and creates a scrollbar, which causes a tabindex of "0", a role of + "region", and an aria-label or aria-labelledby to be applied. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer bibendum in neque nec pharetra. Duis + lacinia vel sapien ut imperdiet. Nunc ultrices mollis dictum. Duis tempus, massa nec tincidunt tempor, + enim ex porttitor odio, eu facilisis dolor tortor id sapien. Etiam sit amet molestie lacus. Nulla + facilisi. Duis eget finibus ipsum. Quisque dictum enim sed sodales porta. Curabitur eget orci eu risus + posuere pulvinar id nec turpis. Morbi mattis orci vel posuere tincidunt. Fusce bibendum et libero a + auctor. +

+

+ Proin elementum commodo sodales. Quisque eget libero mattis, ornare augue at, egestas nisi. Mauris + ultrices orci fringilla pretium mattis. Aliquam erat volutpat. Sed pharetra condimentum dui, nec + bibendum ante. Vestibulum sollicitudin, sem accumsan pharetra molestie, purus turpis lacinia lorem, + commodo sodales quam lectus a urna. Nam gravida, felis a lacinia varius, ex ipsum ultrices orci, non + egestas diam velit in mi. Ut sit amet commodo orci. Duis sed diam odio. Duis mi metus, dignissim in odio + nec, ornare aliquet libero. Sed luctus elit nibh. Quisque et felis diam. Integer ac metus dolor. +

+ + <> +

+ The content of this step overflows and creates a scrollbar, which causes a tabindex of "0", a role of + "region", and an aria-label or aria-labelledby to be applied. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer bibendum in neque nec pharetra. Duis + lacinia vel sapien ut imperdiet. Nunc ultrices mollis dictum. Duis tempus, massa nec tincidunt tempor, + enim ex porttitor odio, eu facilisis dolor tortor id sapien. Etiam sit amet molestie lacus. Nulla + facilisi. Duis eget finibus ipsum. Quisque dictum enim sed sodales porta. Curabitur eget orci eu risus + posuere pulvinar id nec turpis. Morbi mattis orci vel posuere tincidunt. Fusce bibendum et libero a + auctor. +

+

+ Proin elementum commodo sodales. Quisque eget libero mattis, ornare augue at, egestas nisi. Mauris + ultrices orci fringilla pretium mattis. Aliquam erat volutpat. Sed pharetra condimentum dui, nec + bibendum ante. Vestibulum sollicitudin, sem accumsan pharetra molestie, purus turpis lacinia lorem, + commodo sodales quam lectus a urna. Nam gravida, felis a lacinia varius, ex ipsum ultrices orci, non + egestas diam velit in mi. Ut sit amet commodo orci. Duis sed diam odio. Duis mi metus, dignissim in odio + nec, ornare aliquet libero. Sed luctus elit nibh. Quisque et felis diam. Integer ac metus dolor. +

+ +
) @@ -122,7 +210,7 @@ export class WizardDeprecatedDemo extends React.Component