Skip to content

Commit

Permalink
feat: support overwrite the more tabs dropdown props (#396)
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentLiuxiang committed Jun 13, 2021
1 parent b68f85a commit 56e59aa
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
12 changes: 8 additions & 4 deletions src/TabNavList/OperationNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Menu, { MenuItem } from 'rc-menu';
import Dropdown from 'rc-dropdown';
import type { Tab, TabsLocale, EditableConfig } from '../interface';
import AddButton from './AddButton';
import type { DropdownProps } from 'rc-dropdown/lib/Dropdown';

export interface OperationNodeProps {
prefixCls: string;
Expand All @@ -19,6 +20,7 @@ export interface OperationNodeProps {
mobile: boolean;
moreIcon?: React.ReactNode;
moreTransitionName?: string;
moreTabsDropdownProps?: Partial<DropdownProps>;
editable?: EditableConfig;
locale?: TabsLocale;
onTabClick: (key: React.Key, e: React.MouseEvent | React.KeyboardEvent) => void;
Expand All @@ -39,6 +41,7 @@ function OperationNode(
tabBarGutter,
rtl,
onTabClick,
moreTabsDropdownProps,
}: OperationNodeProps,
ref: React.Ref<HTMLDivElement>,
) {
Expand All @@ -65,7 +68,7 @@ function OperationNode(
selectedKeys={[selectedKey]}
aria-label={dropdownAriaLabel !== undefined ? dropdownAriaLabel : 'expanded dropdown'}
>
{tabs.map(tab => (
{tabs.map((tab) => (
<MenuItem
key={tab.key}
id={`${popupId}-${tab.key}`}
Expand All @@ -80,8 +83,8 @@ function OperationNode(
);

function selectOffset(offset: -1 | 1) {
const enabledTabs = tabs.filter(tab => !tab.disabled);
let selectedIndex = enabledTabs.findIndex(tab => tab.key === selectedKey) || 0;
const enabledTabs = tabs.filter((tab) => !tab.disabled);
let selectedIndex = enabledTabs.findIndex((tab) => tab.key === selectedKey) || 0;
const len = enabledTabs.length;

for (let i = 0; i < len; i += 1) {
Expand Down Expand Up @@ -149,7 +152,7 @@ function OperationNode(
}

const overlayClassName = classNames({
[`${dropdownPrefix}-rtl`]: rtl
[`${dropdownPrefix}-rtl`]: rtl,
});

const moreNode: React.ReactElement = mobile ? null : (
Expand All @@ -163,6 +166,7 @@ function OperationNode(
overlayClassName={overlayClassName}
mouseEnterDelay={0.1}
mouseLeaveDelay={0.1}
{...moreTabsDropdownProps}
>
<button
type="button"
Expand Down
12 changes: 8 additions & 4 deletions src/TabNavList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import useTouchMove from '../hooks/useTouchMove';
import useRefs from '../hooks/useRefs';
import AddButton from './AddButton';
import useSyncState from '../hooks/useSyncState';
import type { DropdownProps } from 'rc-dropdown/lib/Dropdown';

export interface TabNavListProps {
id: string;
Expand All @@ -36,6 +37,7 @@ export interface TabNavListProps {
extra?: TabBarExtraContent;
editable?: EditableConfig;
moreIcon?: React.ReactNode;
moreTabsDropdownProps?: Partial<DropdownProps>;
moreTransitionName?: string;
mobile: boolean;
tabBarGutter?: number;
Expand Down Expand Up @@ -89,6 +91,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
children,
onTabClick,
onTabScroll,
moreTabsDropdownProps,
} = props;
const tabsWrapperRef = useRef<HTMLDivElement>();
const tabListRef = useRef<HTMLDivElement>();
Expand Down Expand Up @@ -162,7 +165,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {

useTouchMove(tabsWrapperRef, (offsetX, offsetY) => {
function doMove(setState: React.Dispatch<React.SetStateAction<number>>, offset: number) {
setState(value => {
setState((value) => {
const newValue = alignInRange(value + offset);

return newValue;
Expand Down Expand Up @@ -269,7 +272,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
{ ...props, tabs },
);

const tabNodes: React.ReactElement[] = tabs.map(tab => {
const tabNodes: React.ReactElement[] = tabs.map((tab) => {
const { key } = tab;
return (
<TabNode
Expand All @@ -286,7 +289,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
renderWrapper={children}
removeAriaLabel={locale?.removeAriaLabel}
ref={getBtnRef(key)}
onClick={e => {
onClick={(e) => {
onTabClick(key, e);
}}
onRemove={() => {
Expand Down Expand Up @@ -398,7 +401,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
// Should recalculate when rtl changed
useEffect(() => {
onListHolderResize();
}, [rtl, tabBarGutter, activeKey, tabs.map(tab => tab.key).join('_')]);
}, [rtl, tabBarGutter, activeKey, tabs.map((tab) => tab.key).join('_')]);

// ========================= Render ========================
const hasDropdown = !!hiddenTabs.length;
Expand Down Expand Up @@ -478,6 +481,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
ref={operationsRef}
prefixCls={prefixCls}
tabs={hiddenTabs}
moreTabsDropdownProps={moreTabsDropdownProps}
className={!hasDropdown && operationsHiddenClassName}
/>

Expand Down
12 changes: 8 additions & 4 deletions src/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
TabBarExtraContent,
} from './interface';
import TabContext from './TabContext';
import type { DropdownProps } from 'rc-dropdown/lib/Dropdown';

/**
* Should added antd:
Expand Down Expand Up @@ -51,6 +52,7 @@ export interface TabsProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'o
tabBarStyle?: React.CSSProperties;
tabPosition?: TabPosition;
destroyInactiveTabPane?: boolean;
moreTabsDropdownProps?: Partial<DropdownProps>;

onChange?: (activeKey: string) => void;
onTabClick?: (activeKey: string, e: React.KeyboardEvent | React.MouseEvent) => void;
Expand Down Expand Up @@ -81,7 +83,7 @@ function parseTabList(children: React.ReactNode): Tab[] {

return null;
})
.filter(tab => tab);
.filter((tab) => tab);
}

function Tabs(
Expand All @@ -106,6 +108,7 @@ function Tabs(
moreIcon,
moreTransitionName,
destroyInactiveTabPane,
moreTabsDropdownProps,
renderTabBar,
onChange,
onTabClick,
Expand Down Expand Up @@ -149,18 +152,18 @@ function Tabs(
defaultValue: defaultActiveKey,
});
const [activeIndex, setActiveIndex] = useState(() =>
tabs.findIndex(tab => tab.key === mergedActiveKey),
tabs.findIndex((tab) => tab.key === mergedActiveKey),
);

// Reset active key if not exist anymore
useEffect(() => {
let newActiveIndex = tabs.findIndex(tab => tab.key === mergedActiveKey);
let newActiveIndex = tabs.findIndex((tab) => tab.key === mergedActiveKey);
if (newActiveIndex === -1) {
newActiveIndex = Math.max(0, Math.min(activeIndex, tabs.length - 1));
setMergedActiveKey(tabs[newActiveIndex]?.key);
}
setActiveIndex(newActiveIndex);
}, [tabs.map(tab => tab.key).join('_'), mergedActiveKey, activeIndex]);
}, [tabs.map((tab) => tab.key).join('_'), mergedActiveKey, activeIndex]);

// ===================== Accessibility ====================
const [mergedId, setMergedId] = useMergedState(null, {
Expand Down Expand Up @@ -212,6 +215,7 @@ function Tabs(
extra: tabBarExtraContent,
style: tabBarStyle,
panes: children,
moreTabsDropdownProps,
};

if (renderTabBar) {
Expand Down
30 changes: 29 additions & 1 deletion tests/operation-overflow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Tabs.Operation-Overflow', () => {

function btnOffsetPosition() {
const btn = this as HTMLButtonElement;
const btnList = [...btn.parentNode.childNodes].filter(ele =>
const btnList = [...btn.parentNode.childNodes].filter((ele) =>
(ele as HTMLElement).className.includes('rc-tabs-tab'),
);
const index = btnList.indexOf(btn);
Expand Down Expand Up @@ -62,4 +62,32 @@ describe('Tabs.Operation-Overflow', () => {

jest.useRealTimers();
});

it('moreTabsDropdownProps trigger click', () => {
jest.useFakeTimers();
const onEdit = jest.fn();
const wrapper = mount(
getTabs({ editable: { onEdit }, moreTabsDropdownProps: { trigger: 'click' } }),
);

triggerResize(wrapper);
act(() => {
jest.runAllTimers();
wrapper.update();
});

// hover
wrapper.find('.rc-tabs-nav-more').simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.rc-tabs-dropdown')).toHaveLength(0);

// click
wrapper.find('.rc-tabs-nav-more').simulate('click');
expect(wrapper.find('.rc-tabs-dropdown').hasClass('ant-tabs-dropdown-hidden')).toBeFalsy();

wrapper.unmount();

jest.useRealTimers();
});
});

0 comments on commit 56e59aa

Please sign in to comment.