Skip to content

Commit 32acfd5

Browse files
committed
feat: resolve closeTab backfill
1 parent bbc1973 commit 32acfd5

File tree

10 files changed

+259
-263
lines changed

10 files changed

+259
-263
lines changed

src/components/tabs/Tab.tsx

+42-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { useRef } from 'react';
2+
import { useRef, useState } from 'react';
33
import { findDOMNode } from 'react-dom';
44
import {
55
DragSourceMonitor,
@@ -8,16 +8,35 @@ import {
88
useDrop,
99
} from 'react-dnd';
1010

11-
import { classNames, getBEMElement, getBEMModifier, prefixClaName } from 'mo/common/className';
11+
import {
12+
classNames,
13+
getBEMElement,
14+
getBEMModifier,
15+
prefixClaName,
16+
} from 'mo/common/className';
17+
import TabDot from './tabDot';
1218

13-
export const tabClassName = prefixClaName('tab')
14-
export const tabItemClassName = getBEMElement(tabClassName, 'item')
15-
export const tabItemCloseClassName = getBEMElement(tabItemClassName, 'close')
19+
export const tabClassName = prefixClaName('tab');
20+
export const tabItemClassName = getBEMElement(tabClassName, 'item');
1621

1722
export const Tab = (props) => {
18-
const { index, propsKey, activeTab, children, onMoveTab, onTabChange } = props;
23+
const {
24+
closable,
25+
index,
26+
modified,
27+
propsKey,
28+
active,
29+
label,
30+
onTabClose,
31+
onMoveTab,
32+
onTabChange
33+
} = props;
1934
const ref = useRef<HTMLDivElement>(null);
2035

36+
const [hover, setHover] = useState(false);
37+
const handleMouseOver = () => setHover(true);
38+
const handleMouseOut = () => setHover(false);
39+
2140
const [, drag] = useDrag({
2241
collect: (monitor: DragSourceMonitor) => ({
2342
isDragging: monitor.isDragging(),
@@ -65,10 +84,24 @@ export const Tab = (props) => {
6584
return (
6685
<div
6786
ref={ref}
68-
className={classNames(tabItemClassName, { [getBEMModifier(tabItemClassName, 'active')]: activeTab === propsKey })}
69-
onClick={(event: React.MouseEvent) => onTabChange(propsKey)}
87+
className={classNames(tabItemClassName, {
88+
[getBEMModifier(tabItemClassName, 'active')]:
89+
active,
90+
})}
91+
onClick={(event: React.MouseEvent) => onTabChange(event, propsKey)}
92+
onMouseOver={handleMouseOver}
93+
onMouseOut={handleMouseOut}
7094
>
71-
{children}
95+
{label}
96+
{closable && (
97+
<TabDot
98+
classNames={getBEMElement(tabItemClassName, 'op')}
99+
modified={modified}
100+
active={active}
101+
buttonHover={hover}
102+
onClick={(e) => onTabClose?.(propsKey)}
103+
/>
104+
)}
72105
</div>
73106
);
74107
};

src/components/tabs/index.tsx

+44-46
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import { DndProvider } from 'react-dnd';
44
import HTML5Backend from 'react-dnd-html5-backend';
55
import update from 'immutability-helper';
66

7-
import { prefixClaName, getBEMElement, getBEMModifier, classNames } from 'mo/common/className';
8-
import { Icon } from 'mo/components/icon';
7+
import {
8+
prefixClaName,
9+
getBEMElement,
10+
getBEMModifier,
11+
classNames,
12+
} from 'mo/common/className';
913

1014
import { Tab, tabItemClassName } from './Tab';
11-
import TabButton from './tabButton';
1215

1316
import './style.scss';
1417
export interface ITab {
@@ -27,19 +30,27 @@ export interface ITabsProps {
2730
data: ITab[];
2831
activeTab?: string;
2932
type?: 'line' | 'editable-card';
30-
onCloseTab?: (key?: string) => void ;
33+
onCloseTab?: (key?: string) => void;
3134
onMoveTab?: (tabs: ITab[]) => void;
3235
onSelectTab?: (key?: string) => void;
3336
}
3437

35-
export const tabsClassName = prefixClaName('tabs')
36-
export const tabsHeader = getBEMElement(tabsClassName, 'header')
37-
export const tabsContent = getBEMElement(tabsClassName, 'content')
38-
export const tabsContentItem = getBEMElement(tabsContent, 'item')
39-
export const tabItemCloseClassName = getBEMElement(tabItemClassName, 'close')
38+
export const tabsClassName = prefixClaName('tabs');
39+
export const tabsHeader = getBEMElement(tabsClassName, 'header');
40+
export const tabsContent = getBEMElement(tabsClassName, 'content');
41+
export const tabsContentItem = getBEMElement(tabsContent, 'item');
42+
export const tabItemCloseClassName = getBEMElement(tabItemClassName, 'close');
4043

4144
const Tabs = (props: ITabsProps) => {
42-
const { closable, data, activeTab, type = 'line', onCloseTab, onSelectTab } = props;
45+
const {
46+
closable,
47+
data,
48+
activeTab,
49+
type = 'line',
50+
onCloseTab,
51+
onSelectTab,
52+
} = props;
53+
debugger
4354
const onMoveTab = useCallback(
4455
(dragIndex, hoverIndex) => {
4556
const dragTab = data[dragIndex];
@@ -55,62 +66,49 @@ const Tabs = (props: ITabsProps) => {
5566
[data]
5667
);
5768

58-
const onTabClick = (key?: string) => {
69+
const onTabClick = (e: React.MouseEvent, key?: string) => {
5970
onSelectTab?.(key);
6071
};
61-
62-
const onTabClose = (item: ITab) => {
63-
onCloseTab?.(item.key)
64-
};
65-
66-
const renderTabBar = (tab) => {
67-
return (
68-
<TabButton
69-
key={tab.key}
70-
name={tab.name}
71-
modified={tab.modified}
72-
active={activeTab === tab.key}
73-
onClose={() => onCloseTab?.(tab.key)}
74-
/>
75-
)
76-
}
7772
return (
7873
<DndProvider backend={HTML5Backend}>
79-
<div className={classNames(tabsClassName, getBEMModifier(tabsClassName, `${type}`))}>
74+
<div
75+
className={classNames(
76+
tabsClassName,
77+
getBEMModifier(tabsClassName, `${type}`)
78+
)}
79+
>
8080
<div className={tabsHeader}>
8181
{data?.map((tab: ITab, index: number) => {
8282
return (
83-
<Tab
83+
<Tab
8484
onMoveTab={onMoveTab}
8585
onTabChange={onTabClick}
86+
onTabClose={onCloseTab}
8687
index={index}
8788
propsKey={tab.key}
8889
key={tab.key}
89-
activeTab={activeTab}
90+
active={activeTab === tab.key}
9091
title={tab.tip}
92+
closable={closable}
93+
{...tab}
9194
>
92-
{type === 'editable-card' ? renderTabBar?.(tab) : tab.label}
93-
{closable && (
94-
<div className={classNames(tabItemCloseClassName, {[getBEMModifier(tabItemCloseClassName, 'active')]: activeTab === tab.key })} onClick={(e) => {
95-
e.stopPropagation()
96-
onTabClose(tab)
97-
}}>
98-
<Icon type="close" />
99-
</div>
100-
)}
10195
</Tab>
102-
)
96+
);
10397
})}
10498
</div>
105-
<div className={tabsContent}>{
106-
data?.map((tab: ITab) => {
99+
<div className={tabsContent}>
100+
{data?.map((tab: ITab) => {
107101
return (
108-
<div className={classNames(tabsContentItem, { [getBEMModifier(tabsContentItem, 'active')]: activeTab === tab.key })}>
102+
<div
103+
className={classNames(tabsContentItem, {
104+
[getBEMModifier(tabsContentItem, 'active')]:
105+
activeTab === tab.key,
106+
})}
107+
>
109108
{tab.renderPanel}
110109
</div>
111-
)
112-
})
113-
}
110+
);
111+
})}
114112
</div>
115113
</div>
116114
</DndProvider>

src/components/tabs/style.scss

+64-63
Original file line numberDiff line numberDiff line change
@@ -38,89 +38,90 @@
3838

3939
#{$tab} {
4040
&__item {
41+
align-items: center;
42+
4143
align-items: center;
4244
box-sizing: border-box;
4345
cursor: pointer;
46+
cursor: pointer;
4447
display: flex;
48+
display: inline-flex;
4549
font-size: 13px;
4650
height: 100%;
51+
height: 100%;
4752
max-width: 300px;
4853
min-width: 40px;
4954
padding: 0 20px;
55+
padding: 0 14px;
56+
position: relative;
57+
user-select: none;
5058

51-
&__wrapper {
52-
display: flex;
53-
justify-content: flex-start;
59+
&__name {
60+
font-size: 16px;
61+
margin-left: 10px;
5462
}
5563

56-
&__close {
57-
font-size: 13px;
58-
font-weight: 700;
59-
height: 14px;
60-
margin-left: 8px;
61-
visibility: visible;
62-
width: 14px;
64+
&__op {
65+
margin-left: 10px;
66+
width: 20px;
6367
}
6468

65-
&__button {
66-
align-items: center;
67-
cursor: pointer;
68-
display: inline-flex;
69-
height: 100%;
70-
padding: 0 14px;
69+
&__dot {
70+
display: block;
71+
height: 18px;
7172
position: relative;
72-
user-select: none;
73-
74-
&__name {
75-
font-size: 16px;
76-
margin-left: 10px;
77-
}
78-
79-
&__op {
80-
margin-left: 10px;
81-
width: 20px;
82-
}
73+
width: 18px;
8374

84-
&__dot {
75+
&::after {
76+
border-radius: 50%;
77+
content: '';
8578
display: block;
86-
height: 18px;
79+
height: 9px;
80+
left: 5px;
8781
position: relative;
88-
width: 18px;
89-
90-
&::after {
91-
border-radius: 50%;
92-
content: '';
93-
display: block;
94-
height: 9px;
95-
left: 5px;
96-
position: relative;
97-
top: 5px;
98-
width: 9px;
99-
}
100-
}
101-
102-
&__close {
103-
cursor: pointer;
104-
display: block;
105-
font-weight: 500;
106-
height: 18px;
107-
width: 18px;
82+
top: 5px;
83+
width: 9px;
10884
}
85+
}
10986

110-
&__placeholder {
111-
display: block;
112-
height: 18px;
113-
width: 18px;
114-
}
115-
116-
&--active::after {
117-
bottom: 0;
118-
content: '';
119-
height: 1px;
120-
left: 0;
121-
position: absolute;
122-
width: 100%;
123-
}
87+
&__close {
88+
cursor: pointer;
89+
display: block;
90+
font-weight: 500;
91+
height: 18px;
92+
width: 18px;
12493
}
94+
95+
&__placeholder {
96+
display: block;
97+
height: 18px;
98+
width: 18px;
99+
}
100+
101+
// &--active::after {
102+
// bottom: 0;
103+
// content: '';
104+
// height: 1px;
105+
// left: 0;
106+
// position: absolute;
107+
// width: 100%;
108+
// }
109+
110+
// &__wrapper {
111+
// display: flex;
112+
// justify-content: flex-start;
113+
// }
114+
115+
// &__close {
116+
// font-size: 13px;
117+
// font-weight: 700;
118+
// height: 14px;
119+
// margin-left: 8px;
120+
// visibility: visible;
121+
// width: 14px;
122+
// }
123+
124+
// &__button {
125+
// }
125126
}
126127
}

0 commit comments

Comments
 (0)