Skip to content

Commit

Permalink
feat(tag): updates tags to use DismissibleTag (carbon-design-system#6112
Browse files Browse the repository at this point in the history
)

* feat(tag): updates tags to use DismissibleTag

* feat(tags): depracate filter prop

* fix: tag overflow modal tests

* fix(datagrid): tests label to dismiss

* feat: adds DismissibleTag to index.d.ts

* fix: type errors

* fix: made prop optional

* fix(get-started-card): adds react import for failing avt

---------

Co-authored-by: David Menendez <[email protected]>
  • Loading branch information
AlexanderMelox and davidmenendez authored Oct 22, 2024
1 parent 5b94ed8 commit 18b47c7
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 56 deletions.
17 changes: 11 additions & 6 deletions packages/ibm-products/src/components/AddSelect/AddSelectFilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
//

import React, { useState } from 'react';
import { Button, ButtonSet, Dropdown, Search, Tag, Layer } from '@carbon/react';
import {
Button,
ButtonSet,
Dropdown,
Search,
DismissibleTag,
Layer,
} from '@carbon/react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import { Filter } from '@carbon/react/icons';
Expand Down Expand Up @@ -148,15 +155,13 @@ export let AddSelectFilter = ({
{hasFiltersApplied && (
<div className={`${blockClass}-applied`}>
{Object.keys(appliedFilters).map((filterType) => (
<Tag
<DismissibleTag
key={filterType}
text={`${filterType}: ${appliedFilters[filterType]}`}
type="gray"
size="sm"
onClose={() => removeTag(filterType)}
filter
>
{`${filterType}: ${appliedFilters[filterType]}`}
</Tag>
/>
))}
<Button kind="ghost" size="sm" onClick={clearFilters}>
{clearFiltersText}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2539,15 +2539,13 @@ describe(componentName, () => {
expect(innerContainer.childElementCount).toEqual(1);
});
const findFilterTagAndRemove = async () => {
const filterTagCloseButtons = screen.getAllByLabelText('Clear filter');
const filterTagCloseButtons = screen.getAllByLabelText('Dismiss');
const visibleFilterTags = filterTagCloseButtons.filter((el) =>
el.parentElement.parentElement.classList.contains(
`${pkg.prefix}--tag-set__displayed-tag`
)
el.closest(`.${pkg.prefix}--tag-set__displayed-tag`)
);
await click(visibleFilterTags[0]);
const checkAgainForCloseFilterButton =
screen.queryAllByLabelText('Clear filter');
screen.queryAllByLabelText('Dismiss');
expect(checkAgainForCloseFilterButton).toEqual([]);
};
it('should render initial filters in panel and test close button on filter tag', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { GetStartedCard } from '.';
import React from 'react';
import mdx from './GetStartedCard.mdx';

import { action } from '@storybook/addon-actions';
Expand Down
33 changes: 22 additions & 11 deletions packages/ibm-products/src/components/TagOverflow/TagOverflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import React, {
useRef,
useState,
} from 'react';
import { Tag, Tooltip } from '@carbon/react';
import { Tag, Tooltip, DismissibleTag } from '@carbon/react';

import PropTypes from 'prop-types';
import { TYPES } from './constants';
Expand All @@ -27,9 +27,11 @@ import { getDevtoolsProps } from '../../global/js/utils/devtools';
import { isRequiredIf } from '../../global/js/utils/props-helper';
import { pkg } from '../../settings';
import { useResizeObserver } from '../../global/js/hooks/useResizeObserver';

export interface TagOverflowItem {
className?: string;
/**
* @deprecated The `filter` prop is no longer going to be used. To use DismissibleTags, pass in an onClose function.
*/
filter?: boolean;
id: string;
label: string;
Expand Down Expand Up @@ -273,19 +275,28 @@ export let TagOverflow = forwardRef(
if (tagComponent) {
return getCustomComponent(item, tagComponent);
} else {
const { id, label, tagType, onClose, ...other } = item;
const { id, label, tagType, onClose, filter, ...other } = item;
// If there is no template prop, then render items as Tags
return (
<div ref={(node) => itemRefHandler(id, node)} key={id}>
<Tooltip align={overflowAlign} label={label}>
<Tag
{...other}
className={`${blockClass}__item--tag`}
type={tagType}
onClose={() => handleTagOnClose(onClose, index)}
>
{label}
</Tag>
{typeof onClose === 'function' || filter ? (
<DismissibleTag
{...other}
className={`${blockClass}__item--tag`}
type={tagType}
onClose={() => handleTagOnClose(onClose, index)}
text={label}
/>
) : (
<Tag
{...other}
className={`${blockClass}__item--tag`}
type={tagType}
>
{label}
</Tag>
)}
</Tooltip>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
ModalBody,
Search,
Tag,
DismissibleTag,
} from '@carbon/react';

import { pkg } from '../../settings';
Expand All @@ -41,6 +42,7 @@ interface TagOverflowModalProps {
className?: string;
modalAriaLabel?: string;
onClose?: () => void;
onTagClose?: (params: { label: string; id: any }) => void;
open?: boolean;
overflowType?: 'default' | 'tag';
portalTarget?: ReactNode;
Expand All @@ -57,6 +59,7 @@ export const TagOverflowModal = ({
title,
modalAriaLabel = defaults.modalAriaLabel,
onClose,
onTagClose,
open,
overflowType,
portalTarget: portalTargetIn,
Expand Down Expand Up @@ -114,12 +117,18 @@ export const TagOverflowModal = ({
hasScrollingContent
aria-label={modalAriaLabel}
>
{getFilteredItems().map(({ label, id, filter }) => {
const isFilterable = overflowType === 'tag' ? filter : false;
return (
<Tag key={id} filter={isFilterable}>
{label}
</Tag>
{getFilteredItems().map(({ label, id, filter, onClose }) => {
const isFilterable =
overflowType === 'tag' && (typeof onClose === 'function' || filter);

return isFilterable ? (
<DismissibleTag
key={id}
text={label}
onClose={() => onTagClose?.({ label, id })}
/>
) : (
<Tag key={id}>{label}</Tag>
);
})}
<div className={`${blockClass}__fade`} />
Expand All @@ -137,6 +146,7 @@ TagOverflowModal.propTypes = {
),
className: PropTypes.string,
onClose: PropTypes.func,
onTagClose: PropTypes.func,
open: PropTypes.bool,
overflowType: PropTypes.oneOf(['default', 'tag']),
portalTarget: PropTypes.node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Tag,
Popover,
PopoverContent,
DismissibleTag,
OperationalTag,
} from '@carbon/react';
import { useClickOutside } from '../../global/js/hooks';
Expand Down Expand Up @@ -118,7 +119,26 @@ export const TagOverflowPopover = forwardRef(
const typeValue =
overflowType === 'tag' ? 'high-contrast' : tagType;
const isFilterable =
overflowType === 'tag' ? filter : false;
overflowType === 'tag' &&
(typeof onClose === 'function' || filter);

let tag;
if (isFilterable) {
tag = (
<DismissibleTag
{...other}
onClose={() => onClose?.()}
type={typeValue}
text={label}
/>
);
} else {
tag = (
<Tag {...other} type={typeValue}>
{label}
</Tag>
);
}

return (
<li
Expand All @@ -130,18 +150,7 @@ export const TagOverflowPopover = forwardRef(
})}
key={id}
>
{overflowType === 'tag' ? (
<Tag
{...other}
onClose={() => onClose?.()}
type={typeValue}
filter={isFilterable}
>
{label}
</Tag>
) : (
label
)}
{overflowType === 'tag' ? tag : label}
</li>
);
}
Expand Down
47 changes: 34 additions & 13 deletions packages/ibm-products/src/components/TagSet/TagSet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { getDevtoolsProps } from '../../global/js/utils/devtools';
import { isRequiredIf } from '../../global/js/utils/props-helper';
import { pkg } from '../../settings';
import { useResizeObserver } from '../../global/js/hooks/useResizeObserver';
import { DismissibleTag } from '@carbon/react';

const componentName = 'TagSet';
const blockClass = `${pkg.prefix}--tag-set`;
Expand Down Expand Up @@ -58,6 +59,10 @@ type OverflowType = 'default' | 'tag';
type TagType = {
label: string;
type?: keyof typeof tagTypes;
/**
* @deprecated Use the `onClose` function instead to render as a DismissibleTag
*/
filter?: boolean;
} & TagBaseProps;
export interface TagSetProps extends PropsWithChildren {
/**
Expand Down Expand Up @@ -203,7 +208,7 @@ export let TagSet = React.forwardRef<HTMLDivElement, TagSetProps>(
// create sizing tags
setHiddenSizingTags(
tags && tags.length > 0
? tags.map(({ label, id, ...other }, index) => {
? tags.map(({ label, id, filter, onClose, ...other }, index) => {
return (
<div
key={index}
Expand All @@ -214,12 +219,20 @@ export let TagSet = React.forwardRef<HTMLDivElement, TagSetProps>(
}
}}
>
<Tag
{...other} // ensure id is not duplicated
data-original-id={id}
>
{label}
</Tag>
{typeof onClose === 'function' || filter ? (
<DismissibleTag
{...other}
data-original-id={id}
text={label}
/>
) : (
<Tag
{...other} // ensure id is not duplicated
data-original-id={id}
>
{label}
</Tag>
)}
</div>
);
})
Expand All @@ -243,16 +256,24 @@ export let TagSet = React.forwardRef<HTMLDivElement, TagSetProps>(
// create visible and overflow tags
let newDisplayedTags =
tags && tags.length > 0
? tags.map(({ label, onClose, ...other }, index) => {
? tags.map(({ label, onClose, filter, ...other }, index) => {
if (index == tags.length - 1 && other.size) {
size = other.size;
}

if (typeof onClose === 'function' || filter) {
return (
<DismissibleTag
{...other}
key={`displayed-tag-${index}`}
onClose={() => handleTagOnClose(onClose, index)}
text={label}
/>
);
}

return (
<Tag
{...other}
key={`displayed-tag-${index}`}
onClose={() => handleTagOnClose(onClose, index)}
>
<Tag {...other} key={`displayed-tag-${index}`}>
{label}
</Tag>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const TagSetModal = ({
aria-label={modalAriaLabel}
>
{filteredModalTags.map(({ label, ...other }, index) => (
<Tag {...other} filter={false} key={`all-tags-${index}`}>
<Tag {...other} key={`all-tags-${index}`}>
{label}
</Tag>
))}
Expand Down
1 change: 1 addition & 0 deletions packages/ibm-products/src/custom-typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ declare module '@carbon/react' {
CopyButton,
CopyButtonProps,
DangerButton,
DismissibleTag,
DataTable,
DataTable,
DataTable,
Expand Down
3 changes: 2 additions & 1 deletion packages/ibm-products/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"extends": "typescript-config-carbon/tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
// TODO: Turn back on once stricter typings for internal utilities are complete
"noImplicitAny": false,
"noImplicitAny": false
},
"include": ["src/**/*", "../core/**/*"]
}

0 comments on commit 18b47c7

Please sign in to comment.