@@ -9,6 +9,7 @@ import { Button } from '../Button';
99import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon' ;
1010import { Radio } from '../Radio' ;
1111import { Checkbox } from '../Checkbox' ;
12+ import { GenerateId } from '../../helpers/GenerateId/GenerateId' ;
1213
1314export interface CardHeaderActionsObject {
1415 /** Actions of the card header */
@@ -87,122 +88,122 @@ export const CardHeader: React.FunctionComponent<CardHeaderProps> = ({
8788 toggleButtonProps,
8889 isToggleRightAligned,
8990 ...props
90- } : CardHeaderProps ) => {
91- const uniqueId = React . useId ( ) ;
92-
93- return (
94- < CardContext . Consumer >
95- { ( { cardId, isClickable, isSelectable, isSelected, isDisabled : isCardDisabled } ) => {
96- const cardHeaderToggle = (
97- < div className = { css ( styles . cardHeaderToggle ) } >
98- < Button
99- variant = "plain"
100- type = "button"
101- onClick = { ( evt ) => {
102- onExpand ( evt , cardId ) ;
103- } }
104- { ...toggleButtonProps }
105- icon = {
106- < span className = { css ( styles . cardHeaderToggleIcon ) } >
107- < AngleRightIcon />
108- </ span >
109- }
110- />
111- </ div >
112- ) ;
113-
114- const isClickableOrSelectableOnly = ( isClickable && ! isSelectable ) || ( isSelectable && ! isClickable ) ;
115- if ( actions ?. actions && isClickableOrSelectableOnly ) {
116- // eslint-disable-next-line no-console
117- console . error (
118- `Card: ${
119- isClickable ? 'Clickable' : 'Selectable'
120- } only cards should not contain any other actions. If you wish to include additional actions, use a clickable and selectable card.`
91+ } : CardHeaderProps ) => (
92+ < GenerateId >
93+ { ( randomId ) => (
94+ < CardContext . Consumer >
95+ { ( { cardId, isClickable, isSelectable, isSelected, isDisabled : isCardDisabled } ) => {
96+ const cardHeaderToggle = (
97+ < div className = { css ( styles . cardHeaderToggle ) } >
98+ < Button
99+ variant = "plain"
100+ type = "button"
101+ onClick = { ( evt ) => {
102+ onExpand ( evt , cardId ) ;
103+ } }
104+ { ...toggleButtonProps }
105+ icon = {
106+ < span className = { css ( styles . cardHeaderToggleIcon ) } >
107+ < AngleRightIcon />
108+ </ span >
109+ }
110+ />
111+ </ div >
121112 ) ;
122- }
123113
124- const isClickableOnlyCard = isClickable && ! isSelectable ;
125- if (
126- ( isClickableOnlyCard || isSelectable ) &&
127- ! selectableActions ?. selectableActionAriaLabel &&
128- ! selectableActions ?. selectableActionAriaLabelledby
129- ) {
130- // eslint-disable-next-line no-console
131- console . error (
132- `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.`
133- ) ;
134- }
114+ const isClickableOrSelectableOnly = ( isClickable && ! isSelectable ) || ( isSelectable && ! isClickable ) ;
115+ if ( actions ?. actions && isClickableOrSelectableOnly ) {
116+ // eslint-disable-next-line no-console
117+ console . error (
118+ `Card: ${
119+ isClickable ? 'Clickable' : 'Selectable'
120+ } only cards should not contain any other actions. If you wish to include additional actions, use a clickable and selectable card.`
121+ ) ;
122+ }
135123
136- const SelectableCardInput = selectableActions ?. variant === 'single' ? Radio : Checkbox ;
137- const getSelectableProps = ( ) => ( {
138- className : css ( 'pf-m-standalone' ) ,
139- inputClassName : css ( selectableActions ?. isHidden && 'pf-v6-screen-reader' ) ,
140- label : < > </ > ,
141- 'aria-label' : selectableActions . selectableActionAriaLabel ,
142- 'aria-labelledby' : selectableActions . selectableActionAriaLabelledby ,
143- id : selectableActions . selectableActionId ?? `card-selectable-${ uniqueId } ` ,
144- name : selectableActions . name ,
145- isDisabled : isCardDisabled ,
146- onChange : selectableActions . onChange ,
147- isChecked : selectableActions . isChecked ?? isSelected ,
148- ...selectableActions . selectableActionProps
149- } ) ;
124+ const isClickableOnlyCard = isClickable && ! isSelectable ;
125+ if (
126+ ( isClickableOnlyCard || isSelectable ) &&
127+ ! selectableActions ?. selectableActionAriaLabel &&
128+ ! selectableActions ?. selectableActionAriaLabelledby
129+ ) {
130+ // eslint-disable-next-line no-console
131+ console . error (
132+ `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.`
133+ ) ;
134+ }
150135
151- const isClickableLinkCard = selectableActions ?. to !== undefined ;
152- const ClickableCardComponent = isClickableLinkCard ? 'a' : 'button' ;
153- const getClickableProps = ( ) => {
154- const isDisabledLinkCard = isCardDisabled && isClickableLinkCard ;
155- const baseProps = {
156- className : css (
157- 'pf-v6-c-card__clickable-action' ,
158- isDisabledLinkCard && styles . modifiers . disabled ,
159- selectableActions ?. isHidden && 'pf-v6-screen-reader'
160- ) ,
161- id : selectableActions . selectableActionId ,
136+ const SelectableCardInput = selectableActions ?. variant === 'single' ? Radio : Checkbox ;
137+ const getSelectableProps = ( ) => ( {
138+ className : css ( 'pf-m-standalone' ) ,
139+ inputClassName : css ( selectableActions ?. isHidden && 'pf-v6-screen-reader' ) ,
140+ label : < > </ > ,
162141 'aria-label' : selectableActions . selectableActionAriaLabel ,
163142 'aria-labelledby' : selectableActions . selectableActionAriaLabelledby ,
143+ id : selectableActions . selectableActionId ?? `card-selectable-${ randomId } ` ,
144+ name : selectableActions . name ,
145+ isDisabled : isCardDisabled ,
146+ onChange : selectableActions . onChange ,
147+ isChecked : selectableActions . isChecked ?? isSelected ,
164148 ...selectableActions . selectableActionProps
165- } ;
149+ } ) ;
166150
167- if ( isClickableLinkCard ) {
168- return {
169- ...baseProps ,
170- href : selectableActions . to ,
171- ...( isCardDisabled && { tabIndex : - 1 , 'aria-disabled' : true } ) ,
172- ...( selectableActions . isExternalLink && { target : '_blank' } )
151+ const isClickableLinkCard = selectableActions ?. to !== undefined ;
152+ const ClickableCardComponent = isClickableLinkCard ? 'a' : 'button' ;
153+ const getClickableProps = ( ) => {
154+ const isDisabledLinkCard = isCardDisabled && isClickableLinkCard ;
155+ const baseProps = {
156+ className : css (
157+ 'pf-v6-c-card__clickable-action' ,
158+ isDisabledLinkCard && styles . modifiers . disabled ,
159+ selectableActions ?. isHidden && 'pf-v6-screen-reader'
160+ ) ,
161+ id : selectableActions . selectableActionId ,
162+ 'aria-label' : selectableActions . selectableActionAriaLabel ,
163+ 'aria-labelledby' : selectableActions . selectableActionAriaLabelledby ,
164+ ...selectableActions . selectableActionProps
173165 } ;
174- }
175166
176- return { ...baseProps , type : 'button' , disabled : isCardDisabled , onClick : selectableActions . onClickAction } ;
177- } ;
167+ if ( isClickableLinkCard ) {
168+ return {
169+ ...baseProps ,
170+ href : selectableActions . to ,
171+ ...( isCardDisabled && { tabIndex : - 1 , 'aria-disabled' : true } ) ,
172+ ...( selectableActions . isExternalLink && { target : '_blank' } )
173+ } ;
174+ }
178175
179- return (
180- < div
181- className = { css ( styles . cardHeader , isToggleRightAligned && styles . modifiers . toggleRight , className ) }
182- id = { id }
183- { ...props }
184- >
185- { onExpand && ! isToggleRightAligned && cardHeaderToggle }
186- { ( actions || ( selectableActions && ( isClickable || isSelectable ) ) ) && (
187- < CardActions
188- className = { actions ?. className }
189- hasNoOffset = { actions ?. hasNoOffset || selectableActions ?. hasNoOffset }
190- >
191- { actions ?. actions }
192- { selectableActions && ( isClickable || isSelectable ) && (
193- < CardSelectableActions className = { selectableActions ?. className } >
194- { isSelectable && < SelectableCardInput { ...getSelectableProps ( ) } /> }
195- { isClickableOnlyCard && < ClickableCardComponent { ...getClickableProps ( ) } /> }
196- </ CardSelectableActions >
197- ) }
198- </ CardActions >
199- ) }
200- { children && < CardHeaderMain > { children } </ CardHeaderMain > }
201- { onExpand && isToggleRightAligned && cardHeaderToggle }
202- </ div >
203- ) ;
204- } }
205- </ CardContext . Consumer >
206- ) ;
207- } ;
176+ return { ...baseProps , type : 'button' , disabled : isCardDisabled , onClick : selectableActions . onClickAction } ;
177+ } ;
178+
179+ return (
180+ < div
181+ className = { css ( styles . cardHeader , isToggleRightAligned && styles . modifiers . toggleRight , className ) }
182+ id = { id }
183+ { ...props }
184+ >
185+ { onExpand && ! isToggleRightAligned && cardHeaderToggle }
186+ { ( actions || ( selectableActions && ( isClickable || isSelectable ) ) ) && (
187+ < CardActions
188+ className = { actions ?. className }
189+ hasNoOffset = { actions ?. hasNoOffset || selectableActions ?. hasNoOffset }
190+ >
191+ { actions ?. actions }
192+ { selectableActions && ( isClickable || isSelectable ) && (
193+ < CardSelectableActions className = { selectableActions ?. className } >
194+ { isSelectable && < SelectableCardInput { ...getSelectableProps ( ) } /> }
195+ { isClickableOnlyCard && < ClickableCardComponent { ...getClickableProps ( ) } /> }
196+ </ CardSelectableActions >
197+ ) }
198+ </ CardActions >
199+ ) }
200+ { children && < CardHeaderMain > { children } </ CardHeaderMain > }
201+ { onExpand && isToggleRightAligned && cardHeaderToggle }
202+ </ div >
203+ ) ;
204+ } }
205+ </ CardContext . Consumer >
206+ ) }
207+ </ GenerateId >
208+ ) ;
208209CardHeader . displayName = 'CardHeader' ;
0 commit comments