diff --git a/docs/examples/indicator.tsx b/docs/examples/indicator.tsx index 18ea104f..90642451 100644 --- a/docs/examples/indicator.tsx +++ b/docs/examples/indicator.tsx @@ -26,38 +26,32 @@ export default () => ( origin - 20} - indicatorAlign="start" + indicator={{ size: origin => origin - 20, align: 'start' }} /> origin - 20} - indicatorAlign="center" + indicator={{ size: origin => origin - 20, align: 'center' }} /> origin - 20} - indicatorAlign="end" + indicator={{ size: origin => origin - 20, align: 'end' }} /> origin - 20} - indicatorAlign="start" + indicator={{ size: origin => origin - 20, align: 'start' }} /> origin - 20} - indicatorAlign="center" + indicator={{ size: origin => origin - 20, align: 'center' }} /> origin - 20} - indicatorAlign="end" + indicator={{ size: origin => origin - 20, align: 'end' }} /> ); diff --git a/src/TabNavList/index.tsx b/src/TabNavList/index.tsx index 0cccdfc4..2f83b907 100644 --- a/src/TabNavList/index.tsx +++ b/src/TabNavList/index.tsx @@ -51,8 +51,13 @@ export interface TabNavListProps { children?: (node: React.ReactElement) => React.ReactElement; getPopupContainer?: (node: HTMLElement) => HTMLElement; popupClassName?: string; + + /** @deprecated Use `indicator={ size: ... }` instead */ indicatorSize?: GetIndicatorSize; - indicatorAlign?: 'start' | 'center' | 'end'; + indicator?: { + size?: GetIndicatorSize; + align?: 'start' | 'center' | 'end'; + }; } const getTabSize = (tab: HTMLElement, containerRect: { x: number; y: number }) => { @@ -107,8 +112,13 @@ const TabNavList = React.forwardRef((props, ref onTabClick, onTabScroll, indicatorSize, - indicatorAlign, + indicator, } = props; + + const mergedIndicatorSize = indicator?.size || indicatorSize; + + const mergedIndicatorAlign = indicator?.align || 'center'; + const { prefixCls, tabs } = React.useContext(TabContext); const containerRef = useRef(null); const extraLeftRef = useRef(null); @@ -396,8 +406,10 @@ const TabNavList = React.forwardRef((props, ref activeTabOffset, horizontal: tabPositionTopOrBottom, rtl, - indicatorSize, - indicatorAlign, + indicator: { + size: mergedIndicatorSize, + align: mergedIndicatorAlign, + }, }); // ========================= Effect ======================== diff --git a/src/Tabs.tsx b/src/Tabs.tsx index bb8ae60c..d13e0479 100644 --- a/src/Tabs.tsx +++ b/src/Tabs.tsx @@ -70,9 +70,12 @@ export interface TabsProps popupClassName?: string; - // Indicator + /** @deprecated Use `indicator={ size: ... }` instead */ indicatorSize?: GetIndicatorSize; - indicatorAlign?: 'start' | 'center' | 'end'; + indicator?: { + size?: GetIndicatorSize; + align?: 'start' | 'center' | 'end'; + }; } const Tabs = React.forwardRef((props, ref) => { @@ -101,7 +104,7 @@ const Tabs = React.forwardRef((props, ref) => { getPopupContainer, popupClassName, indicatorSize, - indicatorAlign = 'center', + indicator, ...restProps } = props; const tabs = React.useMemo( @@ -186,7 +189,7 @@ const Tabs = React.forwardRef((props, ref) => { getPopupContainer, popupClassName, indicatorSize, - indicatorAlign, + indicator, }; return ( diff --git a/src/hooks/useIndicator.ts b/src/hooks/useIndicator.ts index 6a9ee732..172bd523 100644 --- a/src/hooks/useIndicator.ts +++ b/src/hooks/useIndicator.ts @@ -8,26 +8,28 @@ interface UseIndicatorOptions { activeTabOffset: TabOffset; horizontal: boolean; rtl: boolean; - indicatorSize: GetIndicatorSize; - indicatorAlign: 'start' | 'center' | 'end'; + indicator?: { + size?: GetIndicatorSize; + align?: 'start' | 'center' | 'end'; + }; } const useIndicator = (options: UseIndicatorOptions) => { - const { activeTabOffset, horizontal, rtl, indicatorSize, indicatorAlign } = options; + const { activeTabOffset, horizontal, rtl, indicator } = options; const [inkStyle, setInkStyle] = useState(); const inkBarRafRef = useRef(); const getLength = React.useCallback( (origin: number) => { - if (typeof indicatorSize === 'function') { - return indicatorSize(origin); + if (typeof indicator?.size === 'function') { + return indicator?.size(origin); } - if (typeof indicatorSize === 'number') { - return indicatorSize; + if (typeof indicator?.size === 'number') { + return indicator?.size; } return origin; }, - [indicatorSize], + [indicator], ); // Delay set ink style to avoid remove tab blink @@ -42,27 +44,27 @@ const useIndicator = (options: UseIndicatorOptions) => { if (horizontal) { newInkStyle.width = getLength(activeTabOffset.width); const key = rtl ? 'right' : 'left'; - if (indicatorAlign === 'start') { + if (indicator?.align === 'start') { newInkStyle[key] = activeTabOffset[key]; } - if (indicatorAlign === 'center') { + if (indicator?.align === 'center') { newInkStyle[key] = activeTabOffset[key] + activeTabOffset.width / 2; newInkStyle.transform = rtl ? 'translateX(50%)' : 'translateX(-50%)'; } - if (indicatorAlign === 'end') { + if (indicator?.align === 'end') { newInkStyle[key] = activeTabOffset[key] + activeTabOffset.width; newInkStyle.transform = 'translateX(-100%)'; } } else { newInkStyle.height = getLength(activeTabOffset.height); - if (indicatorAlign === 'start') { + if (indicator?.align === 'start') { newInkStyle.top = activeTabOffset.top; } - if (indicatorAlign === 'center') { + if (indicator?.align === 'center') { newInkStyle.top = activeTabOffset.top + activeTabOffset.height / 2; newInkStyle.transform = 'translateY(-50%)'; } - if (indicatorAlign === 'end') { + if (indicator?.align === 'end') { newInkStyle.top = activeTabOffset.top + activeTabOffset.height; newInkStyle.transform = 'translateY(-100%)'; } @@ -75,7 +77,7 @@ const useIndicator = (options: UseIndicatorOptions) => { }); return cleanInkBarRaf; - }, [activeTabOffset, horizontal, rtl, indicatorSize, indicatorAlign, getLength]); + }, [activeTabOffset, horizontal, rtl, indicator?.align, getLength]); return { style: inkStyle }; }; diff --git a/tests/index.test.tsx b/tests/index.test.tsx index 60753a34..d0f90698 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -653,22 +653,19 @@ describe('Tabs.Basic', () => { const { container: startContainer } = render( origin - 10} - indicatorAlign="start" + indicator={{ size: origin => origin - 20, align: 'start' }} />, ); const { container: centerContainer } = render( origin - 10} - indicatorAlign="center" + indicator={{ size: origin => origin - 20, align: 'center' }} />, ); const { container: endContainer } = render( origin - 10} - indicatorAlign="end" + indicator={{ size: origin => origin - 20, align: 'end' }} />, ); @@ -689,24 +686,21 @@ describe('Tabs.Basic', () => { origin - 10} - indicatorAlign="start" + indicator={{ size: origin => origin - 20, align: 'start' }} />, ); const { container: centerContainer } = render( origin - 10} - indicatorAlign="center" + indicator={{ size: origin => origin - 20, align: 'center' }} />, ); const { container: endContainer } = render( origin - 10} - indicatorAlign="end" + indicator={{ size: origin => origin - 20, align: 'end' }} />, );