diff --git a/e2e/components/FilterPanel/FilterPanel-test.avt.e2e.js b/e2e/components/FilterPanel/FilterPanel-test.avt.e2e.js
new file mode 100644
index 0000000000..cd02c0d459
--- /dev/null
+++ b/e2e/components/FilterPanel/FilterPanel-test.avt.e2e.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright IBM Corp. 2024, 2024
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+import { expect, test } from '@playwright/test';
+import { visitStory } from '../../test-utils/storybook';
+import { carbon } from '../../../packages/ibm-products/src/settings';
+
+test.describe('FilterPanel @avt', () => {
+ test('@avt-default-state', async ({ page }) => {
+ await visitStory(page, {
+ component: 'FilterPanel',
+ id: 'ibm-products-components-filter-panel-filterpanel--default',
+ globals: {
+ carbonTheme: 'white',
+ },
+ });
+
+ await page.click(`.${carbon.prefix}--accordion__heading`);
+ await page
+ .locator(`.${carbon.prefix}--accordion__item--active`)
+ .screenshot({ animations: 'disabled' });
+
+ await expect(page).toHaveNoACViolations('FilterPanel @avt-default-state');
+ });
+});
diff --git a/packages/ibm-products-styles/src/components/TagOverflow/_tag-overflow.scss b/packages/ibm-products-styles/src/components/TagOverflow/_tag-overflow.scss
index aa042accc3..b152b5ae79 100644
--- a/packages/ibm-products-styles/src/components/TagOverflow/_tag-overflow.scss
+++ b/packages/ibm-products-styles/src/components/TagOverflow/_tag-overflow.scss
@@ -68,6 +68,11 @@ $block-class-modal: #{$block-class}-modal;
max-width: $spacing-09;
}
+.#{c4p-settings.$carbon-prefix}--popover
+ .#{c4p-settings.$carbon-prefix}--popover-content {
+ white-space: normal;
+}
+
.#{$block-class-overflow} {
display: inline-block;
vertical-align: bottom;
@@ -139,8 +144,6 @@ $block-class-modal: #{$block-class}-modal;
margin: 0;
background-color: inherit;
color: inherit;
- text-overflow: ellipsis;
- white-space: nowrap;
}
.#{$block-class-overflow}__tag
diff --git a/packages/ibm-products-styles/src/components/_index-with-carbon.scss b/packages/ibm-products-styles/src/components/_index-with-carbon.scss
index 467f3209af..f816182334 100644
--- a/packages/ibm-products-styles/src/components/_index-with-carbon.scss
+++ b/packages/ibm-products-styles/src/components/_index-with-carbon.scss
@@ -77,3 +77,4 @@
@use './FilterPanel/index-with-carbon' as *;
@use './ConditionBuilder/index-with-carbon' as *;
@use './GetStartedCard/index-with-carbon' as *;
+@use './Guidebanner/index-with-carbon' as *;
diff --git a/packages/ibm-products/src/components/TagOverflow/TagOverflow.js b/packages/ibm-products/src/components/TagOverflow/TagOverflow.js
index eea31b3400..34fee58c90 100644
--- a/packages/ibm-products/src/components/TagOverflow/TagOverflow.js
+++ b/packages/ibm-products/src/components/TagOverflow/TagOverflow.js
@@ -24,8 +24,6 @@ const componentName = 'TagOverflow';
const allTagsModalSearchThreshold = 10;
-// TODO: support prop overflowType
-
// Default values for props
const defaults = {
items: [],
@@ -182,8 +180,8 @@ export let TagOverflow = React.forwardRef(
}
const hiddenItems = items?.slice(visibleItemsArr.length);
- const overflowItemsArr = hiddenItems?.map((item) => {
- return { type: item.tagType, label: item.label, id: item.id };
+ const overflowItemsArr = hiddenItems?.map(({ tagType, ...other }) => {
+ return { type: tagType, ...other };
});
setVisibleItems(visibleItemsArr);
@@ -197,6 +195,16 @@ export let TagOverflow = React.forwardRef(
onOverflowTagChange,
]);
+ const handleTagOnClose = useCallback(
+ (onClose, index) => {
+ onClose?.();
+ if (index <= visibleItems.length - 1) {
+ setPopoverOpen(false);
+ }
+ },
+ [visibleItems]
+ );
+
return (
{visibleItems.length > 0 &&
- visibleItems.map((item) => {
+ visibleItems.map((item, index) => {
// Render custom components
if (tagComponent) {
return getCustomComponent(item);
} else {
+ const { id, label, tagType, onClose, ...other } = item;
// If there is no template prop, then render items as Tags
return (
-
itemRefHandler(item.id, node)}
- key={item.id}
- >
-
+ itemRefHandler(id, node)} key={id}>
+
handleTagOnClose(onClose, index)}
>
- {item.label}
+ {label}
@@ -256,6 +264,7 @@ export let TagOverflow = React.forwardRef(
open={showAllModalOpen}
title={allTagsModalTitle}
onClose={handleModalClose}
+ overflowType={overflowType}
searchLabel={allTagsModalSearchLabel}
searchPlaceholder={allTagsModalSearchPlaceholderText}
portalTarget={allTagsModalTarget}
diff --git a/packages/ibm-products/src/components/TagOverflow/TagOverflow.stories.jsx b/packages/ibm-products/src/components/TagOverflow/TagOverflow.stories.jsx
index 06dc6a678d..578b59857f 100644
--- a/packages/ibm-products/src/components/TagOverflow/TagOverflow.stories.jsx
+++ b/packages/ibm-products/src/components/TagOverflow/TagOverflow.stories.jsx
@@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
-import React from 'react';
+import React, { useState, useRef } from 'react';
import { Theme } from '@carbon/react';
import { pkg } from '../../settings';
@@ -120,3 +120,40 @@ CustomComponentsWithOverflowModal.args = {
tagComponent: IconComponent,
...overflowAndModalStrings,
};
+
+const TemplateWithClose = (argsIn) => {
+ const { containerWidth, allTagsModalTargetCustomDomNode, items, ...args } = {
+ ...argsIn,
+ };
+ const [liveTags, setLiveTags] = useState(
+ items.map((item) => ({
+ ...item,
+ filter: true,
+ onClose: () => handleTagClose(item.label),
+ }))
+ );
+
+ const handleTagClose = (key) => {
+ setLiveTags((prev) => prev.filter((item) => item.label !== key));
+ };
+
+ const ref = useRef();
+ return (
+
+
+
+ );
+};
+
+export const InteractiveTags = TemplateWithClose.bind({});
+InteractiveTags.args = {
+ items: tags,
+ containerWidth: 500,
+ ...overflowAndModalStrings,
+};
diff --git a/packages/ibm-products/src/components/TagOverflow/TagOverflowModal.tsx b/packages/ibm-products/src/components/TagOverflow/TagOverflowModal.tsx
index cef0eab080..107826844f 100644
--- a/packages/ibm-products/src/components/TagOverflow/TagOverflowModal.tsx
+++ b/packages/ibm-products/src/components/TagOverflow/TagOverflowModal.tsx
@@ -39,6 +39,7 @@ interface TagOverflowModalProps {
className?: string;
onClose?: () => void;
open?: boolean;
+ overflowType?: 'default' | 'tag';
portalTarget?: ReactNode;
searchLabel?: string;
searchPlaceholder?: string;
@@ -53,6 +54,7 @@ export const TagOverflowModal = ({
title,
onClose,
open,
+ overflowType,
portalTarget: portalTargetIn,
searchLabel = defaults.searchLabel,
searchPlaceholder,
@@ -64,28 +66,12 @@ export const TagOverflowModal = ({
const renderPortalUse = usePortalTarget(portalTargetIn);
const getFilteredItems = (): AllTags => {
- let newFilteredModalTags: AllTags = [];
- if (open) {
- if (search === '' && allTags) {
- newFilteredModalTags = allTags.slice(0);
- } else {
- const lCaseSearch = search.toLocaleLowerCase();
-
- allTags?.forEach((tag) => {
- const dataSearch = tag['data-search']
- ?.toLocaleLowerCase()
- ?.indexOf(lCaseSearch);
- const labelSearch = tag.label
- ?.toLocaleLowerCase()
- ?.indexOf(lCaseSearch);
-
- if (dataSearch > -1 || labelSearch > -1) {
- newFilteredModalTags.push(tag);
- }
- });
- }
+ if (open && search && allTags) {
+ return allTags.filter((tag) =>
+ tag.label?.toLocaleLowerCase()?.includes(search.toLocaleLowerCase())
+ );
}
- return newFilteredModalTags;
+ return allTags || [];
};
const handleSearch = (evt) => {
@@ -119,11 +105,14 @@ export const TagOverflowModal = ({
/>
- {getFilteredItems().map(({ label, id, ...other }) => (
-
- {label}
-
- ))}
+ {getFilteredItems().map(({ label, id, filter, ...other }) => {
+ const isFilterable = overflowType === 'tag' ? filter : false;
+ return (
+
+ {label}
+
+ );
+ })}
@@ -140,6 +129,7 @@ TagOverflowModal.propTypes = {
className: PropTypes.string,
onClose: PropTypes.func,
open: PropTypes.bool,
+ overflowType: PropTypes.oneOf(['default', 'tag']),
portalTarget: PropTypes.node,
searchLabel: PropTypes.string,
searchPlaceholder: PropTypes.string,
diff --git a/packages/ibm-products/src/components/TagOverflow/TagOverflowPopover.js b/packages/ibm-products/src/components/TagOverflow/TagOverflowPopover.js
index 3d6d596a1a..4aa960fed0 100644
--- a/packages/ibm-products/src/components/TagOverflow/TagOverflowPopover.js
+++ b/packages/ibm-products/src/components/TagOverflow/TagOverflowPopover.js
@@ -102,29 +102,39 @@ export const TagOverflowPopover = React.forwardRef(
- {getOverflowPopoverItems().map((tag) => {
- const tagProps = {};
- if (overflowType === 'tag') {
- tagProps.type = 'high-contrast';
- }
- if (overflowType === 'default') {
- tagProps.filter = false;
+ {getOverflowPopoverItems().map(
+ ({ label, id, tagType, filter, onClose, ...other }) => {
+ const typeValue =
+ overflowType === 'tag' ? 'high-contrast' : tagType;
+ const isFilterable =
+ overflowType === 'tag' ? filter : false;
+
+ return (
+ -
+ {overflowType === 'tag' ? (
+ onClose?.()}
+ type={typeValue}
+ filter={isFilterable}
+ >
+ {label}
+
+ ) : (
+ label
+ )}
+
+ );
}
- return (
- -
- {tag.label}
- {/* {React.cloneElement(tag, tagProps)} */}
-
- );
- })}
+ )}
{overflowTags.length > allTagsModalSearchThreshold && (