Skip to content

Commit

Permalink
Updated API to have isSelected control selectable card state
Browse files Browse the repository at this point in the history
  • Loading branch information
thatblindgeye committed Mar 28, 2024
1 parent 989894a commit 8bfd525
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 26 deletions.
7 changes: 5 additions & 2 deletions packages/react-core/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export interface CardProps extends React.HTMLProps<HTMLElement>, OUIAProps {
isSelectableRaised?: boolean;
/** Flag indicating that the card is clickable and contains some action that triggers on click. */
isClickable?: boolean;
/** Flag indicating whether a card that is both clickable and selectable is currently selected and has selected styling.
* This will not determine the card's actual selected state.
/** Flag indicating whether a card that is either selectable only or both clickable and selectable is
* currently selected and has selected styling.
*/
isSelected?: boolean;
/** Flag indicating whether a card that is either only clickable or that is both clickable and selectable
Expand Down Expand Up @@ -62,6 +62,7 @@ interface CardContextProps {
isExpanded: boolean;
isClickable: boolean;
isSelectable: boolean;
isSelected: boolean;
isClicked: boolean;
isDisabled: boolean;
// TODO: Remove hasSelectableInput when deprecated prop is removed
Expand All @@ -79,6 +80,7 @@ export const CardContext = React.createContext<Partial<CardContextProps>>({
isExpanded: false,
isClickable: false,
isSelectable: false,
isSelected: false,
isClicked: false,
isDisabled: false
});
Expand Down Expand Up @@ -175,6 +177,7 @@ export const Card: React.FunctionComponent<CardProps> = ({
isExpanded,
isClickable,
isSelectable,
isSelected,
isClicked,
isDisabled,
// TODO: Remove hasSelectableInput when deprecated prop is removed
Expand Down
9 changes: 6 additions & 3 deletions packages/react-core/src/components/Card/CardHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ export interface CardHeaderSelectableActionsObject {
isExternalLink?: boolean;
/** Name for the input element of a clickable or selectable card. */
name?: string;
/** Flag indicating whether the selectable card input is checked */
/** @deprecated Flag indicating whether the selectable card input is checked. We recommend using
* the isSelected prop on the card component instead.
*/
isChecked?: boolean;
}

Expand Down Expand Up @@ -80,7 +82,7 @@ export const CardHeader: React.FunctionComponent<CardHeaderProps> = ({
}: CardHeaderProps) => (
<CardContext.Consumer>
{/* TODO: Remove hasSelectableInput when deprecated props are removed */}
{({ cardId, isClickable, isSelectable, isClicked, isDisabled: isCardDisabled, hasSelectableInput }) => {
{({ cardId, isClickable, isSelectable, isSelected, isClicked, isDisabled: isCardDisabled, hasSelectableInput }) => {
const cardHeaderToggle = (
<div className={css(styles.cardHeaderToggle)}>
<Button
Expand Down Expand Up @@ -130,12 +132,13 @@ export const CardHeader: React.FunctionComponent<CardHeaderProps> = ({
name: selectableActions.name,
isDisabled: isCardDisabled
};
const isSelectableInputChecked = selectableActions.isChecked ?? isSelected;

if (isClickable && !isSelectable) {
return { ...baseProps, onClick: handleActionClick, isChecked: isClicked };
}
if (isSelectable) {
return { ...baseProps, onChange: selectableActions.onChange, isChecked: selectableActions.isChecked };
return { ...baseProps, onChange: selectableActions.onChange, isChecked: isSelectableInputChecked };
}

return baseProps;
Expand Down
2 changes: 1 addition & 1 deletion packages/react-core/src/components/Card/examples/Card.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ When a group of single selectable cards are related, you must pass the same `nam

### Actionable

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.
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`.

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).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ export const CardClickable: React.FunctionComponent = () => {
const [isChecked1, setIsChecked1] = React.useState(false);
const [isChecked2, setIsChecked2] = React.useState(false);
const [isChecked3, setIsChecked3] = React.useState(false);
const [isSelected1, setIsSelected1] = React.useState(false);
const [isClicked, setIsClicked] = React.useState(false);

const id1 = 'clickable-selectable-card-input-1';
const id2 = 'clickable-selectable-card-input-2';
const id3 = 'clickable-selectable-card-input-3';

const onClick = () => {
setIsSelected1((prevState) => !prevState);
setIsClicked((prevState) => !prevState);
};

const onChange = (event: React.FormEvent<HTMLInputElement>, checked: boolean) => {
Expand All @@ -33,13 +33,18 @@ export const CardClickable: React.FunctionComponent = () => {

return (
<React.Fragment>
<Card id="clickable-selectable-card-example-1" isClickable isSelectable isSelected={isSelected1}>
<Card
id="clickable-selectable-card-example-1"
isClickable
isClicked={isClicked}
isSelectable
isSelected={isChecked1}
>
<CardHeader
selectableActions={{
selectableActionId: id1,
selectableActionAriaLabelledby: 'clickable-selectable-card-example-1',
name: id1,
isChecked: isChecked1,
onChange
}}
>
Expand All @@ -51,13 +56,12 @@ export const CardClickable: React.FunctionComponent = () => {
</CardHeader>
<CardBody>This card performs an action upon clicking the card title and is selectable.</CardBody>
</Card>
<Card id="clickable-selectable-card-example-2" isClickable isSelectable>
<Card id="clickable-selectable-card-example-2" isClickable isSelectable isSelected={isChecked2}>
<CardHeader
selectableActions={{
selectableActionId: id2,
selectableActionAriaLabelledby: 'clickable-selectable-card-example-2',
name: id2,
isChecked: isChecked2,
onChange
}}
>
Expand All @@ -71,13 +75,12 @@ export const CardClickable: React.FunctionComponent = () => {
.
</CardBody>
</Card>
<Card id="clickable-selectable-card-example-3" isClickable isSelectable isDisabled>
<Card id="clickable-selectable-card-example-3" isClickable isSelectable isDisabled isSelected={isChecked3}>
<CardHeader
selectableActions={{
selectableActionId: id3,
selectableActionAriaLabelledby: 'clickable-selectable-card-example-3',
name: id3,
isChecked: isChecked3,
onChange
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,38 @@ export const SelectableCard: React.FunctionComponent = () => {

return (
<React.Fragment>
<Card id="selectable-card-example-1" isSelectable>
<Card id="selectable-card-example-1" isSelectable isSelected={isChecked1}>
<CardHeader
selectableActions={{
selectableActionId: id1,
selectableActionAriaLabelledby: 'selectable-card-example-1',
name: id1,
isChecked: isChecked1,
onChange
}}
>
<CardTitle>First card</CardTitle>
</CardHeader>
<CardBody>This card is selectable.</CardBody>
</Card>
<Card id="selectable-card-example-2" isSelectable>
<Card id="selectable-card-example-2" isSelectable isSelected={isChecked2}>
<CardHeader
selectableActions={{
selectableActionId: id2,
selectableActionAriaLabelledby: 'selectable-card-example-2',
name: id2,
isChecked: isChecked2,
onChange
}}
>
<CardTitle>Second card</CardTitle>
</CardHeader>
<CardBody>This card is selectable.</CardBody>
</Card>
<Card id="selectable-card-example-3" isSelectable isDisabled>
<Card id="selectable-card-example-3" isSelectable isDisabled isSelected={isChecked3}>
<CardHeader
selectableActions={{
selectableActionId: id3,
selectableActionAriaLabelledby: 'selectable-card-example-3',
name: id3,
isChecked: isChecked3,
onChange
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,41 @@ export const SingleSelectableCard: React.FunctionComponent = () => {

return (
<React.Fragment>
<Card id="single-selectable-card-example-1" isSelectable>
<Card id="single-selectable-card-example-1" isSelectable isSelected={isChecked === id1}>
<CardHeader
selectableActions={{
selectableActionId: id1,
selectableActionAriaLabelledby: 'single-selectable-card-example-1',
name: 'single-selectable-card-example',
variant: 'single',
isChecked: isChecked === id1,
onChange
}}
>
<CardTitle>First card</CardTitle>
</CardHeader>
<CardBody>This card is single selectable.</CardBody>
</Card>
<Card id="single-selectable-card-example-2" isSelectable>
<Card id="single-selectable-card-example-2" isSelectable isSelected={isChecked === id2}>
<CardHeader
selectableActions={{
selectableActionId: id2,
selectableActionAriaLabelledby: 'single-selectable-card-example-2',
name: 'single-selectable-card-example',
variant: 'single',
isChecked: isChecked === id2,
onChange
}}
>
<CardTitle>Second card</CardTitle>
</CardHeader>
<CardBody>This card is single selectable.</CardBody>
</Card>
<Card id="single-selectable-card-example-3" isSelectable isDisabled>
<Card id="single-selectable-card-example-3" isSelectable isDisabled isSelected={isChecked === id3}>
<CardHeader
selectableActions={{
selectableActionId: id3,
selectableActionAriaLabelledby: 'single-selectable-card-example-3',
name: 'single-selectable-card-example',
variant: 'single',
isChecked: isChecked === id3,
onChange
}}
>
Expand Down

0 comments on commit 8bfd525

Please sign in to comment.