Skip to content

Commit

Permalink
fix(TagOverflowModal): resolve merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
anamikaanu96 committed May 29, 2024
2 parents 5914d16 + d8efc8f commit 2491a0d
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 63 deletions.
31 changes: 31 additions & 0 deletions e2e/components/FilterPanel/FilterPanel-test.avt.e2e.js
Original file line number Diff line number Diff line change
@@ -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');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 *;
33 changes: 21 additions & 12 deletions packages/ibm-products/src/components/TagOverflow/TagOverflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ const componentName = 'TagOverflow';

const allTagsModalSearchThreshold = 10;

// TODO: support prop overflowType

// Default values for props
const defaults = {
items: [],
Expand Down Expand Up @@ -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);
Expand All @@ -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 (
<div
{
Expand All @@ -211,23 +219,23 @@ export let TagOverflow = React.forwardRef(
{...getDevtoolsProps(componentName)}
>
{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 (
<div
ref={(node) => itemRefHandler(item.id, node)}
key={item.id}
>
<Tooltip align="bottom" label={item.label}>
<div ref={(node) => itemRefHandler(id, node)} key={id}>
<Tooltip align={overflowAlign} label={label}>
<Tag
{...other}
className={`${blockClass}__item--tag`}
type={item.tagType}
type={tagType}
onClose={() => handleTagOnClose(onClose, index)}
>
{item.label}
{label}
</Tag>
</Tooltip>
</div>
Expand Down Expand Up @@ -256,6 +264,7 @@ export let TagOverflow = React.forwardRef(
open={showAllModalOpen}
title={allTagsModalTitle}
onClose={handleModalClose}
overflowType={overflowType}
searchLabel={allTagsModalSearchLabel}
searchPlaceholder={allTagsModalSearchPlaceholderText}
portalTarget={allTagsModalTarget}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 (
<div style={{ width: containerWidth }} ref={ref}>
<TagOverflow
{...args}
items={liveTags}
allTagsModalTarget={
allTagsModalTargetCustomDomNode ? ref.current : undefined
}
/>
</div>
);
};

export const InteractiveTags = TemplateWithClose.bind({});
InteractiveTags.args = {
items: tags,
containerWidth: 500,
...overflowAndModalStrings,
};
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ interface TagOverflowModalProps {
className?: string;
onClose?: () => void;
open?: boolean;
overflowType?: 'default' | 'tag';
portalTarget?: ReactNode;
searchLabel?: string;
searchPlaceholder?: string;
Expand All @@ -53,6 +54,7 @@ export const TagOverflowModal = ({
title,
onClose,
open,
overflowType,
portalTarget: portalTargetIn,
searchLabel = defaults.searchLabel,
searchPlaceholder,
Expand All @@ -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) => {
Expand Down Expand Up @@ -119,11 +105,14 @@ export const TagOverflowModal = ({
/>
</ModalHeader>
<ModalBody className={`${blockClass}__body`} hasForm>
{getFilteredItems().map(({ label, id, ...other }) => (
<Tag {...other} filter={false} key={id}>
{label}
</Tag>
))}
{getFilteredItems().map(({ label, id, filter, ...other }) => {
const isFilterable = overflowType === 'tag' ? filter : false;
return (
<Tag {...other} key={id} filter={isFilterable}>
{label}
</Tag>
);
})}
</ModalBody>
<div className={`${blockClass}__fade`} />
</ComposedModal>
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,29 +102,39 @@ export const TagOverflowPopover = React.forwardRef(
<PopoverContent>
<div ref={overflowTagContent} className={`${blockClass}__content`}>
<ul className={`${blockClass}__tag-list`}>
{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 (
<li
className={cx(`${blockClass}__tag-item`, {
[`${blockClass}__tag-item--default`]:
overflowType === 'default',
[`${blockClass}__tag-item--tag`]:
overflowType === 'tag',
})}
key={id}
>
{overflowType === 'tag' ? (
<Tag
{...other}
onClose={() => onClose?.()}
type={typeValue}
filter={isFilterable}
>
{label}
</Tag>
) : (
label
)}
</li>
);
}
return (
<li
className={cx(`${blockClass}__tag-item`, {
[`${blockClass}__tag-item--default`]:
overflowType === 'default',
[`${blockClass}__tag-item--tag`]:
overflowType === 'tag',
})}
key={tag.id}
>
{tag.label}
{/* {React.cloneElement(tag, tagProps)} */}
</li>
);
})}
)}
</ul>
{overflowTags.length > allTagsModalSearchThreshold && (
<Link
Expand Down

0 comments on commit 2491a0d

Please sign in to comment.