Skip to content

Commit 0bb8e59

Browse files
author
Eric Olkowski
committed
Updated API to have isSelected control selectable card state
1 parent c090826 commit 0bb8e59

File tree

7 files changed

+66
-29
lines changed

7 files changed

+66
-29
lines changed

packages/react-core/src/components/Card/Card.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ export interface CardProps extends React.HTMLProps<HTMLElement>, OUIAProps {
1818
isSelectable?: boolean;
1919
/** Flag indicating that the card is clickable and contains some action that triggers on click. */
2020
isClickable?: boolean;
21-
/** Flag indicating whether a card that is both clickable and selectable is currently selected and has selected styling.
22-
* This will not determine the card's actual selected state.
21+
/** Flag indicating whether a card that is either selectable only or both clickable and selectable is
22+
* currently selected and has selected styling.
2323
*/
2424
isSelected?: boolean;
2525
/** Flag indicating whether a card that is either only clickable or that is both clickable and selectable
@@ -49,6 +49,7 @@ interface CardContextProps {
4949
isExpanded: boolean;
5050
isClickable: boolean;
5151
isSelectable: boolean;
52+
isSelected: boolean;
5253
isClicked: boolean;
5354
isDisabled: boolean;
5455
}
@@ -58,6 +59,7 @@ export const CardContext = React.createContext<Partial<CardContextProps>>({
5859
isExpanded: false,
5960
isClickable: false,
6061
isSelectable: false,
62+
isSelected: false,
6163
isClicked: false,
6264
isDisabled: false
6365
});
@@ -119,6 +121,7 @@ export const Card: React.FunctionComponent<CardProps> = ({
119121
isExpanded,
120122
isClickable,
121123
isSelectable,
124+
isSelected,
122125
isClicked,
123126
isDisabled
124127
}}

packages/react-core/src/components/Card/CardHeader.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ export interface CardHeaderSelectableActionsObject {
4444
isExternalLink?: boolean;
4545
/** Name for the input element of a clickable or selectable card. */
4646
name?: string;
47-
/** Flag indicating whether the selectable card input is checked */
47+
/** @deprecated Flag indicating whether the selectable card input is checked. We recommend using
48+
* the isSelected prop on the card component instead.
49+
*/
4850
isChecked?: boolean;
4951
}
5052

@@ -79,7 +81,7 @@ export const CardHeader: React.FunctionComponent<CardHeaderProps> = ({
7981
...props
8082
}: CardHeaderProps) => (
8183
<CardContext.Consumer>
82-
{({ cardId, isClickable, isSelectable, isClicked, isDisabled: isCardDisabled }) => {
84+
{({ cardId, isClickable, isSelectable, isSelected, isClicked, isDisabled: isCardDisabled }) => {
8385
const cardHeaderToggle = (
8486
<div className={css(styles.cardHeaderToggle)}>
8587
<Button
@@ -126,6 +128,7 @@ export const CardHeader: React.FunctionComponent<CardHeaderProps> = ({
126128
name: selectableActions.name,
127129
isDisabled: isCardDisabled
128130
};
131+
const isSelectableInputChecked = selectableActions.isChecked ?? isSelected;
129132

130133
if (isClickable && !isSelectable) {
131134
return {
@@ -135,7 +138,7 @@ export const CardHeader: React.FunctionComponent<CardHeaderProps> = ({
135138
};
136139
}
137140
if (isSelectable) {
138-
return { ...baseProps, onChange: selectableActions.onChange, isChecked: selectableActions.isChecked };
141+
return { ...baseProps, onChange: selectableActions.onChange, isChecked: isSelectableInputChecked };
139142
}
140143

141144
return baseProps;

packages/react-core/src/components/Card/examples/Card.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ When a group of single selectable cards are related, you must pass the same `nam
133133

134134
### Actionable
135135

136-
An actionable card can perform an action or navigate to a link by clicking anywhere within the card. You can also pass in the `isExternalLink` property to `selectableActions` if you want an actionable card's link to open in a new tab or window.
136+
An actionable card can perform an action or navigate to a link by clicking anywhere within the card. To open a link in a new tab or window, pass the `isExternalLink` property to `selectableActions`.
137137

138138
You can pass the `isClicked` property to `<Card>` to convey that a card is the currently clicked one, such as when clicking a card would open a [primary-detail view](/patterns/primary-detail). This must not be used simply for "selection" of a card, and you should instead use our [selectable card](#selectable) or [single selectable card](#single-selectable).
139139

packages/react-core/src/components/Card/examples/CardClickableSelectable.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ export const CardClickable: React.FunctionComponent = () => {
55
const [isChecked1, setIsChecked1] = React.useState(false);
66
const [isChecked2, setIsChecked2] = React.useState(false);
77
const [isChecked3, setIsChecked3] = React.useState(false);
8-
const [isSelected1, setIsSelected1] = React.useState(false);
8+
const [isClicked, setIsClicked] = React.useState(false);
99
const [isSecondary, setIsSecondary] = React.useState<boolean>(false);
1010

1111
const id1 = 'clickable-selectable-card-input-1';
1212
const id2 = 'clickable-selectable-card-input-2';
1313
const id3 = 'clickable-selectable-card-input-3';
1414

1515
const onClick = () => {
16-
setIsSelected1((prevState) => !prevState);
16+
setIsClicked((prevState) => !prevState);
1717
};
1818

1919
const onChange = (event: React.FormEvent<HTMLInputElement>, checked: boolean) => {
@@ -52,15 +52,15 @@ export const CardClickable: React.FunctionComponent = () => {
5252
id="clickable-selectable-card-example-1"
5353
isClickable
5454
isSelectable
55-
isSelected={isSelected1}
55+
isSelected={isChecked1}
56+
isClicked={isClicked}
5657
variant={isSecondary ? 'secondary' : 'default'}
5758
>
5859
<CardHeader
5960
selectableActions={{
6061
selectableActionId: id1,
6162
selectableActionAriaLabelledby: 'clickable-selectable-card-example-1',
6263
name: id1,
63-
isChecked: isChecked1,
6464
onChange
6565
}}
6666
>
@@ -76,14 +76,14 @@ export const CardClickable: React.FunctionComponent = () => {
7676
id="clickable-selectable-card-example-2"
7777
isClickable
7878
isSelectable
79+
isSelected={isChecked2}
7980
variant={isSecondary ? 'secondary' : 'default'}
8081
>
8182
<CardHeader
8283
selectableActions={{
8384
selectableActionId: id2,
8485
selectableActionAriaLabelledby: 'clickable-selectable-card-example-2',
8586
name: id2,
86-
isChecked: isChecked2,
8787
onChange
8888
}}
8989
>
@@ -102,14 +102,14 @@ export const CardClickable: React.FunctionComponent = () => {
102102
isClickable
103103
isSelectable
104104
isDisabled
105+
isSelected={isChecked3}
105106
variant={isSecondary ? 'secondary' : 'default'}
106107
>
107108
<CardHeader
108109
selectableActions={{
109110
selectableActionId: id3,
110111
selectableActionAriaLabelledby: 'clickable-selectable-card-example-3',
111112
name: id3,
112-
isChecked: isChecked3,
113113
onChange
114114
}}
115115
>

packages/react-core/src/components/Card/examples/CardSelectable.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,41 +42,54 @@ export const SelectableCard: React.FunctionComponent = () => {
4242
/>
4343
<div style={{ marginTop: '15px' }}>
4444
<Gallery hasGutter>
45-
<Card id="selectable-card-example-1" isSelectable variant={isSecondary ? 'secondary' : 'default'}>
45+
<Card
46+
id="selectable-card-example-1"
47+
isSelectable
48+
isSelected={isChecked1}
49+
variant={isSecondary ? 'secondary' : 'default'}
50+
>
4651
<CardHeader
4752
selectableActions={{
4853
selectableActionId: id1,
4954
selectableActionAriaLabelledby: 'selectable-card-example-1',
5055
name: id1,
51-
isChecked: isChecked1,
5256
onChange
5357
}}
5458
>
5559
<CardTitle>First card</CardTitle>
5660
</CardHeader>
5761
<CardBody>This card is selectable.</CardBody>
5862
</Card>
59-
<Card id="selectable-card-example-2" isSelectable variant={isSecondary ? 'secondary' : 'default'}>
63+
<Card
64+
id="selectable-card-example-2"
65+
isSelectable
66+
isSelected={isChecked2}
67+
variant={isSecondary ? 'secondary' : 'default'}
68+
>
6069
<CardHeader
6170
selectableActions={{
6271
selectableActionId: id2,
6372
selectableActionAriaLabelledby: 'selectable-card-example-2',
6473
name: id2,
65-
isChecked: isChecked2,
6674
onChange
6775
}}
6876
>
6977
<CardTitle>Second card</CardTitle>
7078
</CardHeader>
7179
<CardBody>This card is selectable.</CardBody>
7280
</Card>
73-
<Card id="selectable-card-example-3" isSelectable isDisabled variant={isSecondary ? 'secondary' : 'default'}>
81+
<Card
82+
id="selectable-card-example-3"
83+
isSelectable
84+
isDisabled
85+
isSelected={isChecked3}
86+
variant={isSecondary ? 'secondary' : 'default'}
87+
>
7488
<CardHeader
7589
selectableActions={{
7690
selectableActionId: id3,
7791
selectableActionAriaLabelledby: 'selectable-card-example-3',
7892
name: id3,
79-
isChecked: isChecked3,
8093
onChange
8194
}}
8295
>

packages/react-core/src/components/Card/examples/CardSingleSelectable.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,44 +13,41 @@ export const SingleSelectableCard: React.FunctionComponent = () => {
1313

1414
return (
1515
<Gallery hasGutter>
16-
<Card id="single-selectable-card-example-1" isSelectable>
16+
<Card id="single-selectable-card-example-1" isSelectable isSelected={isChecked === id1}>
1717
<CardHeader
1818
selectableActions={{
1919
selectableActionId: id1,
2020
selectableActionAriaLabelledby: 'single-selectable-card-example-1',
2121
name: 'single-selectable-card-example',
2222
variant: 'single',
23-
isChecked: isChecked === id1,
2423
onChange
2524
}}
2625
>
2726
<CardTitle>First card</CardTitle>
2827
</CardHeader>
2928
<CardBody>This card is single selectable.</CardBody>
3029
</Card>
31-
<Card id="single-selectable-card-example-2" isSelectable>
30+
<Card id="single-selectable-card-example-2" isSelectable isSelected={isChecked === id2}>
3231
<CardHeader
3332
selectableActions={{
3433
selectableActionId: id2,
3534
selectableActionAriaLabelledby: 'single-selectable-card-example-2',
3635
name: 'single-selectable-card-example',
3736
variant: 'single',
38-
isChecked: isChecked === id2,
3937
onChange
4038
}}
4139
>
4240
<CardTitle>Second card</CardTitle>
4341
</CardHeader>
4442
<CardBody>This card is single selectable.</CardBody>
4543
</Card>
46-
<Card id="single-selectable-card-example-3" isSelectable isDisabled>
44+
<Card id="single-selectable-card-example-3" isSelectable isDisabled isSelected={isChecked === id3}>
4745
<CardHeader
4846
selectableActions={{
4947
selectableActionId: id3,
5048
selectableActionAriaLabelledby: 'single-selectable-card-example-3',
5149
name: 'single-selectable-card-example',
5250
variant: 'single',
53-
isChecked: isChecked === id3,
5451
onChange
5552
}}
5653
>

packages/react-integration/demo-app-ts/src/components/demos/CardDemo/CardDemo.tsx

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ interface CardDemoState {
2626
isOpen: boolean;
2727
selectableChecked1: boolean;
2828
selectableChecked2: boolean;
29+
singleSelectableChecked: string;
2930
drawerIsExpanded: boolean;
3031
selectableClickableChecked: boolean;
3132
selectableClickableSelected: boolean;
3233
selectaleClickableDrawerIsExpanded: boolean;
3334
}
3435

35-
export class CardDemo extends Component {
36+
class CardDemo extends Component {
3637
static displayName = 'CardDemo';
3738

3839
state: CardDemoState = {
@@ -41,6 +42,7 @@ export class CardDemo extends Component {
4142
isOpen: false,
4243
selectableChecked1: false,
4344
selectableChecked2: false,
45+
singleSelectableChecked: '',
4446
drawerIsExpanded: false,
4547
selectableClickableChecked: false,
4648
selectableClickableSelected: false,
@@ -94,6 +96,10 @@ export class CardDemo extends Component {
9496
}
9597
};
9698

99+
onSingleSelectableChange = (event: React.FormEvent<HTMLInputElement>) => {
100+
this.setState({ singleSelectableChecked: (event.target as HTMLElement).id });
101+
};
102+
97103
onSelectableClickableChange = (_event: React.FormEvent<HTMLInputElement>, checked: boolean) => {
98104
this.setState({ selectableClickableChecked: checked });
99105
};
@@ -109,6 +115,7 @@ export class CardDemo extends Component {
109115
const {
110116
selectableChecked1,
111117
selectableChecked2,
118+
singleSelectableChecked,
112119
drawerIsExpanded,
113120
selectableClickableChecked,
114121
selectableClickableSelected,
@@ -213,26 +220,36 @@ export class CardDemo extends Component {
213220
<CardBody>This card is selectable.</CardBody>
214221
</Card>
215222
<br></br>
216-
<Card id="single-selectable-card-example-1" isSelectable>
223+
<Card
224+
id="single-selectable-card-example-1"
225+
isSelectable
226+
isSelected={singleSelectableChecked === 'single-selectable-card-input-1'}
227+
>
217228
<CardHeader
218229
selectableActions={{
219230
selectableActionId: 'single-selectable-card-input-1',
220231
selectableActionAriaLabelledby: 'single-selectable-card-example-1',
221232
name: 'single-selectable-card-example',
222-
variant: 'single'
233+
variant: 'single',
234+
onChange: this.onSingleSelectableChange
223235
}}
224236
>
225237
<CardTitle>First single selectable card</CardTitle>
226238
</CardHeader>
227239
<CardBody>This card is single selectable.</CardBody>
228240
</Card>
229-
<Card id="single-selectable-card-example-2" isSelectable>
241+
<Card
242+
id="single-selectable-card-example-2"
243+
isSelectable
244+
isSelected={singleSelectableChecked === 'single-selectable-card-input-2'}
245+
>
230246
<CardHeader
231247
selectableActions={{
232248
selectableActionId: 'single-selectable-card-input-2',
233249
selectableActionAriaLabelledby: 'single-selectable-card-example-2',
234250
name: 'single-selectable-card-example',
235-
variant: 'single'
251+
variant: 'single',
252+
onChange: this.onSingleSelectableChange
236253
}}
237254
>
238255
<CardTitle>Second single selectable card</CardTitle>
@@ -325,3 +342,7 @@ export class CardDemo extends Component {
325342
);
326343
}
327344
}
345+
346+
CardDemo.displayName = 'CardDemo';
347+
348+
export { CardDemo };

0 commit comments

Comments
 (0)