diff --git a/packages/react-core/src/demos/Card/Card.md b/packages/react-core/src/demos/Card/Card.md
index c5669cfbd54..5c3cfb3316e 100644
--- a/packages/react-core/src/demos/Card/Card.md
+++ b/packages/react-core/src/demos/Card/Card.md
@@ -27,701 +27,5 @@ This demonstrates how you can assemble a full page view that contains a grid of
### Card view
-```js isFullscreen
-import React from 'react';
-import {
- Badge,
- Bullseye,
- Button,
- Card,
- CardHeader,
- CardTitle,
- CardBody,
- Checkbox,
- Divider,
- Dropdown,
- DropdownItem,
- DropdownList,
- EmptyState,
- EmptyStateHeader,
- EmptyStateIcon,
- EmptyStateFooter,
- EmptyStateVariant,
- EmptyStateActions,
- Gallery,
- MenuToggle,
- MenuToggleCheckbox,
- OverflowMenu,
- OverflowMenuControl,
- OverflowMenuDropdownItem,
- OverflowMenuItem,
- PageSection,
- PageSectionVariants,
- Pagination,
- TextContent,
- Text,
- Title,
- Toolbar,
- ToolbarItem,
- ToolbarFilter,
- ToolbarContent,
- Select,
- SelectList,
- SelectOption
-} from '@patternfly/react-core';
-import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
-import DashboardWrapper from '@patternfly/react-core/src/demos/examples/DashboardWrapper';
-
-import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon';
-import TrashIcon from '@patternfly/react-icons/dist/esm/icons/trash-icon';
-import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon';
-import pfIcon from './pf-logo-small.svg';
-import activeMQIcon from './activemq-core_200x150.png';
-import avroIcon from './camel-avro_200x150.png';
-import dropBoxIcon from './camel-dropbox_200x150.png';
-import infinispanIcon from './camel-infinispan_200x150.png';
-import saxonIcon from './camel-saxon_200x150.png';
-import sparkIcon from './camel-spark_200x150.png';
-import swaggerIcon from './camel-swagger-java_200x150.png';
-import azureIcon from './FuseConnector_Icons_AzureServices.png';
-import restIcon from './FuseConnector_Icons_REST.png';
-import { data } from './CardData.jsx';
-
-class CardViewBasic extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- filters: {
- products: []
- },
- cardData: data,
- isChecked: false,
- selectedItems: [],
- areAllSelected: false,
- isUpperToolbarDropdownOpen: false,
- isUpperToolbarKebabDropdownOpen: false,
- isLowerToolbarDropdownOpen: false,
- isLowerToolbarKebabDropdownOpen: false,
- isCardKebabDropdownOpen: false,
- activeItem: 0,
- splitButtonDropdownIsOpen: false,
- page: 1,
- perPage: 10,
- totalItemCount: 10
- };
-
- this.checkAllSelected = (selected, total) => {
- if (selected && selected < total) {
- return null;
- }
- return selected === total;
- };
-
- this.onToolbarDropdownToggle = () => {
- this.setState((prevState) => ({
- isLowerToolbarDropdownOpen: !prevState.isLowerToolbarDropdownOpen
- }));
- };
-
- this.onToolbarKebabDropdownToggle = () => {
- this.setState({
- isOpen: !this.state.isLowerToolbarKebabDropdownOpen
- });
- };
-
- this.onToolbarKebabDropdownSelect = (event) => {
- this.setState({
- isLowerToolbarKebabDropdownOpen: !this.state.isLowerToolbarKebabDropdownOpen
- });
- };
-
- this.onCardKebabDropdownToggle = (key, event) => {
- event?.stopPropagation();
- this.setState((prevState) => ({
- [key]: !prevState[key]
- }));
- };
-
- this.onCardKebabDropdownSelect = (key, event) => {
- this.setState({
- [key]: !this.state[key]
- });
- };
-
- this.deleteItem = (item) => (event) => {
- const filter = (getter) => (val) => getter(val) !== item.id;
- this.setState({
- cardData: this.state.cardData.filter(filter(({ id }) => id)),
- selectedItems: this.state.selectedItems.filter(filter((id) => id))
- });
- };
-
- this.onSetPage = (_event, pageNumber) => {
- this.setState({
- page: pageNumber
- });
- };
-
- this.onPerPageSelect = (_event, perPage) => {
- this.setState({
- perPage,
- page: 1
- });
- };
-
- this.onSplitButtonToggle = () => {
- this.setState((prevState) => ({
- splitButtonDropdownIsOpen: !prevState.splitButtonDropdownIsOpen
- }));
- };
-
- this.onSplitButtonSelect = () => {
- this.setState({
- splitButtonDropdownIsOpen: false
- });
- };
-
- this.onNameSelect = (event, selection) => {
- const checked = event.target.checked;
- this.setState((prevState) => {
- const prevSelections = prevState.filters['products'];
- return {
- filters: {
- ...prevState.filters,
- ['products']: checked
- ? [...prevSelections, selection]
- : prevSelections.filter((value) => value !== selection)
- }
- };
- });
- };
-
- this.onDelete = (type = '', id = '') => {
- if (type) {
- this.setState((prevState) => {
- prevState.filters[type.toLowerCase()] = prevState.filters[type.toLowerCase()].filter((s) => s !== id);
- return {
- filters: prevState.filters
- };
- });
- } else {
- this.setState({
- filters: {
- products: []
- }
- });
- }
- };
-
- this.onKeyDown = (event, productId) => {
- if (event.target !== event.currentTarget) {
- return;
- }
- if ([' ', 'Enter'].includes(event.key)) {
- event.preventDefault();
- this.setState((prevState) => {
- return prevState.selectedItems.includes(productId * 1)
- ? {
- selectedItems: [...prevState.selectedItems.filter((id) => productId * 1 != id)],
- areAllSelected: this.checkAllSelected(prevState.selectedItems.length - 1, prevState.totalItemCount)
- }
- : {
- selectedItems: [...prevState.selectedItems, productId * 1],
- areAllSelected: this.checkAllSelected(prevState.selectedItems.length + 1, prevState.totalItemCount)
- };
- });
- }
- };
-
- this.onClick = (productId) => {
- this.setState((prevState) => {
- return prevState.selectedItems.includes(productId * 1)
- ? {
- selectedItems: [...prevState.selectedItems.filter((id) => productId * 1 != id)],
- areAllSelected: this.checkAllSelected(prevState.selectedItems.length - 1, prevState.totalItemCount)
- }
- : {
- selectedItems: [...prevState.selectedItems, productId * 1],
- areAllSelected: this.checkAllSelected(prevState.selectedItems.length + 1, prevState.totalItemCount)
- };
- });
- };
- }
-
- selectedItems(e) {
- const { value, checked } = e.target;
- let { selectedItems } = this.state;
-
- if (checked) {
- selectedItems = [...selectedItems, value];
- } else {
- selectedItems = selectedItems.filter((el) => el !== value);
- if (this.state.areAllSelected) {
- this.setState({
- areAllSelected: !this.state.areAllSelected
- });
- }
- }
- this.setState({ selectedItems });
- }
-
- splitCheckboxSelectAll(e) {
- const { checked } = e.target;
- const { isChecked, cardData } = this.state;
- let collection = [];
-
- if (checked) {
- for (var i = 0; i <= 9; i++) collection = [...collection, i];
- }
-
- this.setState(
- {
- selectedItems: collection,
- isChecked: isChecked,
- areAllSelected: checked
- },
- this.updateSelected
- );
- }
-
- selectPage(e) {
- const { checked } = e.target;
- const { isChecked, totalItemCount, perPage } = this.state;
- let collection = [];
-
- collection = this.getAllItems();
-
- this.setState(
- {
- selectedItems: collection,
- isChecked: checked,
- areAllSelected: totalItemCount === perPage ? true : false
- },
- this.updateSelected
- );
- }
-
- selectAll(e) {
- const { checked } = e.target;
- const { isChecked } = this.state;
-
- let collection = [];
- for (var i = 0; i <= 9; i++) collection = [...collection, i];
-
- this.setState(
- {
- selectedItems: collection,
- isChecked: true,
- areAllSelected: true
- },
- this.updateSelected
- );
- }
-
- selectNone(e) {
- const { checked } = e.target;
- const { isChecked, selectedItems } = this.state;
- this.setState(
- {
- selectedItems: [],
- isChecked: false,
- areAllSelected: false
- },
- this.updateSelected
- );
- }
-
- getAllItems() {
- const { cardData } = this.state;
- const collection = [];
- for (const items of cardData) {
- collection.push(items.id);
- }
-
- return collection;
- }
-
- updateSelected() {
- const { cardData, selectedItems } = this.state;
- let rows = cardData.map((post) => {
- post.selected = selectedItems.includes(post.id);
- return post;
- });
-
- this.setState({
- cardData: rows
- });
- }
-
- renderPagination() {
- const { page, perPage, totalItemCount, cardData } = this.state;
-
- const defaultPerPageOptions = [
- {
- title: '1',
- value: 1
- },
- {
- title: '5',
- value: 5
- },
- {
- title: '10',
- value: 10
- }
- ];
-
- return (
-
- );
- }
-
- buildSelectDropdown() {
- const { splitButtonDropdownIsOpen, selectedItems, areAllSelected, filters, cardData } = this.state;
- const numSelected = selectedItems.length;
- const allSelected = areAllSelected;
- const anySelected = numSelected > 0;
- const someChecked = anySelected ? null : false;
- const isChecked = allSelected ? true : someChecked;
- const splitButtonDropdownItems = (
- <>
-
- Select none (0 items)
-
-
- Select page ({this.state.perPage} items)
-
-
- Select all ({this.state.totalItemCount} items)
-
- >
- );
- return (
- this.setState({ splitButtonDropdownIsOpen: isOpen })}
- toggle={(toggleRef) => (
-
- {numSelected !== 0 && `${numSelected} selected`}
-
- ]
- }}
- >
- )}
- >
- {splitButtonDropdownItems}
-
- );
- }
-
- buildFilterDropdown() {
- const { isLowerToolbarDropdownOpen, filters } = this.state;
-
- const filterDropdownItems = (
-
-
- PatternFly
-
-
- ActiveMQ
-
-
- Apache Spark
-
-
- Avro
-
-
- Azure Services
-
-
- Crypto
-
-
- DropBox
-
-
- JBoss Data Grid
-
-
- REST
-
-
- SWAGGER
-
-
- );
-
- return (
-
-
-
- );
- }
-
- render() {
- const {
- isUpperToolbarDropdownOpen,
- isLowerToolbarDropdownOpen,
- isUpperToolbarKebabDropdownOpen,
- isLowerToolbarKebabDropdownOpen,
- isCardKebabDropdownOpen,
- splitButtonDropdownIsOpen,
- activeItem,
- filters,
- cardData,
- checked,
- selectedItems,
- areAllSelected,
- isChecked,
- page,
- perPage
- } = this.state;
-
- const toolbarKebabDropdownItems = [
-
- Link
- ,
-
- Action
- ,
-
- Disabled Link
- ,
-
- Disabled Action
- ,
- ,
-
- Separated Link
- ,
-
- Separated Action
-
- ];
-
- const toolbarItems = (
-
- {this.buildSelectDropdown()}
- {this.buildFilterDropdown()}
-
-
-
-
-
-
- (
-
-
-
- )}
- isOpen={isLowerToolbarKebabDropdownOpen}
- onOpenChange={(isOpen) => this.setState({ isLowerToolbarKebabDropdownOpen: isOpen })}
- >
- {toolbarKebabDropdownItems}
-
-
-
-
-
- {this.renderPagination()}
-
-
- );
-
- const icons = {
- pfIcon,
- activeMQIcon,
- sparkIcon,
- avroIcon,
- azureIcon,
- saxonIcon,
- dropBoxIcon,
- infinispanIcon,
- restIcon,
- swaggerIcon
- };
-
- const filtered =
- filters.products.length > 0
- ? data.filter((card) => {
- return filters.products.length === 0 || filters.products.includes(card.name);
- })
- : cardData.slice((page - 1) * perPage, perPage === 1 ? page * perPage : page * perPage - 1);
-
- return (
-
-
-
-
- Projects
- This is a demo that showcases PatternFly cards.
-
-
- {toolbarItems}
-
-
-
-
-
-
-
- }
- />
-
-
-
-
-
-
-
-
- {filtered.map((product, key) => (
- this.onKeyDown(e, product.id)}
- onClick={() => this.onClick(product.id)}
- onSelectableInputChange={() => this.onClick(product.id)}
- isSelected={selectedItems.includes(product.id)}
- >
-
- this.setState({ [key]: isOpen })}
- toggle={(toggleRef: React.Ref) => (
- this.onCardKebabDropdownToggle(key, e)}
- isExpanded={this.state[key]}
- >
-
-
- )}
- popperProps={{ position: 'right' }}
- >
-
-
-
- Delete
-
-
-
-
- >
- )
- }}
- >
-
-
- {product.name}
- {product.description}
-
- ))}
-
-
-
-
-
-
-
- );
- }
-}
+```js file="../examples/Card/CardView.tsx" isFullscreen
```
diff --git a/packages/react-core/src/demos/PrimaryDetail.md b/packages/react-core/src/demos/PrimaryDetail.md
index 32be47f1363..fad31736e70 100644
--- a/packages/react-core/src/demos/PrimaryDetail.md
+++ b/packages/react-core/src/demos/PrimaryDetail.md
@@ -534,10 +534,9 @@ class PrimaryDetailCardView extends React.Component {
id={'card-view-' + key}
onKeyDown={this.onKeyDown}
onClick={this.onCardClick}
- onSelectableInputChange={this.onChange}
- isSelectableRaised
- isSelected={activeCard === 'card-view-' + key}
- hasSelectableInput
+ isClickable
+ isSelectable
+ isSelected={activeCard?.charAt(activeCard.length - 1) === key.toString()}
>
- this.onCheckboxClick(event, product.id)}
- value={product.id}
- isChecked={selectedItems.includes(product.id)}
- aria-label="card checkbox example"
- id={`check-${product.id}`}
- />
>
)
}}
+ selectableActions={{
+ isChecked: selectedItems.includes(product.id),
+ selectableActionAriaLabelledby: `${'card-view-' + key}`,
+ selectableActionId: `selectable-actions-item-${product.id}`,
+ name: `check-${product.id}`,
+ onChange: this.state.onCardClick
+ }}
>
diff --git a/packages/react-core/src/demos/examples/Card/CardView.tsx b/packages/react-core/src/demos/examples/Card/CardView.tsx
new file mode 100644
index 00000000000..b2e0b6d0c59
--- /dev/null
+++ b/packages/react-core/src/demos/examples/Card/CardView.tsx
@@ -0,0 +1,583 @@
+import React from 'react';
+import DashboardWrapper from '@patternfly/react-core/src/demos/examples/DashboardWrapper';
+import {
+ Badge,
+ Bullseye,
+ Button,
+ Card,
+ CardHeader,
+ CardTitle,
+ CardBody,
+ Divider,
+ Dropdown,
+ DropdownItem,
+ DropdownList,
+ EmptyState,
+ EmptyStateHeader,
+ EmptyStateIcon,
+ EmptyStateFooter,
+ EmptyStateVariant,
+ EmptyStateActions,
+ Gallery,
+ MenuToggle,
+ MenuToggleCheckbox,
+ OverflowMenu,
+ OverflowMenuControl,
+ OverflowMenuDropdownItem,
+ OverflowMenuItem,
+ PageSection,
+ PageSectionVariants,
+ Pagination,
+ TextContent,
+ Text,
+ Toolbar,
+ ToolbarItem,
+ ToolbarFilter,
+ ToolbarContent,
+ Select,
+ SelectList,
+ SelectOption,
+ MenuToggleElement
+} from '@patternfly/react-core';
+import { data } from '../../Card/CardData';
+import TrashIcon from '@patternfly/react-icons/dist/esm/icons/trash-icon';
+import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon';
+import pfIcon from './pf-logo-small.svg';
+import activeMQIcon from './../Card/activemq-core_200x150.png';
+import avroIcon from './../camel-avro_200x150.png';
+import dropBoxIcon from './../camel-dropbox_200x150.png';
+import infinispanIcon from './../camel-infinispan_200x150.png';
+import saxonIcon from './../camel-saxon_200x150.png';
+import sparkIcon from './../camel-spark_200x150.png';
+import swaggerIcon from './../camel-swagger-java_200x150.png';
+import azureIcon from './../FuseConnector_Icons_AzureServices.png';
+import restIcon from './../FuseConnector_Icons_REST.png';
+import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
+
+export const CardViewBasic: React.FunctionComponent = () => {
+ const totalItemCount = 10;
+
+ const [cardData, setCardData] = React.useState(data);
+ const [isChecked, setIsChecked] = React.useState(false);
+ const [selectedItems, setSelectedItems] = React.useState([]);
+ const [areAllSelected, setAreAllSelected] = React.useState(false);
+ const [splitButtonDropdownIsOpen, setSplitButtonDropdownIsOpen] = React.useState(false);
+ const [isLowerToolbarDropdownOpen, setIsLowerToolbarDropdownOpen] = React.useState(false);
+ const [isLowerToolbarKebabDropdownOpen, setIsLowerToolbarKebabDropdownOpen] = React.useState(false);
+ const [page, setPage] = React.useState(1);
+ const [perPage, setPerPage] = React.useState(10);
+ const [filters, setFilters] = React.useState>({ products: [] });
+ const [state, setState] = React.useState({});
+
+ interface ProductType {
+ id: number;
+ name: string;
+ icon: string;
+ description: string;
+ }
+ const checkAllSelected = (selected: number, total: number) => {
+ if (selected && selected < total) {
+ return null;
+ }
+ return selected === total;
+ };
+
+ const onToolbarDropdownToggle = () => {
+ setIsLowerToolbarDropdownOpen(!isLowerToolbarDropdownOpen);
+ };
+
+ const onToolbarKebabDropdownToggle = () => {
+ setIsLowerToolbarKebabDropdownOpen(!isLowerToolbarKebabDropdownOpen);
+ };
+
+ const onToolbarKebabDropdownSelect = () => {
+ setIsLowerToolbarKebabDropdownOpen(!isLowerToolbarKebabDropdownOpen);
+ };
+
+ const onCardKebabDropdownToggle = (
+ event: React.MouseEvent | React.MouseEvent,
+ key: string
+ ) => {
+ event?.stopPropagation();
+ setState({
+ [key]: !state[key as keyof Object]
+ });
+ };
+
+ const deleteItem = (item: ProductType) => {
+ const filter = (getter) => (val) => getter(val) !== item.id;
+
+ setCardData(cardData.filter(filter(({ id }) => id)));
+
+ setSelectedItems(selectedItems.filter(filter((id) => id)));
+ };
+
+ const onSetPage = (_event: any, pageNumber: number) => {
+ setPage(pageNumber);
+ };
+
+ const onPerPageSelect = (_event: any, perPage: number) => {
+ setPerPage(perPage);
+ setPage(1);
+ };
+
+ const onSplitButtonToggle = () => {
+ setSplitButtonDropdownIsOpen(!splitButtonDropdownIsOpen);
+ };
+
+ const onSplitButtonSelect = () => {
+ setSplitButtonDropdownIsOpen(false);
+ };
+
+ const onNameSelect = (event: any, selection = '') => {
+ const checked = event.target.checked;
+ const prevSelections = filters.products;
+
+ setFilters({
+ ...filters,
+ products: checked ? [...prevSelections, selection] : prevSelections.filter((value) => value !== selection)
+ });
+ };
+
+ const onDelete = (type = '', _id = '') => {
+ if (type) {
+ setFilters(filters);
+ } else {
+ setFilters({ products: [] });
+ }
+ };
+
+ const onChange = (event: React.FormEvent) => {
+ const name = event.currentTarget.name;
+ const productId = Number(name.charAt(name.length - 1));
+
+ if (selectedItems.includes(productId * 1)) {
+ setSelectedItems(selectedItems.filter((id) => productId * 1 !== id));
+
+ const checkAll = checkAllSelected(selectedItems.length - 1, totalItemCount);
+ setAreAllSelected(!!checkAll);
+ } else {
+ setSelectedItems([...selectedItems, productId * 1]);
+ const checkAll = checkAllSelected(selectedItems.length + 1, totalItemCount);
+ setAreAllSelected(!!checkAll);
+ }
+ };
+
+ const updateSelected = () => {
+ const rows = cardData.map((post) => {
+ post.selected = selectedItems.includes(post.id);
+ return post;
+ });
+
+ setCardData(rows);
+ };
+
+ const getAllItems = () => {
+ const collection: number[] = [];
+ for (const items of cardData) {
+ collection.push(items.id);
+ }
+
+ return collection;
+ };
+
+ const splitCheckboxSelectAll = (e: any) => {
+ let collection: number[] = [];
+
+ if (e.target.checked) {
+ for (let i = 0; i <= 9; i++) {
+ collection = [...collection, i];
+ }
+ }
+
+ setSelectedItems(collection);
+ setIsChecked(isChecked);
+ setAreAllSelected(e.target.checked);
+
+ updateSelected();
+ };
+
+ const selectPage = (e: { target: { checked: any } }) => {
+ const { checked } = e.target;
+ let collection: number[] = [];
+
+ collection = getAllItems();
+
+ setSelectedItems(collection);
+ setIsChecked(checked);
+ setAreAllSelected(totalItemCount === perPage ? true : false);
+
+ updateSelected();
+ };
+
+ const selectAll = () => {
+ let collection: number[] = [];
+ for (let i = 0; i <= 9; i++) {
+ collection = [...collection, i];
+ }
+
+ setSelectedItems(collection);
+ setIsChecked(true);
+ setAreAllSelected(true);
+
+ updateSelected();
+ };
+
+ const selectNone = () => {
+ setSelectedItems([]);
+ setIsChecked(false);
+ setAreAllSelected(false);
+
+ updateSelected();
+ };
+
+ const renderPagination = () => {
+ const defaultPerPageOptions = [
+ {
+ title: '1',
+ value: 1
+ },
+ {
+ title: '5',
+ value: 5
+ },
+ {
+ title: '10',
+ value: 10
+ }
+ ];
+
+ return (
+
+ );
+ };
+
+ const buildSelectDropdown = () => {
+ const numSelected = selectedItems.length;
+ const anySelected = numSelected > 0;
+ const splitButtonDropdownItems = (
+ <>
+
+ Select none (0 items)
+
+
+ Select page ({perPage} items)
+
+
+ Select all ({totalItemCount} items)
+
+ >
+ );
+ return (
+ setSplitButtonDropdownIsOpen(isOpen)}
+ toggle={(toggleRef) => (
+ splitCheckboxSelectAll(e)}
+ >
+ {numSelected !== 0 && `${numSelected} selected`}
+
+ ]
+ }}
+ >
+ )}
+ >
+ {splitButtonDropdownItems}
+
+ );
+ };
+
+ const buildFilterDropdown = () => {
+ const filterDropdownItems = (
+
+
+ PatternFly
+
+
+ ActiveMQ
+
+
+ Apache Spark
+
+
+ Avro
+
+
+ Azure Services
+
+
+ Crypto
+
+
+ DropBox
+
+
+ JBoss Data Grid
+
+
+ REST
+
+
+ SWAGGER
+
+
+ );
+
+ return (
+ onDelete(type as string, id as string)}
+ >
+
+
+ );
+ };
+
+ const toolbarKebabDropdownItems = [
+
+ Link
+ ,
+
+ Action
+ ,
+
+ Disabled Link
+ ,
+
+ Disabled Action
+ ,
+ ,
+
+ Separated Link
+ ,
+
+ Separated Action
+
+ ];
+
+ const toolbarItems = (
+
+ {buildSelectDropdown()}
+ {buildFilterDropdown()}
+
+
+
+
+
+
+ (
+
+
+
+ )}
+ isOpen={isLowerToolbarKebabDropdownOpen}
+ onOpenChange={(isOpen) => setIsLowerToolbarDropdownOpen(isOpen)}
+ >
+ {toolbarKebabDropdownItems}
+
+
+
+
+
+ {renderPagination()}
+
+
+ );
+
+ const icons = {
+ pfIcon,
+ activeMQIcon,
+ sparkIcon,
+ avroIcon,
+ azureIcon,
+ saxonIcon,
+ dropBoxIcon,
+ infinispanIcon,
+ restIcon,
+ swaggerIcon
+ };
+
+ const filtered =
+ filters.products.length > 0
+ ? data.filter((card: { name: string }) => filters.products.length === 0 || filters.products.includes(card.name))
+ : cardData.slice((page - 1) * perPage, perPage === 1 ? page * perPage : page * perPage - 1);
+
+ return (
+
+
+
+
+ Projects
+ This is a demo that showcases PatternFly cards.
+
+
+ {toolbarItems}
+
+
+
+
+
+
+
+ }
+ />
+
+
+
+
+
+
+
+
+ {filtered.map((product, key) => (
+
+
+ setState({ [key]: isOpen })}
+ toggle={(toggleRef: React.Ref) => (
+ {
+ onCardKebabDropdownToggle(e, key.toString());
+ }}
+ isExpanded={!!state[key]}
+ >
+
+
+ )}
+ popperProps={{ position: 'right' }}
+ >
+
+ {
+ deleteItem(product);
+ }}
+ >
+
+ Delete
+
+
+
+ >
+ )
+ }}
+ >
+
+
+ {product.name}
+ {product.description}
+
+ ))}
+
+
+
+
+
+
+
+ );
+};