Skip to content

Commit 0c00695

Browse files
authored
feat: support body and content semantic DOM (#993)
* feat: support body and content semantic DOM * fix: align TabPanelList animated prop type * fix: align TabPanelList tabPosition prop type
1 parent 926f67e commit 0c00695

6 files changed

Lines changed: 62 additions & 29 deletions

File tree

assets/panels.less

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
@tabs-prefix-cls: rc-tabs;
22

33
.@{tabs-prefix-cls} {
4-
&-content {
4+
&-body {
55
&-holder {
66
flex: auto;
77
}
8+
89
position: relative;
910

1011
// display: flex;
@@ -15,7 +16,7 @@
1516
// }
1617
}
1718

18-
&-tabpane {
19+
&-content {
1920
// flex: none;
2021
// width: 100%;
2122

assets/position.less

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
order: 1;
2525
}
2626

27-
.@{tabs-prefix-cls}-content {
27+
.@{tabs-prefix-cls}-body {
2828
order: 0;
2929
}
3030

@@ -71,7 +71,7 @@
7171
order: 1;
7272
}
7373

74-
.@{tabs-prefix-cls}-content {
74+
.@{tabs-prefix-cls}-body {
7575
order: 0;
7676
}
7777

src/TabPanelList/index.tsx

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,45 @@ import TabPane from './TabPane';
88
export interface TabPanelListProps {
99
activeKey: string;
1010
id: string;
11-
animated?: AnimatedConfig;
12-
tabPosition?: TabPosition;
11+
animated: AnimatedConfig;
12+
tabPosition: TabPosition;
1313
destroyOnHidden?: boolean;
14+
bodyStyle?: React.CSSProperties;
15+
bodyClassName?: string;
1416
contentStyle?: React.CSSProperties;
1517
contentClassName?: string;
1618
}
1719

1820
const TabPanelList: React.FC<TabPanelListProps> = props => {
19-
const { id, activeKey, animated, tabPosition, destroyOnHidden, contentStyle, contentClassName } =
20-
props;
21+
const {
22+
id,
23+
activeKey,
24+
animated,
25+
tabPosition,
26+
destroyOnHidden,
27+
bodyStyle,
28+
bodyClassName,
29+
contentStyle,
30+
contentClassName,
31+
} = props;
2132
const { prefixCls, tabs } = React.useContext(TabContext);
2233
const tabPaneAnimated = animated.tabPane;
2334

24-
const tabPanePrefixCls = `${prefixCls}-tabpane`;
35+
const bodyPrefixCls = `${prefixCls}-body`;
36+
const contentPrefixCls = `${prefixCls}-content`;
2537

2638
return (
27-
<div className={clsx(`${prefixCls}-content-holder`)}>
39+
<div className={clsx(`${bodyPrefixCls}-holder`)}>
2840
<div
29-
className={clsx(`${prefixCls}-content`, `${prefixCls}-content-${tabPosition}`, {
30-
[`${prefixCls}-content-animated`]: tabPaneAnimated,
31-
})}
41+
className={clsx(
42+
bodyPrefixCls,
43+
`${bodyPrefixCls}-${tabPosition}`,
44+
{
45+
[`${bodyPrefixCls}-animated`]: tabPaneAnimated,
46+
},
47+
bodyClassName,
48+
)}
49+
style={bodyStyle}
3250
>
3351
{tabs.map(item => {
3452
const {
@@ -46,13 +64,13 @@ const TabPanelList: React.FC<TabPanelListProps> = props => {
4664
visible={active}
4765
forceRender={forceRender}
4866
removeOnLeave={!!(destroyOnHidden ?? itemDestroyOnHidden)}
49-
leavedClassName={`${tabPanePrefixCls}-hidden`}
67+
leavedClassName={`${contentPrefixCls}-hidden`}
5068
{...animated.tabPaneMotion}
5169
>
5270
{({ style: motionStyle, className: motionClassName }, ref) => (
5371
<TabPane
5472
{...restTabProps}
55-
prefixCls={tabPanePrefixCls}
73+
prefixCls={contentPrefixCls}
5674
id={id}
5775
tabKey={key}
5876
animated={tabPaneAnimated}

src/Tabs.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@ import type {
3434
// Used for accessibility
3535
let uuid = 0;
3636

37-
export type SemanticName = 'popup' | 'item' | 'indicator' | 'content' | 'header' | 'remove';
37+
export type SemanticName =
38+
| 'popup'
39+
| 'item'
40+
| 'indicator'
41+
| 'body'
42+
| 'content'
43+
| 'header'
44+
| 'remove';
3845

3946
export interface TabsProps extends Omit<
4047
React.HTMLAttributes<HTMLDivElement>,
@@ -216,6 +223,8 @@ const Tabs = React.forwardRef<HTMLDivElement, TabsProps>((props, ref) => {
216223
<TabPanelList
217224
destroyOnHidden={destroyOnHidden}
218225
{...sharedProps}
226+
bodyStyle={styles?.body}
227+
bodyClassName={tabsClassNames?.body}
219228
contentStyle={styles?.content}
220229
contentClassName={tabsClassNames?.content}
221230
animated={mergedAnimated}

tests/__snapshots__/index.test.tsx.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ exports[`Tabs.Basic Normal 1`] = `
8383
</div>
8484
</div>
8585
<div
86-
class="rc-tabs-content-holder"
86+
class="rc-tabs-body-holder"
8787
>
8888
<div
89-
class="rc-tabs-content rc-tabs-content-top"
89+
class="rc-tabs-body rc-tabs-body-top"
9090
>
9191
<div
9292
aria-hidden="false"
9393
aria-labelledby="rc-tabs-test-tab-bamboo"
94-
class="rc-tabs-tabpane rc-tabs-tabpane-active"
94+
class="rc-tabs-content rc-tabs-content-active"
9595
id="rc-tabs-test-panel-bamboo"
9696
role="tabpanel"
9797
tabindex="0"
@@ -156,15 +156,15 @@ exports[`Tabs.Basic Skip invalidate children 1`] = `
156156
</div>
157157
</div>
158158
<div
159-
class="rc-tabs-content-holder"
159+
class="rc-tabs-body-holder"
160160
>
161161
<div
162-
class="rc-tabs-content rc-tabs-content-top"
162+
class="rc-tabs-body rc-tabs-body-top"
163163
>
164164
<div
165165
aria-hidden="false"
166166
aria-labelledby="rc-tabs-test-tab-light"
167-
class="rc-tabs-tabpane rc-tabs-tabpane-active"
167+
class="rc-tabs-content rc-tabs-content-active"
168168
id="rc-tabs-test-panel-light"
169169
role="tabpanel"
170170
tabindex="0"

tests/index.test.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,8 @@ describe('Tabs.Basic', () => {
331331
const { container, rerender } = render(getTabs(props));
332332

333333
function matchText(text: string) {
334-
expect(container.querySelectorAll('.rc-tabs-tabpane')).toHaveLength(1);
335-
expect(container.querySelector('.rc-tabs-tabpane-active').textContent).toEqual(text);
334+
expect(container.querySelectorAll('.rc-tabs-content')).toHaveLength(1);
335+
expect(container.querySelector('.rc-tabs-content-active').textContent).toEqual(text);
336336
}
337337

338338
matchText('Light');
@@ -367,8 +367,8 @@ describe('Tabs.Basic', () => {
367367
const { container, rerender } = render(getTabs(props));
368368

369369
function matchText(text: string) {
370-
expect(container.querySelectorAll('.rc-tabs-tabpane')).toHaveLength(1);
371-
expect(container.querySelector('.rc-tabs-tabpane-active').textContent).toEqual(text);
370+
expect(container.querySelectorAll('.rc-tabs-content')).toHaveLength(1);
371+
expect(container.querySelector('.rc-tabs-content-active').textContent).toEqual(text);
372372
}
373373

374374
matchText('Light');
@@ -743,13 +743,15 @@ describe('Tabs.Basic', () => {
743743
const customClassNames = {
744744
indicator: 'custom-indicator',
745745
item: 'custom-item',
746+
body: 'custom-body',
746747
content: 'custom-content',
747748
header: 'custom-header',
748749
};
749750
const customStyles = {
750751
indicator: { background: 'red' },
751752
item: { color: 'blue' },
752-
content: { background: 'green' },
753+
body: { background: 'green' },
754+
content: { color: 'purple' },
753755
header: { background: 'yellow' },
754756
};
755757
const { container } = render(
@@ -762,17 +764,20 @@ describe('Tabs.Basic', () => {
762764
);
763765
const indicator = container.querySelector('.rc-tabs-ink-bar') as HTMLElement;
764766
const item = container.querySelector('.rc-tabs-tab') as HTMLElement;
765-
const content = container.querySelector('.rc-tabs-tabpane') as HTMLElement;
767+
const body = container.querySelector('.rc-tabs-body') as HTMLElement;
768+
const content = container.querySelector('.rc-tabs-content') as HTMLElement;
766769
const header = container.querySelector('.rc-tabs-nav') as HTMLElement;
767770

768771
expect(indicator).toHaveClass('custom-indicator');
769772
expect(item).toHaveClass('custom-item');
773+
expect(body).toHaveClass('custom-body');
770774
expect(content).toHaveClass('custom-content');
771775
expect(header).toHaveClass('custom-header');
772776

773777
expect(indicator).toHaveStyle({ background: 'red' });
774778
expect(item).toHaveStyle({ color: 'blue' });
775-
expect(content).toHaveStyle({ background: 'green' });
779+
expect(body).toHaveStyle({ background: 'green' });
780+
expect(content).toHaveStyle({ color: 'purple' });
776781
expect(header).toHaveStyle({ background: 'yellow' });
777782
});
778783

0 commit comments

Comments
 (0)