Skip to content

Commit

Permalink
refactor: refactor closeIcon (#665)
Browse files Browse the repository at this point in the history
* refactor: refactor closeIcon

* feat: optimize code

* feat: optimize code

* feat: optimize code

* feat: optimize code

* feat: optimize code

* feat: optimize code
  • Loading branch information
kiner-tang authored Jun 19, 2023
1 parent 2b08148 commit dd243be
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 11 deletions.
18 changes: 10 additions & 8 deletions src/TabNavList/OperationNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as React from 'react';
import { useEffect, useState } from 'react';
import type { EditableConfig, Tab, TabsLocale } from '../interface';
import AddButton from './AddButton';
import { getRemovable } from '../util';

export interface OperationNodeProps {
prefixCls: string;
Expand Down Expand Up @@ -83,17 +84,18 @@ function OperationNode(
aria-label={dropdownAriaLabel !== undefined ? dropdownAriaLabel : 'expanded dropdown'}
>
{tabs.map(tab => {
const removable = editable && tab.closable !== false && !tab.disabled;
const { closable, disabled, closeIcon, key, label } = tab;
const removable = getRemovable(closable, closeIcon, editable, disabled);
return (
<MenuItem
key={tab.key}
id={`${popupId}-${tab.key}`}
key={key}
id={`${popupId}-${key}`}
role="option"
aria-controls={id && `${id}-panel-${tab.key}`}
disabled={tab.disabled}
aria-controls={id && `${id}-panel-${key}`}
disabled={disabled}
>
{/* {tab.tab} */}
<span>{tab.label}</span>
<span>{label}</span>
{removable && (
<button
type="button"
Expand All @@ -102,10 +104,10 @@ function OperationNode(
className={`${dropdownPrefix}-menu-item-remove`}
onClick={e => {
e.stopPropagation();
onRemoveTab(e, tab.key);
onRemoveTab(e, key);
}}
>
{tab.closeIcon || editable.removeIcon || '×'}
{closeIcon || editable.removeIcon || '×'}
</button>
)}
</MenuItem>
Expand Down
4 changes: 2 additions & 2 deletions src/TabNavList/TabNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import classNames from 'classnames';
import KeyCode from 'rc-util/lib/KeyCode';
import * as React from 'react';
import type { EditableConfig, Tab } from '../interface';
import { genDataNodeKey } from '../util';
import { genDataNodeKey, getRemovable } from '../util';

export interface TabNodeProps {
id: string;
Expand Down Expand Up @@ -35,7 +35,7 @@ function TabNode({
}: TabNodeProps) {
const tabPrefix = `${prefixCls}-tab`;

const removable = editable && closable !== false && !disabled;
const removable = getRemovable(closable, closeIcon, editable, disabled);

function onInternalClick(e: React.MouseEvent | React.KeyboardEvent) {
if (disabled) {
Expand Down
23 changes: 22 additions & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from 'react';
import type React from 'react';
import type { ReactNode } from 'react';
import type { EditableConfig } from './interface';

/**
* We trade Map as deps which may change with same value but different ref object.
Expand All @@ -23,3 +25,22 @@ const RC_TABS_DOUBLE_QUOTE = 'TABS_DQ';
export function genDataNodeKey(key: React.Key): string {
return String(key).replace(/"/g, RC_TABS_DOUBLE_QUOTE);
}

export function getRemovable(
closable?: boolean,
closeIcon?: ReactNode,
editable?: EditableConfig,
disabled?: boolean,
) {
if (
// Only editable tabs can be removed
!editable ||
// Tabs cannot be removed when disabled
disabled ||
// If closable is not explicitly set to true, the remove button should be hidden when closeIcon is null or false
(closable !== true && (closeIcon === false || closeIcon === null))
) {
return false;
}
return true;
}
59 changes: 59 additions & 0 deletions tests/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,65 @@ describe('Tabs.Basic', () => {
container.querySelector('.rc-tabs-tab-remove').querySelector('.close-light'),
).toBeTruthy();
});
it('customize closeIcon', () => {
const onEdit = jest.fn();
const { container } = render(
getTabs({
editable: { onEdit },
items: [
{
key: 'light',
closeIcon: <span className="close-light" />,
children: 'Light',
},
] as any,
}),
);

expect(
container.querySelector('.rc-tabs-tab-remove').querySelector('.close-light'),
).toBeTruthy();
});
it('should hide closeIcon when closeIcon is set to null or false', () => {
const onEdit = jest.fn();
const { container } = render(
getTabs({
editable: { onEdit },
items: [
{
key: 'light1',
closeIcon: null,
children: 'Light',
},
{
key: 'light2',
closeIcon: false,
children: 'Light',
},
{
key: 'light3',
closeIcon: null,
closable: true,
children: 'Light',
},
{
key: 'light4',
closeIcon: false,
closable: true,
children: 'Light',
},
] as any,
}),
);

const removes = container.querySelectorAll('.rc-tabs-tab-remove');
expect(removes.length).toBe(2);
expect(container.querySelector('[data-node-key="light1"]').querySelector('.rc-tabs-tab-remove')).toBeFalsy();
expect(container.querySelector('[data-node-key="light2"]').querySelector('.rc-tabs-tab-remove')).toBeFalsy();
expect(container.querySelector('[data-node-key="light3"]').querySelector('.rc-tabs-tab-remove')).toBeTruthy();
expect(container.querySelector('[data-node-key="light4"]').querySelector('.rc-tabs-tab-remove')).toBeTruthy();

});
});

it('extra', () => {
Expand Down

1 comment on commit dd243be

@vercel
Copy link

@vercel vercel bot commented on dd243be Jun 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

tabs – ./

tabs-git-master-react-component.vercel.app
tabs-react-component.vercel.app

Please sign in to comment.