From d58b051f8d736f55580e3df9fc2bbddf479af099 Mon Sep 17 00:00:00 2001 From: Eric Olkowski <70952936+thatblindgeye@users.noreply.github.com> Date: Mon, 19 Aug 2024 16:19:57 -0400 Subject: [PATCH] fix(Card): updated markup for actionable cards (#10859) * fix(Card): updated markup for actionable cards * Added unit tests * Added noOffset modifier to selectable examples * Updated failing cypress test * Added aria-disabled to link card * Updated tests per Austin feedback --- packages/react-core/package.json | 2 +- .../src/components/Card/CardHeader.tsx | 208 ++++++----- .../Card/__tests__/CardHeader.test.tsx | 331 +++++++++++++++++- .../Card/examples/CardClickable.tsx | 32 +- .../Card/examples/CardClickableSelectable.tsx | 9 +- .../Card/examples/CardSelectable.tsx | 9 +- .../Card/examples/CardSingleSelectable.tsx | 9 +- packages/react-docs/package.json | 2 +- packages/react-icons/package.json | 2 +- .../cypress/integration/card.spec.ts | 6 +- .../components/demos/CardDemo/CardDemo.tsx | 50 +-- packages/react-styles/package.json | 2 +- packages/react-tokens/package.json | 2 +- yarn.lock | 18 +- 14 files changed, 509 insertions(+), 173 deletions(-) diff --git a/packages/react-core/package.json b/packages/react-core/package.json index 4182f51487e..1f26c8bbb46 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -55,7 +55,7 @@ "tslib": "^2.6.2" }, "devDependencies": { - "@patternfly/patternfly": "6.0.0-alpha.205", + "@patternfly/patternfly": "6.0.0-alpha.210", "case-anything": "^2.1.13", "css": "^3.0.0", "fs-extra": "^11.2.0" diff --git a/packages/react-core/src/components/Card/CardHeader.tsx b/packages/react-core/src/components/Card/CardHeader.tsx index de8e030129f..1ee98dbee92 100644 --- a/packages/react-core/src/components/Card/CardHeader.tsx +++ b/packages/react-core/src/components/Card/CardHeader.tsx @@ -26,23 +26,29 @@ export interface CardHeaderSelectableActionsObject { hasNoOffset?: boolean; /** Additional classes added to the selectable actions wrapper */ className?: string; - /** ID passed to the selectable or clickable input */ - selectableActionId: string; - /** Adds an accessible label to the selectable or clickable input */ + /** Custom ID passed to the selectable card's input or a clickable-only card's button/anchor. + * If omitted, a random unique ID will be assigned to a selectable card's input. */ + selectableActionId?: string; + /** Adds an accessible name to the input of a selectable card or clickable button/anchor of a clickable-only card. + * This or selectableActionAriaLabelledby is required for clickable-only cards. + */ selectableActionAriaLabel?: string; - /** Adds an accessible label to the selectable or clickable input by passing in a - * space separated list of id's. + /** A single or list of space-delimited ID's that provide an accessible name to the input of a selectable card + * or clickable button/anchor of a clickable-only card. This or selectableActionAriaLabelledby is required + * for clickable-only cards. */ selectableActionAriaLabelledby?: string; /** Callback for when a selectable card input changes */ onChange?: (event: React.FormEvent, checked: boolean) => void; - /** Action to call when clickable card is clicked */ - onClickAction?: (event: React.FormEvent | React.MouseEvent) => void; - /** Link to navigate to when clickable card is clicked */ + /** Action to call when a clickable-only card is clicked. This cannot be combined with the to prop. */ + onClickAction?: (event: React.MouseEvent) => void; + /** Link to navigate to when a clickable-only card is clicked. This cannot be combined with the onClickAction prop. */ to?: string; - /** Flag to indicate whether a clickable card's link should open in a new tab/window. */ + /** Additional props spread to a selectable card input or clickable-only card's button/anchor. */ + selectableActionProps?: any; + /** Flag to indicate whether a clickable-only card's link should open in a new tab/window. */ isExternalLink?: boolean; - /** Name for the input element of a clickable or selectable card. */ + /** Name for the input element of a selectable card. */ name?: string; /** @deprecated Flag indicating whether the selectable card input is checked. We recommend using * the isSelected prop on the card component instead. @@ -79,101 +85,117 @@ export const CardHeader: React.FunctionComponent = ({ toggleButtonProps, isToggleRightAligned, ...props -}: CardHeaderProps) => ( - - {({ cardId, isClickable, isSelectable, isSelected, isClicked, isDisabled: isCardDisabled }) => { - const cardHeaderToggle = ( -
-
- ); +}: CardHeaderProps) => { + const uniqueId = React.useId(); - const isClickableOrSelectableOnly = (isClickable && !isSelectable) || (isSelectable && !isClickable); - if (actions?.actions && isClickableOrSelectableOnly) { - // eslint-disable-next-line no-console - console.warn( - `${ - isClickable ? 'Clickable' : 'Selectable' - } only cards should not contain any other actions. If you wish to include additional actions, use a clickable and selectable card.` + return ( + + {({ cardId, isClickable, isSelectable, isSelected, isDisabled: isCardDisabled }) => { + const cardHeaderToggle = ( +
+
); - } - const handleActionClick = (event: React.FormEvent | React.MouseEvent) => { - if (selectableActions?.onClickAction) { - selectableActions.onClickAction(event); - } else if (selectableActions?.to) { - window.open(selectableActions.to, selectableActions.isExternalLink ? '_blank' : '_self'); + const isClickableOrSelectableOnly = (isClickable && !isSelectable) || (isSelectable && !isClickable); + if (actions?.actions && isClickableOrSelectableOnly) { + // eslint-disable-next-line no-console + console.error( + `Card: ${ + isClickable ? 'Clickable' : 'Selectable' + } only cards should not contain any other actions. If you wish to include additional actions, use a clickable and selectable card.` + ); + } + + const isClickableOnlyCard = isClickable && !isSelectable; + if ( + (isClickableOnlyCard || isSelectable) && + !selectableActions?.selectableActionAriaLabel && + !selectableActions?.selectableActionAriaLabelledby + ) { + // eslint-disable-next-line no-console + console.error( + `Card: ${isClickableOnlyCard ? 'Clickable-only cards' : 'Cards with a selectable input'} must have either the selectableActions.selectableActionAriaLabel or selectableActions.selectableActionAriaLabelledby prop passed in order to provide an accessible name to the clickable element.` + ); } - }; - const getClickableSelectableProps = () => { - const baseProps = { + const SelectableCardInput = selectableActions?.variant === 'single' ? Radio : Checkbox; + const getSelectableProps = () => ({ className: 'pf-m-standalone', - inputClassName: isClickable && !isSelectable && 'pf-v6-screen-reader', label: <>, 'aria-label': selectableActions.selectableActionAriaLabel, 'aria-labelledby': selectableActions.selectableActionAriaLabelledby, - id: selectableActions.selectableActionId, + id: selectableActions.selectableActionId ?? `card-selectable-${uniqueId}`, name: selectableActions.name, - isDisabled: isCardDisabled - }; - const isSelectableInputChecked = selectableActions.isChecked ?? isSelected; + isDisabled: isCardDisabled, + onChange: selectableActions.onChange, + isChecked: selectableActions.isChecked ?? isSelected, + ...selectableActions.selectableActionProps + }); - if (isClickable && !isSelectable) { - return { - ...baseProps, - onClick: handleActionClick, - isChecked: isClicked + const isClickableLinkCard = selectableActions?.to !== undefined; + const ClickableCardComponent = isClickableLinkCard ? 'a' : 'button'; + const getClickableProps = () => { + const isDisabledLinkCard = isCardDisabled && isClickableLinkCard; + const baseProps = { + className: css('pf-v6-c-card__clickable-action', isDisabledLinkCard && styles.modifiers.disabled), + id: selectableActions.selectableActionId, + 'aria-label': selectableActions.selectableActionAriaLabel, + 'aria-labelledby': selectableActions.selectableActionAriaLabelledby, + ...selectableActions.selectableActionProps }; - } - if (isSelectable) { - return { ...baseProps, onChange: selectableActions.onChange, isChecked: isSelectableInputChecked }; - } - return baseProps; - }; + if (isClickableLinkCard) { + return { + ...baseProps, + href: selectableActions.to, + ...(isCardDisabled && { tabIndex: -1, 'aria-disabled': true }), + ...(selectableActions.isExternalLink && { target: '_blank' }) + }; + } + + return { ...baseProps, type: 'button', disabled: isCardDisabled, onClick: selectableActions.onClickAction }; + }; - return ( -
- {onExpand && !isToggleRightAligned && cardHeaderToggle} - {(actions || (selectableActions && (isClickable || isSelectable))) && ( - - {actions?.actions} - {selectableActions && (isClickable || isSelectable) && ( - - {selectableActions?.variant === 'single' || (isClickable && !isSelectable) ? ( - - ) : ( - - )} - - )} - - )} - {children && {children}} - {onExpand && isToggleRightAligned && cardHeaderToggle} -
- ); - }} -
-); + return ( +
+ {onExpand && !isToggleRightAligned && cardHeaderToggle} + {(actions || (selectableActions && (isClickable || isSelectable))) && ( + + {actions?.actions} + {selectableActions && (isClickable || isSelectable) && ( + + {isSelectable && } + {isClickableOnlyCard && } + + )} + + )} + {children && {children}} + {onExpand && isToggleRightAligned && cardHeaderToggle} +
+ ); + }} +
+ ); +}; CardHeader.displayName = 'CardHeader'; diff --git a/packages/react-core/src/components/Card/__tests__/CardHeader.test.tsx b/packages/react-core/src/components/Card/__tests__/CardHeader.test.tsx index b17ff54a051..996f024b0ec 100644 --- a/packages/react-core/src/components/Card/__tests__/CardHeader.test.tsx +++ b/packages/react-core/src/components/Card/__tests__/CardHeader.test.tsx @@ -1,6 +1,8 @@ import React from 'react'; -import { render } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { CardHeader } from '../CardHeader'; +import { CardContext } from '../Card'; describe('CardHeader', () => { test('onExpand adds the toggle button', () => { @@ -13,3 +15,330 @@ describe('CardHeader', () => { expect(asFragment()).toMatchSnapshot(); }); }); + +// TODO: check if hasNoOffset for actions/selectableActions and className for selectableActions render +describe('Card with actions and selectableActions', () => { + test('Does not render selectable or clickable actions by default', () => { + render(Test); + + expect(screen.queryByRole('checkbox')).not.toBeInTheDocument(); + expect(screen.queryByRole('button')).not.toBeInTheDocument(); + expect(screen.queryByRole('link')).not.toBeInTheDocument(); + }); + + test('Renders checkbox input when Card has isSelectable and selectableActions.variant = "multiple"', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toBeInTheDocument(); + }); + test('Renders checkbox input by default when Card has isSelectable and selectableActions is passed with any props', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toBeInTheDocument(); + }); + test('Renders radio input when Card has isSelectable and selectableActions.variant = "single"', () => { + render( + + Test + + ); + + expect(screen.getByRole('radio')).toBeInTheDocument(); + }); + test('Renders default ID for selectable card input when selectableActions.selectableActionId is not passed', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox').getAttribute('id')).toMatch(/^card-selectable/); + }); + test('Renders custom ID for selectable card input when selectableActions.selectableActionId is passed', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toHaveAttribute('id', 'custom-id'); + }); + test('Renders name on a selectable card input', () => { + render( + + Test + + ); + + expect(screen.getByRole('radio')).toHaveAttribute('name', 'test'); + }); + test('Renders a selectable card input as not checked by default', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).not.toBeChecked(); + }); + test('Renders a selectable card input as checked when Card has isSelected = true', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toBeChecked(); + }); + test('Renders a selectable card input as checked when deprecated selectableActions.isChecked is true', () => { + render( + + Test + + ); + + expect(screen.getByRole('checkbox')).toBeChecked(); + }); + test('Renders additional props on selectable card input when selectableActions.selectableActionProps is passed', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('checkbox')).toHaveAttribute('style'); + }); + + test('Does not call onChange for selectable card when card is not clicked', async () => { + const user = userEvent.setup(); + const onChangeMock = jest.fn(); + + render( + <> + + + Test + + + ); + + await user.click(screen.getByRole('button', { name: 'Test click' })); + expect(onChangeMock).not.toHaveBeenCalled(); + }); + test('Calls onChange for selectable card when card is clicked', async () => { + const user = userEvent.setup(); + const onChangeMock = jest.fn(); + + render( + + Test + + ); + + const labelElement = document.querySelector('label'); + await user.click(labelElement as HTMLElement); + expect(onChangeMock).toHaveBeenCalled(); + }); + + test('Renders button element when Card has isClickable and selectableActions.onClickAction is passed"', () => { + render( + + {} }}>Test + + ); + + expect(screen.getByRole('button')).toBeInTheDocument(); + }); + test('Renders anchor element when Card has isClickable and selectableActions.to is passed"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).toBeInTheDocument(); + }); + test('Renders href when Card has isClickable and selectableActions.to is passed"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).toHaveAttribute('href', '#some-id'); + }); + test('Does not render ID on clickable element when selectableActions.selectableActionId is not passed"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).not.toHaveAttribute('id'); + }); + test('Renders ID on clickable element when selectableActions.selectableActionId is passed"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).toHaveAttribute('id', 'custom-id'); + }); + test('Renders additional props on clickable element when selectableActions.selectableActionProps is passed', () => { + render( + + + Test + + + ); + + expect(screen.getByRole('link')).toHaveAttribute('style'); + }); + test('Does not render target="_blank" on clickable card anchor element by default"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).not.toHaveAttribute('target'); + }); + test('Renders target="_blank" on clickable card anchor element when selectableActions.isExternalLink is true"', () => { + render( + + Test + + ); + + expect(screen.getByRole('link')).toHaveAttribute('target', '_blank'); + }); + test('Calls onClickAction for clickable card when card is clicked', async () => { + const user = userEvent.setup(); + const onClickMock = jest.fn(); + + render( + + Test + + ); + + await user.click(screen.getByRole('button')); + expect(onClickMock).toHaveBeenCalled(); + }); + + test('Throws error when Card is either clickable or selectable only and has actions prop passed"', () => { + const errorMock = jest.fn() as any; + global.console = { error: errorMock } as any; + render( + + Toggle }} + selectableActions={{ to: '#', selectableActionAriaLabel: 'Link' }} + > + Test + + + ); + + expect(errorMock).toHaveBeenCalled(); + }); + test('Does not throw error when Card is both clickable and selectable and has actions prop passed"', () => { + const errorMock = jest.fn() as any; + global.console = { error: errorMock } as any; + render( + + Toggle }} + selectableActions={{ to: '#', selectableActionAriaLabel: 'Link' }} + > + Test + + + ); + + expect(errorMock).not.toHaveBeenCalled(); + }); + test('Throws error when Card has isClickable and selectableActions.selectableActionAriaLabel or selectableActions.selectableActionAriaLabelledby is not passed"', () => { + const errorMock = jest.fn() as any; + global.console = { error: errorMock } as any; + render( + + Test + + ); + + expect(errorMock).toHaveBeenCalled(); + }); + test('Throws error when Card has isSelectable and selectableActions.selectableActionAriaLabel or selectableActions.selectableActionAriaLabelledby is not passed"', () => { + const errorMock = jest.fn() as any; + global.console = { error: errorMock } as any; + render( + + Test + + ); + + expect(errorMock).toHaveBeenCalled(); + }); + + test('Renders accessible name on selectable card input when selectableActions.selectableActionAriaLabel is passed', () => { + const accessibleName = 'Accessible name'; + render( + + + Test + + + ); + + expect(screen.getByRole('checkbox')).toHaveAccessibleName(accessibleName); + }); + test('Renders accessible name on selectable card input when selectableActions.selectableActionAriaLabelledby is passed', () => { + const labelingId = 'labelling-id'; + const accessibleName = 'Accessible name'; + render( + + +
{accessibleName}
+
+
+ ); + + expect(screen.getByRole('checkbox')).toHaveAccessibleName(accessibleName); + }); + test('Renders accessible name on clickable card clickable element when selectableActions.selectableActionAriaLabel is passed', () => { + const accessibleName = 'Accessible name'; + render( + + Test + + ); + + expect(screen.getByRole('link')).toHaveAccessibleName(accessibleName); + }); + test('Renders accessible name on clickable card clickable element when selectableActions.selectableActionAriaLabelledby is passed', () => { + const labelingId = 'labelling-id'; + const accessibleName = 'Accessible name'; + render( + + +
{accessibleName}
+
+
+ ); + + expect(screen.getByRole('link')).toHaveAccessibleName(accessibleName); + }); +}); diff --git a/packages/react-core/src/components/Card/examples/CardClickable.tsx b/packages/react-core/src/components/Card/examples/CardClickable.tsx index 30b595f2c56..3c0ef1c1bfd 100644 --- a/packages/react-core/src/components/Card/examples/CardClickable.tsx +++ b/packages/react-core/src/components/Card/examples/CardClickable.tsx @@ -4,10 +4,6 @@ import { Card, CardHeader, CardTitle, CardBody, Checkbox, Gallery } from '@patte export const CardClickable: React.FunctionComponent = () => { const [isSecondary, setIsSecondary] = React.useState(false); - const id1 = 'clickable-card-input-1'; - const id2 = 'clickable-card-input-2'; - const id3 = 'clickable-card-input-3'; - const toggleVariant = (checked: boolean) => { setIsSecondary(checked); }; @@ -24,44 +20,38 @@ export const CardClickable: React.FunctionComponent = () => { />
- + console.log(`${id1} clicked`), - selectableActionId: id1, - selectableActionAriaLabelledby: 'clickable-card-example-1', - name: 'clickable-card-example' + onClickAction: () => console.log(`First card in actionable example clicked`), + selectableActionAriaLabelledby: 'clickable-card-example-title-1' }} > - First card + First card in the actionable example This card performs an action on click. - + - Second card + Second card in the actionable example This card can navigate to a link on click. - + console.log(`${id3} clicked`), - selectableActionId: id3, - selectableActionAriaLabelledby: 'clickable-card-example-3', - name: 'clickable-card-example' + onClickAction: () => console.log(`Third card in actionable example clicked`), + selectableActionAriaLabelledby: 'clickable-card-example-title-3' }} > - Third card + Third card in the actionable example This card is clickable but disabled. diff --git a/packages/react-core/src/components/Card/examples/CardClickableSelectable.tsx b/packages/react-core/src/components/Card/examples/CardClickableSelectable.tsx index 76226a796fb..c72516ff21f 100644 --- a/packages/react-core/src/components/Card/examples/CardClickableSelectable.tsx +++ b/packages/react-core/src/components/Card/examples/CardClickableSelectable.tsx @@ -61,7 +61,8 @@ export const CardClickable: React.FunctionComponent = () => { selectableActionId: id1, selectableActionAriaLabelledby: 'clickable-selectable-card-example-1', name: id1, - onChange + onChange, + hasNoOffset: true }} > @@ -84,7 +85,8 @@ export const CardClickable: React.FunctionComponent = () => { selectableActionId: id2, selectableActionAriaLabelledby: 'clickable-selectable-card-example-2', name: id2, - onChange + onChange, + hasNoOffset: true }} > Second Card @@ -110,7 +112,8 @@ export const CardClickable: React.FunctionComponent = () => { selectableActionId: id3, selectableActionAriaLabelledby: 'clickable-selectable-card-example-3', name: id3, - onChange + onChange, + hasNoOffset: true }} > diff --git a/packages/react-core/src/components/Card/examples/CardSelectable.tsx b/packages/react-core/src/components/Card/examples/CardSelectable.tsx index cb32f98bac6..83aac5c128f 100644 --- a/packages/react-core/src/components/Card/examples/CardSelectable.tsx +++ b/packages/react-core/src/components/Card/examples/CardSelectable.tsx @@ -53,7 +53,8 @@ export const SelectableCard: React.FunctionComponent = () => { selectableActionId: id1, selectableActionAriaLabelledby: 'selectable-card-example-1', name: id1, - onChange + onChange, + hasNoOffset: true }} > First card @@ -71,7 +72,8 @@ export const SelectableCard: React.FunctionComponent = () => { selectableActionId: id2, selectableActionAriaLabelledby: 'selectable-card-example-2', name: id2, - onChange + onChange, + hasNoOffset: true }} > Second card @@ -90,7 +92,8 @@ export const SelectableCard: React.FunctionComponent = () => { selectableActionId: id3, selectableActionAriaLabelledby: 'selectable-card-example-3', name: id3, - onChange + onChange, + hasNoOffset: true }} > Third card diff --git a/packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx b/packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx index b8e599e9575..63db53153e8 100644 --- a/packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx +++ b/packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx @@ -20,7 +20,8 @@ export const SingleSelectableCard: React.FunctionComponent = () => { selectableActionAriaLabelledby: 'single-selectable-card-example-1', name: 'single-selectable-card-example', variant: 'single', - onChange + onChange, + hasNoOffset: true }} > First card @@ -34,7 +35,8 @@ export const SingleSelectableCard: React.FunctionComponent = () => { selectableActionAriaLabelledby: 'single-selectable-card-example-2', name: 'single-selectable-card-example', variant: 'single', - onChange + onChange, + hasNoOffset: true }} > Second card @@ -48,7 +50,8 @@ export const SingleSelectableCard: React.FunctionComponent = () => { selectableActionAriaLabelledby: 'single-selectable-card-example-3', name: 'single-selectable-card-example', variant: 'single', - onChange + onChange, + hasNoOffset: true }} > Third card diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index c0f9fc6184d..323e824cac3 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -23,7 +23,7 @@ "test:a11y": "patternfly-a11y --config patternfly-a11y.config" }, "dependencies": { - "@patternfly/patternfly": "6.0.0-alpha.205", + "@patternfly/patternfly": "6.0.0-alpha.210", "@patternfly/react-charts": "workspace:^", "@patternfly/react-code-editor": "workspace:^", "@patternfly/react-core": "workspace:^", diff --git a/packages/react-icons/package.json b/packages/react-icons/package.json index 33c1e61c6fc..33602049de1 100644 --- a/packages/react-icons/package.json +++ b/packages/react-icons/package.json @@ -33,7 +33,7 @@ "@fortawesome/free-brands-svg-icons": "^5.15.4", "@fortawesome/free-regular-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", - "@patternfly/patternfly": "6.0.0-alpha.205", + "@patternfly/patternfly": "6.0.0-alpha.210", "fs-extra": "^11.2.0", "tslib": "^2.6.2" }, diff --git a/packages/react-integration/cypress/integration/card.spec.ts b/packages/react-integration/cypress/integration/card.spec.ts index 19a8adc49fd..1c20570f996 100644 --- a/packages/react-integration/cypress/integration/card.spec.ts +++ b/packages/react-integration/cypress/integration/card.spec.ts @@ -61,9 +61,9 @@ describe('Card Demo Test', () => { }); it('Verify clickable only card action is triggered', () => { - cy.get('#clickable-card-drawer').should('not.have.class', 'pf-m-expanded'); - cy.get('#clickable-card-example-1').click(); - cy.get('#clickable-card-drawer').should('have.class', 'pf-m-expanded'); + cy.get('#clickable-card-example-1').should('not.have.class', 'pf-m-current'); + cy.get('#clickable-card-example-1 .pf-v6-c-card__clickable-action').click(); + cy.get('#clickable-card-example-1').should('have.class', 'pf-m-current'); }); it('Verify clickable only card link is navigated to', () => { diff --git a/packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx index c9914db2178..9cf4c53ccd8 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx +++ b/packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx @@ -28,7 +28,7 @@ interface CardDemoState { selectableChecked1: boolean; selectableChecked2: boolean; singleSelectableChecked: string; - drawerIsExpanded: boolean; + isCardClicked: boolean; selectableClickableChecked: boolean; selectableClickableSelected: boolean; selectaleClickableDrawerIsExpanded: boolean; @@ -44,7 +44,7 @@ class CardDemo extends Component { selectableChecked1: false, selectableChecked2: false, singleSelectableChecked: '', - drawerIsExpanded: false, + isCardClicked: false, selectableClickableChecked: false, selectableClickableSelected: false, selectaleClickableDrawerIsExpanded: false @@ -117,7 +117,7 @@ class CardDemo extends Component { selectableChecked1, selectableChecked2, singleSelectableChecked, - drawerIsExpanded, + isCardClicked, selectableClickableChecked, selectableClickableSelected, selectaleClickableDrawerIsExpanded @@ -259,35 +259,21 @@ class CardDemo extends Component { This card is single selectable.

-
- - - Clickable card drawer panel - - } - > - - - { - this.setState({ drawerIsExpanded: !drawerIsExpanded }); - }, - selectableActionId: 'clickable-card-input-1', - selectableActionAriaLabelledby: 'clickable-card-example-1', - name: 'clickable-card-example-1' - }} - > - Clickable card with action - - This card performs an action on click. - - - - -
+ + { + this.setState({ isCardClicked: !isCardClicked }); + }, + selectableActionId: 'clickable-card-input-1', + selectableActionAriaLabelledby: 'clickable-card-example-1', + name: 'clickable-card-example-1' + }} + > + Clickable card with action + + This card performs an action on click. +