From 9e74910f974544722b21ecbcf0b57e62c38661b7 Mon Sep 17 00:00:00 2001
From: Jony J <1844749591@qq.com>
Date: Wed, 12 Feb 2025 11:48:55 +0800
Subject: [PATCH 01/13] feat: retire deprecated api (#768)
---
docs/demo/renderTabBar-use-panes.md | 8 -----
docs/examples/renderTabBar-use-panes.tsx | 43 ------------------------
src/TabNavList/Wrapper.tsx | 15 ++-------
src/Tabs.tsx | 1 -
src/interface.ts | 2 --
tests/index.test.tsx | 17 ----------
6 files changed, 2 insertions(+), 84 deletions(-)
delete mode 100644 docs/demo/renderTabBar-use-panes.md
delete mode 100644 docs/examples/renderTabBar-use-panes.tsx
diff --git a/docs/demo/renderTabBar-use-panes.md b/docs/demo/renderTabBar-use-panes.md
deleted file mode 100644
index 616e1cfc..00000000
--- a/docs/demo/renderTabBar-use-panes.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: enderTabBar-use-panes
-nav:
- title: Demo
- path: /demo
----
-
-
diff --git a/docs/examples/renderTabBar-use-panes.tsx b/docs/examples/renderTabBar-use-panes.tsx
deleted file mode 100644
index a976effe..00000000
--- a/docs/examples/renderTabBar-use-panes.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react';
-import Tabs from '../../src';
-import '../../assets/index.less';
-
-const renderTabBar = props => {
- return (
-
- {props.panes.map(pane => {
- const { key } = pane;
- return {key};
- })}
-
- );
-};
-
-export default () => {
- return (
-
-
-
- );
-};
diff --git a/src/TabNavList/Wrapper.tsx b/src/TabNavList/Wrapper.tsx
index a2b4bd50..b4203554 100644
--- a/src/TabNavList/Wrapper.tsx
+++ b/src/TabNavList/Wrapper.tsx
@@ -3,25 +3,14 @@
import * as React from 'react';
import type { TabNavListProps } from '.';
import TabNavList from '.';
-import TabContext from '../TabContext';
-import TabPane from '../TabPanelList/TabPane';
-
+
export type TabNavListWrapperProps = Required> &
TabNavListProps;
// We have to create a TabNavList components.
const TabNavListWrapper: React.FC = ({ renderTabBar, ...restProps }) => {
- const { tabs } = React.useContext(TabContext);
if (renderTabBar) {
- const tabNavBarProps = {
- ...restProps,
- // Legacy support. We do not use this actually
- panes: tabs.map(({ label, key, ...restTabProps }) => (
-
- )),
- };
-
- return renderTabBar(tabNavBarProps, TabNavList);
+ return renderTabBar(restProps, TabNavList);
}
return ;
diff --git a/src/Tabs.tsx b/src/Tabs.tsx
index 7d6df768..6a288859 100644
--- a/src/Tabs.tsx
+++ b/src/Tabs.tsx
@@ -178,7 +178,6 @@ const Tabs = React.forwardRef((props, ref) => {
onTabScroll,
extra: tabBarExtraContent,
style: tabBarStyle,
- panes: null,
getPopupContainer,
popupClassName,
indicator,
diff --git a/src/interface.ts b/src/interface.ts
index ea7958af..162e1345 100644
--- a/src/interface.ts
+++ b/src/interface.ts
@@ -51,8 +51,6 @@ type RenderTabBarProps = {
onTabScroll: OnTabScroll;
extra: TabBarExtraContent;
style: React.CSSProperties;
- /** @deprecated It do not pass real TabPane node. Only for compatible usage. */
- panes: React.ReactNode;
};
export type RenderTabBar = (
diff --git a/tests/index.test.tsx b/tests/index.test.tsx
index db5bc7d9..a7488dd9 100644
--- a/tests/index.test.tsx
+++ b/tests/index.test.tsx
@@ -310,23 +310,6 @@ describe('Tabs.Basic', () => {
expect(container.querySelector('.my-node')).toBeTruthy();
expect(renderTabBar).toHaveBeenCalled();
});
- it('has panes property in props', () => {
- const renderTabBar = props => {
- return (
-
- {props.panes.map(pane => (
-
- tab
-
- ))}
-
- );
- };
- const { container } = render(getTabs({ renderTabBar }));
- expect(container.querySelector('[data-key="light"]')).toBeTruthy();
- expect(container.querySelector('[data-key="bamboo"]')).toBeTruthy();
- expect(container.querySelector('[data-key="cute"]')).toBeTruthy();
- });
});
it('destroyInactiveTabPane', () => {
From 1559c3b5f8149f2bf4b8b435b7b7441270ec4fd1 Mon Sep 17 00:00:00 2001
From: Jony J <1844749591@qq.com>
Date: Wed, 12 Feb 2025 17:27:58 +0800
Subject: [PATCH 02/13] chore: migrate to @rc-component namespace (#779)
* chore: migrate to @rc-component namespace
* chore: adjust script
* chore: adjust script
---
.fatherrc.js => .fatherrc.ts | 0
package.json | 18 +++++++++---------
tsconfig.json | 3 +++
3 files changed, 12 insertions(+), 9 deletions(-)
rename .fatherrc.js => .fatherrc.ts (100%)
diff --git a/.fatherrc.js b/.fatherrc.ts
similarity index 100%
rename from .fatherrc.js
rename to .fatherrc.ts
diff --git a/package.json b/package.json
index 8816f77c..298a9012 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
- "name": "rc-tabs",
- "version": "15.5.1",
+ "name": "@rc-component/tabs",
+ "version": "1.0.0",
"description": "tabs ui component for react",
"keywords": [
"react",
@@ -32,21 +32,22 @@
"docs:deploy": "gh-pages -d .doc",
"lint": "eslint src/ docs/examples/ --ext .tsx,.ts,.jsx,.js",
"now-build": "npm run build",
- "prepublishOnly": "npm run lint && npm run test && npm run compile && np --yolo --no-publish",
+ "prepublishOnly": "npm run lint && npm run test && npm run compile && rc-np",
"start": "dumi dev",
"test": "rc-test"
},
"dependencies": {
- "@babel/runtime": "^7.11.2",
+ "@rc-component/resize-observer": "^1.0.0",
+ "@rc-component/util": "^1.2.0",
+ "@rc-component/motion": "^1.1.3",
"classnames": "2.x",
"rc-dropdown": "~4.2.0",
"rc-menu": "~9.16.0",
- "rc-motion": "^2.6.2",
- "rc-resize-observer": "^1.0.0",
- "rc-util": "^5.34.1"
+ "rc-motion": "^2.6.2"
},
"devDependencies": {
- "@rc-component/father-plugin": "^1.0.0",
+ "@rc-component/father-plugin": "^2.0.0",
+ "@rc-component/np": "^1.0.3",
"@rc-component/trigger": "^2.0.0",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^16.0.1",
@@ -70,7 +71,6 @@
"history": "^5.3.0",
"immutability-helper": "^3.0.1",
"less": "^4.1.3",
- "np": "^10.0.2",
"preact-compat": "^3.16.0",
"rc-test": "^7.0.14",
"react": "^18.0.0",
diff --git a/tsconfig.json b/tsconfig.json
index aeeacaa4..7a55add9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -20,6 +20,9 @@
],
"rc-tabs": [
"src/"
+ ],
+ "@rc-component/tabs": [
+ "src/"
]
}
},
From 6d02218f91f4d4f84a4aaf89c70e56cacb07f02a Mon Sep 17 00:00:00 2001
From: Jony J <1844749591@qq.com>
Date: Mon, 17 Feb 2025 16:03:54 +0800
Subject: [PATCH 03/13] fix: improve TabPane accessibility and content handling
(#780)
* fix: improve TabPane accessibility and content handling
* test: prevent focus on empty tab panel
---
src/TabPanelList/TabPane.tsx | 4 +++-
tests/accessibility.test.tsx | 12 ++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/TabPanelList/TabPane.tsx b/src/TabPanelList/TabPane.tsx
index 510520d7..d1b803d3 100644
--- a/src/TabPanelList/TabPane.tsx
+++ b/src/TabPanelList/TabPane.tsx
@@ -23,11 +23,13 @@ export interface TabPaneProps {
const TabPane = React.forwardRef((props, ref) => {
const { prefixCls, className, style, id, active, tabKey, children } = props;
+ const hasContent = React.Children.count(children) > 0;
+
return (
{
const firstTab = getByRole('tab', { name: /Tab1/i });
expect(firstTab).toHaveFocus();
});
+
+ it('should not focus on tab panel when it is empty', async () => {
+ const user = userEvent.setup();
+ const { getByRole } = render(
+
,
+ );
+
+ const tabPanel = getByRole('tabpanel', { name: /Tab1/i });
+ await user.tab();
+ await user.tab();
+ expect(tabPanel).not.toHaveFocus();
+ });
});
From ffde754b90a40806f278ffe082c2b9c6fdaa5b68 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?=
Date: Mon, 17 Feb 2025 16:36:52 +0800
Subject: [PATCH 04/13] chore: bump version to 1.1.0
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 298a9012..894829eb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@rc-component/tabs",
- "version": "1.0.0",
+ "version": "1.1.0",
"description": "tabs ui component for react",
"keywords": [
"react",
From ca9a372dea6e0a214ad711f6e9cf39d670ef5d50 Mon Sep 17 00:00:00 2001
From: thinkasany <480968828@qq.com>
Date: Thu, 20 Feb 2025 15:00:29 +0800
Subject: [PATCH 05/13] feat: tab support classnames and styles (#784)
* feat: tab support classnames and styles
* fix: test
* fix
* fix
* fix
---
src/TabNavList/OperationNode.tsx | 7 +++++--
src/TabNavList/TabNode.tsx | 4 +++-
src/TabNavList/index.tsx | 13 ++++++++++---
src/Tabs.tsx | 10 +++++++++-
tests/index.test.tsx | 25 +++++++++++++++++++++++++
tests/overflow.test.tsx | 16 +++++++++++++---
6 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/src/TabNavList/OperationNode.tsx b/src/TabNavList/OperationNode.tsx
index 87a44c80..4c29c572 100644
--- a/src/TabNavList/OperationNode.tsx
+++ b/src/TabNavList/OperationNode.tsx
@@ -26,6 +26,7 @@ export interface OperationNodeProps {
tabMoving?: boolean;
getPopupContainer?: (node: HTMLElement) => HTMLElement;
popupClassName?: string;
+ popupStyle?: React.CSSProperties;
}
const OperationNode = React.forwardRef((props, ref) => {
@@ -45,6 +46,7 @@ const OperationNode = React.forwardRef((prop
onTabClick,
getPopupContainer,
popupClassName,
+ popupStyle,
} = props;
// ======================== Dropdown ========================
const [open, setOpen] = useState(false);
@@ -182,7 +184,7 @@ const OperationNode = React.forwardRef((prop
moreStyle.order = 1;
}
- const overlayClassName = classNames({
+ const overlayClassName = classNames(popupClassName, {
[`${dropdownPrefix}-rtl`]: rtl,
});
@@ -192,7 +194,8 @@ const OperationNode = React.forwardRef((prop
overlay={menu}
visible={tabs.length ? open : false}
onVisibleChange={setOpen}
- overlayClassName={classNames(overlayClassName, popupClassName)}
+ overlayClassName={overlayClassName}
+ overlayStyle={popupStyle}
mouseEnterDelay={0.1}
mouseLeaveDelay={0.1}
getPopupContainer={getPopupContainer}
diff --git a/src/TabNavList/TabNode.tsx b/src/TabNavList/TabNode.tsx
index d3c0d944..0c1e34fd 100644
--- a/src/TabNavList/TabNode.tsx
+++ b/src/TabNavList/TabNode.tsx
@@ -24,6 +24,7 @@ export interface TabNodeProps {
onFocus: React.FocusEventHandler;
onBlur: React.FocusEventHandler;
style?: React.CSSProperties;
+ className?: string;
}
const TabNode: React.FC = props => {
@@ -44,6 +45,7 @@ const TabNode: React.FC = props => {
onMouseDown,
onMouseUp,
style,
+ className,
tabCount,
currentPosition,
} = props;
@@ -81,7 +83,7 @@ const TabNode: React.FC = props => {
>;
+ styles?: Partial
>;
}
const getTabSize = (tab: HTMLElement, containerRect: { left: number; top: number }) => {
@@ -109,6 +112,8 @@ const TabNavList = React.forwardRef((props, ref
onTabClick,
onTabScroll,
indicator,
+ classNames: tabsClassNames,
+ styles,
} = props;
const { prefixCls, tabs } = React.useContext(TabContext);
@@ -417,8 +422,9 @@ const TabNavList = React.forwardRef((props, ref
prefixCls={prefixCls}
key={key}
tab={tab}
+ className={tabsClassNames?.item}
/* first node should not have margin left */
- style={i === 0 ? undefined : tabNodeStyle}
+ style={i === 0 ? styles?.item : { ...tabNodeStyle, ...styles?.item }}
closable={tab.closable}
editable={editable}
active={key === activeKey}
@@ -607,10 +613,10 @@ const TabNavList = React.forwardRef((props, ref
}}
/>
@@ -624,6 +630,7 @@ const TabNavList = React.forwardRef((props, ref
prefixCls={prefixCls}
tabs={hiddenTabs}
className={!hasDropdown && operationsHiddenClassName}
+ popupStyle={styles?.popup}
tabMoving={!!lockAnimation}
/>
diff --git a/src/Tabs.tsx b/src/Tabs.tsx
index 6a288859..f6cdb03b 100644
--- a/src/Tabs.tsx
+++ b/src/Tabs.tsx
@@ -34,11 +34,15 @@ import type {
// Used for accessibility
let uuid = 0;
+export type SemanticName = 'popup' | 'item' | 'indicator';
+
export interface TabsProps
extends Omit, 'onChange' | 'children'> {
prefixCls?: string;
className?: string;
style?: React.CSSProperties;
+ classNames?: Partial>;
+ styles?: Partial>;
id?: string;
items?: Tab[];
@@ -99,6 +103,8 @@ const Tabs = React.forwardRef((props, ref) => {
getPopupContainer,
popupClassName,
indicator,
+ classNames: tabsClassNames,
+ styles,
...restProps
} = props;
const tabs = React.useMemo(
@@ -179,7 +185,9 @@ const Tabs = React.forwardRef((props, ref) => {
extra: tabBarExtraContent,
style: tabBarStyle,
getPopupContainer,
- popupClassName,
+ popupClassName: classNames(popupClassName, tabsClassNames?.popup),
+ styles,
+ classNames: tabsClassNames,
indicator,
};
diff --git a/tests/index.test.tsx b/tests/index.test.tsx
index a7488dd9..12185d10 100644
--- a/tests/index.test.tsx
+++ b/tests/index.test.tsx
@@ -689,4 +689,29 @@ describe('Tabs.Basic', () => {
expect(parseInt(startBar.style.top)).toBeLessThanOrEqual(parseInt(centerBar.style.top));
expect(parseInt(centerBar.style.top)).toBeLessThanOrEqual(parseInt(endBar.style.top));
});
+ it('support classnames and styles', () => {
+ const customClassNames = {
+ indicator: 'custom-indicator',
+ item: 'custom-item',
+ };
+ const customStyles = {
+ indicator: { background: 'red' },
+ item: { color: 'blue' },
+ };
+ const { container } = render(
+ ,
+ );
+ const indicator = container.querySelector('.rc-tabs-ink-bar') as HTMLElement;
+ const item = container.querySelector('.rc-tabs-tab') as HTMLElement;
+
+ expect(indicator).toHaveClass('custom-indicator');
+ expect(item).toHaveClass('custom-item');
+ expect(indicator).toHaveStyle({ background: 'red' });
+ expect(item).toHaveStyle({ color: 'blue' });
+ });
});
diff --git a/tests/overflow.test.tsx b/tests/overflow.test.tsx
index 509bbae6..cc8165e4 100644
--- a/tests/overflow.test.tsx
+++ b/tests/overflow.test.tsx
@@ -95,12 +95,14 @@ describe('Tabs.Overflow', () => {
it('should open dropdown on click when moreTrigger is set to click', () => {
jest.useFakeTimers();
const onChange = jest.fn();
- const { container, unmount } = render(getTabs({ onChange, more: {icon: '...', trigger: 'click'} }));
+ const { container, unmount } = render(
+ getTabs({ onChange, more: { icon: '...', trigger: 'click' } }),
+ );
triggerResize(container);
act(() => {
jest.runAllTimers();
});
- const button = container.querySelector('.rc-tabs-nav-more')
+ const button = container.querySelector('.rc-tabs-nav-more');
fireEvent.click(button);
act(() => {
jest.runAllTimers();
@@ -504,7 +506,13 @@ describe('Tabs.Overflow', () => {
it('should support popupClassName', () => {
jest.useFakeTimers();
- const { container } = render(getTabs({ popupClassName: 'custom-popup' }));
+ const { container } = render(
+ getTabs({
+ popupClassName: 'custom-popup',
+ classNames: { popup: 'classnames-popup' },
+ styles: { popup: { color: 'red' } },
+ }),
+ );
triggerResize(container);
act(() => {
@@ -516,6 +524,8 @@ describe('Tabs.Overflow', () => {
jest.runAllTimers();
});
expect(document.querySelector('.rc-tabs-dropdown')).toHaveClass('custom-popup');
+ expect(document.querySelector('.rc-tabs-dropdown')).toHaveClass('classnames-popup');
+ expect(document.querySelector('.rc-tabs-dropdown')).toHaveStyle('color: red');
});
it('correct handle decimal', () => {
From 1bc44a5e8d21fc4ea91f3227073472de5c46c94c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?=
Date: Thu, 20 Feb 2025 15:08:18 +0800
Subject: [PATCH 06/13] chore: bump version to 1.2.0
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 894829eb..16bd6728 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@rc-component/tabs",
- "version": "1.1.0",
+ "version": "1.2.0",
"description": "tabs ui component for react",
"keywords": [
"react",
From 7d5b243799bbd4552e350c28b993b139e857b21a Mon Sep 17 00:00:00 2001
From: thinkasany <480968828@qq.com>
Date: Thu, 20 Feb 2025 17:49:45 +0800
Subject: [PATCH 07/13] feat: tab support classnames and styles (#786)
* feat: add content for classnames and styles
* add header
---
src/TabNavList/index.tsx | 4 ++--
src/TabPanelList/index.tsx | 16 +++++++++++++---
src/Tabs.tsx | 6 ++++--
tests/index.test.tsx | 11 +++++++++++
4 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/src/TabNavList/index.tsx b/src/TabNavList/index.tsx
index 7411f579..7b49007b 100644
--- a/src/TabNavList/index.tsx
+++ b/src/TabNavList/index.tsx
@@ -573,8 +573,8 @@ const TabNavList = React.forwardRef((props, ref
ref={useComposeRef(ref, containerRef)}
role="tablist"
aria-orientation={tabPositionTopOrBottom ? 'horizontal' : 'vertical'}
- className={classNames(`${prefixCls}-nav`, className)}
- style={style}
+ className={classNames(`${prefixCls}-nav`, className, tabsClassNames?.header)}
+ style={{ ...styles?.header, ...style }}
onKeyDown={() => {
// No need animation when use keyboard
doLockAnimation();
diff --git a/src/TabPanelList/index.tsx b/src/TabPanelList/index.tsx
index 0957bbb6..e340498d 100644
--- a/src/TabPanelList/index.tsx
+++ b/src/TabPanelList/index.tsx
@@ -11,10 +11,20 @@ export interface TabPanelListProps {
animated?: AnimatedConfig;
tabPosition?: TabPosition;
destroyInactiveTabPane?: boolean;
+ contentStyle?: React.CSSProperties;
+ contentClassName?: string;
}
const TabPanelList: React.FC = props => {
- const { id, activeKey, animated, tabPosition, destroyInactiveTabPane } = props;
+ const {
+ id,
+ activeKey,
+ animated,
+ tabPosition,
+ destroyInactiveTabPane,
+ contentStyle,
+ contentClassName,
+ } = props;
const { prefixCls, tabs } = React.useContext(TabContext);
const tabPaneAnimated = animated.tabPane;
@@ -54,8 +64,8 @@ const TabPanelList: React.FC = props => {
tabKey={key}
animated={tabPaneAnimated}
active={active}
- style={{ ...paneStyle, ...motionStyle }}
- className={classNames(paneClassName, motionClassName)}
+ style={{ ...contentStyle, ...paneStyle, ...motionStyle }}
+ className={classNames(contentClassName, paneClassName, motionClassName)}
ref={ref}
/>
)}
diff --git a/src/Tabs.tsx b/src/Tabs.tsx
index f6cdb03b..144dd3b7 100644
--- a/src/Tabs.tsx
+++ b/src/Tabs.tsx
@@ -34,7 +34,7 @@ import type {
// Used for accessibility
let uuid = 0;
-export type SemanticName = 'popup' | 'item' | 'indicator';
+export type SemanticName = 'popup' | 'item' | 'indicator' | 'content' | 'header';
export interface TabsProps
extends Omit, 'onChange' | 'children'> {
@@ -186,9 +186,9 @@ const Tabs = React.forwardRef((props, ref) => {
style: tabBarStyle,
getPopupContainer,
popupClassName: classNames(popupClassName, tabsClassNames?.popup),
+ indicator,
styles,
classNames: tabsClassNames,
- indicator,
};
return (
@@ -212,6 +212,8 @@ const Tabs = React.forwardRef((props, ref) => {
diff --git a/tests/index.test.tsx b/tests/index.test.tsx
index 12185d10..81cb8c99 100644
--- a/tests/index.test.tsx
+++ b/tests/index.test.tsx
@@ -693,10 +693,14 @@ describe('Tabs.Basic', () => {
const customClassNames = {
indicator: 'custom-indicator',
item: 'custom-item',
+ content: 'custom-content',
+ header: 'custom-header',
};
const customStyles = {
indicator: { background: 'red' },
item: { color: 'blue' },
+ content: { background: 'green' },
+ header: { background: 'yellow' },
};
const { container } = render(
{
);
const indicator = container.querySelector('.rc-tabs-ink-bar') as HTMLElement;
const item = container.querySelector('.rc-tabs-tab') as HTMLElement;
+ const content = container.querySelector('.rc-tabs-tabpane') as HTMLElement;
+ const header = container.querySelector('.rc-tabs-nav') as HTMLElement;
expect(indicator).toHaveClass('custom-indicator');
expect(item).toHaveClass('custom-item');
+ expect(content).toHaveClass('custom-content');
+ expect(header).toHaveClass('custom-header');
+
expect(indicator).toHaveStyle({ background: 'red' });
expect(item).toHaveStyle({ color: 'blue' });
+ expect(content).toHaveStyle({ background: 'green' });
+ expect(header).toHaveStyle({ background: 'yellow' });
});
});
From f65defc7c423ddb19cf82a4d576db5367281a237 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?=
Date: Thu, 20 Feb 2025 19:24:48 +0800
Subject: [PATCH 08/13] chore: bump version to 1.2.1
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 16bd6728..09318cd5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@rc-component/tabs",
- "version": "1.2.0",
+ "version": "1.2.1",
"description": "tabs ui component for react",
"keywords": [
"react",
From a710e4762801bb63e20e173802c8a59a03d12971 Mon Sep 17 00:00:00 2001
From: Jony J <1844749591@qq.com>
Date: Tue, 25 Feb 2025 15:21:59 +0800
Subject: [PATCH 09/13] chore: update package dependencies (#788)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* chore: update package dependencies
* chore: bump deps
---------
Co-authored-by: 二货机器人
---
docs/examples/animated.tsx | 2 +-
package.json | 7 +++----
src/TabNavList/OperationNode.tsx | 4 ++--
src/TabPanelList/index.tsx | 2 +-
src/interface.ts | 10 +++++-----
5 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/docs/examples/animated.tsx b/docs/examples/animated.tsx
index c28d62fa..f6118acb 100644
--- a/docs/examples/animated.tsx
+++ b/docs/examples/animated.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import Tabs from '../../src';
-import type { CSSMotionProps } from 'rc-motion';
+import type { CSSMotionProps } from '@rc-component/motion';
import '../../assets/index.less';
import './animated.less';
diff --git a/package.json b/package.json
index 09318cd5..37b125b2 100644
--- a/package.json
+++ b/package.json
@@ -41,14 +41,13 @@
"@rc-component/util": "^1.2.0",
"@rc-component/motion": "^1.1.3",
"classnames": "2.x",
- "rc-dropdown": "~4.2.0",
- "rc-menu": "~9.16.0",
- "rc-motion": "^2.6.2"
+ "@rc-component/dropdown": "~1.0.0",
+ "@rc-component/menu": "~1.0.0"
},
"devDependencies": {
"@rc-component/father-plugin": "^2.0.0",
"@rc-component/np": "^1.0.3",
- "@rc-component/trigger": "^2.0.0",
+ "@rc-component/trigger": "^3.0.0",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
diff --git a/src/TabNavList/OperationNode.tsx b/src/TabNavList/OperationNode.tsx
index 4c29c572..5b58db4e 100644
--- a/src/TabNavList/OperationNode.tsx
+++ b/src/TabNavList/OperationNode.tsx
@@ -1,6 +1,6 @@
import classNames from 'classnames';
-import Dropdown from 'rc-dropdown';
-import Menu, { MenuItem } from 'rc-menu';
+import Dropdown from '@rc-component/dropdown';
+import Menu, { MenuItem } from '@rc-component/menu';
import KeyCode from 'rc-util/lib/KeyCode';
import * as React from 'react';
import { useEffect, useState } from 'react';
diff --git a/src/TabPanelList/index.tsx b/src/TabPanelList/index.tsx
index e340498d..2082c493 100644
--- a/src/TabPanelList/index.tsx
+++ b/src/TabPanelList/index.tsx
@@ -1,5 +1,5 @@
import classNames from 'classnames';
-import CSSMotion from 'rc-motion';
+import CSSMotion from '@rc-component/motion';
import * as React from 'react';
import type { AnimatedConfig, TabPosition } from '../interface';
import TabContext from '../TabContext';
diff --git a/src/interface.ts b/src/interface.ts
index 162e1345..6c62e24e 100644
--- a/src/interface.ts
+++ b/src/interface.ts
@@ -1,15 +1,15 @@
-import type { CSSMotionProps } from 'rc-motion';
+import type { CSSMotionProps } from '@rc-component/motion';
+import { DropdownProps } from '@rc-component/dropdown/lib/Dropdown';
import type React from 'react';
import type { TabNavListProps } from './TabNavList';
import type { TabPaneProps } from './TabPanelList/TabPane';
-import { DropdownProps } from 'rc-dropdown/lib/Dropdown';
export type TriggerProps = {
trigger?: 'hover' | 'click';
-}
+};
export type moreIcon = React.ReactNode;
export type MoreProps = {
- icon?: moreIcon,
+ icon?: moreIcon;
} & Omit;
export type SizeInfo = [width: number, height: number];
@@ -45,7 +45,7 @@ type RenderTabBarProps = {
mobile: boolean;
editable: EditableConfig;
locale: TabsLocale;
- more: MoreProps,
+ more: MoreProps;
tabBarGutter: number;
onTabClick: (key: string, e: React.MouseEvent | React.KeyboardEvent) => void;
onTabScroll: OnTabScroll;
From 629f13ba97bf0c452b991371a274288ef596bb22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?=
Date: Tue, 25 Feb 2025 15:26:49 +0800
Subject: [PATCH 10/13] chore: bump version to 1.3.0
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 37b125b2..2802eb42 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@rc-component/tabs",
- "version": "1.2.1",
+ "version": "1.3.0",
"description": "tabs ui component for react",
"keywords": [
"react",
From c08b866fb5ad8f6f50b9adb6c47f8008b9655515 Mon Sep 17 00:00:00 2001
From: afc163
Date: Tue, 1 Apr 2025 15:59:47 +0800
Subject: [PATCH 11/13] fix: Tabs press Enter/Space on active tab should not
trigger onChange (#790)
* fix: Tabs press Enter/Space on active tab should not trigger onChange
* fix
* fix lint
* remove unused devdeps
---
.husky/pre-commit | 1 +
docs/examples/basic.tsx | 7 ++++++-
package.json | 18 ++++++++++--------
src/TabNavList/index.tsx | 3 ++-
tests/accessibility.test.tsx | 5 ++++-
5 files changed, 23 insertions(+), 11 deletions(-)
create mode 100644 .husky/pre-commit
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 00000000..d0a77842
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1 @@
+npx lint-staged
\ No newline at end of file
diff --git a/docs/examples/basic.tsx b/docs/examples/basic.tsx
index b97a0962..7c460422 100644
--- a/docs/examples/basic.tsx
+++ b/docs/examples/basic.tsx
@@ -38,7 +38,11 @@ export default () => {
}
const onTabClick = (key: string) => {
- console.log('key', key);
+ console.log('onTabClick', key);
+ };
+
+ const onChange = (key: string) => {
+ console.log('onChange', key);
};
return (
@@ -46,6 +50,7 @@ export default () => {
diff --git a/package.json b/package.json
index 2802eb42..91a8efb5 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,8 @@
"now-build": "npm run build",
"prepublishOnly": "npm run lint && npm run test && npm run compile && rc-np",
"start": "dumi dev",
- "test": "rc-test"
+ "test": "rc-test",
+ "prepare": "husky && dumi setup"
},
"dependencies": {
"@rc-component/resize-observer": "^1.0.0",
@@ -45,6 +46,8 @@
"@rc-component/menu": "~1.0.0"
},
"devDependencies": {
+ "@typescript-eslint/eslint-plugin": "^5.59.7",
+ "@typescript-eslint/parser": "^5.59.7",
"@rc-component/father-plugin": "^2.0.0",
"@rc-component/np": "^1.0.3",
"@rc-component/trigger": "^3.0.0",
@@ -54,36 +57,35 @@
"@types/classnames": "^2.2.10",
"@types/enzyme": "^3.10.5",
"@types/jest": "^29.4.0",
- "@types/keyv": "4.2.0",
"@types/react": "^18.2.42",
"@types/react-dom": "^18.0.11",
"@umijs/fabric": "^4.0.1",
- "coveralls": "^3.0.6",
"cross-env": "^7.0.2",
"dumi": "^2.0.0",
"eslint": "^8.54.0",
"eslint-plugin-jest": "^28.9.0",
"eslint-plugin-unicorn": "^56.0.1",
- "fastclick": "~1.0.6",
"father": "^4.0.0",
"gh-pages": "^6.1.0",
- "history": "^5.3.0",
- "immutability-helper": "^3.0.1",
+ "husky": "^9.1.7",
"less": "^4.1.3",
- "preact-compat": "^3.16.0",
+ "lint-staged": "^15.5.0",
+ "prettier": "^3.5.3",
"rc-test": "^7.0.14",
"react": "^18.0.0",
"react-dnd": "^10.0.0",
"react-dnd-html5-backend": "^10.0.0",
"react-dom": "^18.0.0",
"react-sticky": "^6.0.3",
- "sortablejs": "^1.7.0",
"typescript": "^5.3.2"
},
"peerDependencies": {
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
},
+ "lint-staged": {
+ "*": "prettier --write --ignore-unknown"
+ },
"engines": {
"node": ">=8.x"
}
diff --git a/src/TabNavList/index.tsx b/src/TabNavList/index.tsx
index 7b49007b..1caca657 100644
--- a/src/TabNavList/index.tsx
+++ b/src/TabNavList/index.tsx
@@ -375,8 +375,9 @@ const TabNavList = React.forwardRef((props, ref
// Enter & Space
case 'Enter':
case 'Space': {
+ console.log('press', code);
e.preventDefault();
- onTabClick(focusKey, e);
+ onTabClick(activeKey, e);
break;
}
// Backspace
diff --git a/tests/accessibility.test.tsx b/tests/accessibility.test.tsx
index bb0531a4..809a2409 100644
--- a/tests/accessibility.test.tsx
+++ b/tests/accessibility.test.tsx
@@ -91,9 +91,10 @@ describe('Tabs.Accessibility', () => {
it('should activate tab on Enter/Space', async () => {
const onTabClick = jest.fn();
+ const onChange = jest.fn();
const user = userEvent.setup();
- render(createTabs({ onTabClick }));
+ render(createTabs({ onTabClick, onChange }));
// jump to first tab
await user.tab();
@@ -101,6 +102,7 @@ describe('Tabs.Accessibility', () => {
// activate tab
await user.keyboard(' ');
expect(onTabClick).toHaveBeenCalledTimes(1);
+ expect(onChange).not.toHaveBeenCalled();
// move focus to second tab
await user.keyboard('{ArrowRight}');
@@ -108,6 +110,7 @@ describe('Tabs.Accessibility', () => {
// activate tab
await user.keyboard('{Enter}');
expect(onTabClick).toHaveBeenCalledTimes(2);
+ expect(onChange).not.toHaveBeenCalled();
});
it('should not navigate to disabled tabs', async () => {
From 525d42c5b307f873ca56706b647feae9abd42653 Mon Sep 17 00:00:00 2001
From: afc163
Date: Tue, 1 Apr 2025 16:02:48 +0800
Subject: [PATCH 12/13] fix: Tabs press Enter/Space on active tab should not
trigger onChange
---
docs/examples/basic.tsx | 7 ++++++-
package.json | 13 ++++++-------
src/TabNavList/index.tsx | 3 ++-
tests/accessibility.test.tsx | 5 ++++-
4 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/docs/examples/basic.tsx b/docs/examples/basic.tsx
index b97a0962..7c460422 100644
--- a/docs/examples/basic.tsx
+++ b/docs/examples/basic.tsx
@@ -38,7 +38,11 @@ export default () => {
}
const onTabClick = (key: string) => {
- console.log('key', key);
+ console.log('onTabClick', key);
+ };
+
+ const onChange = (key: string) => {
+ console.log('onChange', key);
};
return (
@@ -46,6 +50,7 @@ export default () => {
diff --git a/package.json b/package.json
index 8816f77c..9a8b1ef0 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,8 @@
"now-build": "npm run build",
"prepublishOnly": "npm run lint && npm run test && npm run compile && np --yolo --no-publish",
"start": "dumi dev",
- "test": "rc-test"
+ "test": "rc-test",
+ "prepare": "husky && dumi setup"
},
"dependencies": {
"@babel/runtime": "^7.11.2",
@@ -54,21 +55,17 @@
"@types/classnames": "^2.2.10",
"@types/enzyme": "^3.10.5",
"@types/jest": "^29.4.0",
- "@types/keyv": "4.2.0",
"@types/react": "^18.2.42",
"@types/react-dom": "^18.0.11",
"@umijs/fabric": "^4.0.1",
- "coveralls": "^3.0.6",
"cross-env": "^7.0.2",
"dumi": "^2.0.0",
"eslint": "^8.54.0",
"eslint-plugin-jest": "^28.9.0",
"eslint-plugin-unicorn": "^56.0.1",
- "fastclick": "~1.0.6",
"father": "^4.0.0",
"gh-pages": "^6.1.0",
- "history": "^5.3.0",
- "immutability-helper": "^3.0.1",
+ "husky": "^9.1.7",
"less": "^4.1.3",
"np": "^10.0.2",
"preact-compat": "^3.16.0",
@@ -78,13 +75,15 @@
"react-dnd-html5-backend": "^10.0.0",
"react-dom": "^18.0.0",
"react-sticky": "^6.0.3",
- "sortablejs": "^1.7.0",
"typescript": "^5.3.2"
},
"peerDependencies": {
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
},
+ "lint-staged": {
+ "*": "prettier --write --ignore-unknown"
+ },
"engines": {
"node": ">=8.x"
}
diff --git a/src/TabNavList/index.tsx b/src/TabNavList/index.tsx
index 332974da..8a4f4376 100644
--- a/src/TabNavList/index.tsx
+++ b/src/TabNavList/index.tsx
@@ -370,8 +370,9 @@ const TabNavList = React.forwardRef((props, ref
// Enter & Space
case 'Enter':
case 'Space': {
+ console.log('press', code);
e.preventDefault();
- onTabClick(focusKey, e);
+ onTabClick(activeKey, e);
break;
}
// Backspace
diff --git a/tests/accessibility.test.tsx b/tests/accessibility.test.tsx
index 25081cda..2114320a 100644
--- a/tests/accessibility.test.tsx
+++ b/tests/accessibility.test.tsx
@@ -91,9 +91,10 @@ describe('Tabs.Accessibility', () => {
it('should activate tab on Enter/Space', async () => {
const onTabClick = jest.fn();
+ const onChange = jest.fn();
const user = userEvent.setup();
- render(createTabs({ onTabClick }));
+ render(createTabs({ onTabClick, onChange }));
// jump to first tab
await user.tab();
@@ -101,6 +102,7 @@ describe('Tabs.Accessibility', () => {
// activate tab
await user.keyboard(' ');
expect(onTabClick).toHaveBeenCalledTimes(1);
+ expect(onChange).not.toHaveBeenCalled();
// move focus to second tab
await user.keyboard('{ArrowRight}');
@@ -108,6 +110,7 @@ describe('Tabs.Accessibility', () => {
// activate tab
await user.keyboard('{Enter}');
expect(onTabClick).toHaveBeenCalledTimes(2);
+ expect(onChange).not.toHaveBeenCalled();
});
it('should not navigate to disabled tabs', async () => {
From acb0cceceb16438619819e867711314e04fe11fb Mon Sep 17 00:00:00 2001
From: afc163
Date: Tue, 1 Apr 2025 16:04:45 +0800
Subject: [PATCH 13/13] Apply suggestions from code review
---
package.json | 7 +------
src/TabNavList/index.tsx | 1 -
2 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/package.json b/package.json
index 9a8b1ef0..e50aacc8 100644
--- a/package.json
+++ b/package.json
@@ -34,8 +34,7 @@
"now-build": "npm run build",
"prepublishOnly": "npm run lint && npm run test && npm run compile && np --yolo --no-publish",
"start": "dumi dev",
- "test": "rc-test",
- "prepare": "husky && dumi setup"
+ "test": "rc-test"
},
"dependencies": {
"@babel/runtime": "^7.11.2",
@@ -65,7 +64,6 @@
"eslint-plugin-unicorn": "^56.0.1",
"father": "^4.0.0",
"gh-pages": "^6.1.0",
- "husky": "^9.1.7",
"less": "^4.1.3",
"np": "^10.0.2",
"preact-compat": "^3.16.0",
@@ -81,9 +79,6 @@
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
},
- "lint-staged": {
- "*": "prettier --write --ignore-unknown"
- },
"engines": {
"node": ">=8.x"
}
diff --git a/src/TabNavList/index.tsx b/src/TabNavList/index.tsx
index 8a4f4376..6693bd34 100644
--- a/src/TabNavList/index.tsx
+++ b/src/TabNavList/index.tsx
@@ -370,7 +370,6 @@ const TabNavList = React.forwardRef((props, ref
// Enter & Space
case 'Enter':
case 'Space': {
- console.log('press', code);
e.preventDefault();
onTabClick(activeKey, e);
break;