@@ -4,6 +4,8 @@ import useEvent from 'rc-util/lib/hooks/useEvent';
44import { useComposeRef } from 'rc-util/lib/ref' ;
55import * as React from 'react' ;
66import { useEffect , useRef , useState } from 'react' ;
7+ import type { GetIndicatorSize } from '../hooks/useIndicator' ;
8+ import useIndicator from '../hooks/useIndicator' ;
79import useOffsets from '../hooks/useOffsets' ;
810import useSyncState from '../hooks/useSyncState' ;
911import useTouchMove from '../hooks/useTouchMove' ;
@@ -26,8 +28,6 @@ import AddButton from './AddButton';
2628import ExtraContent from './ExtraContent' ;
2729import OperationNode from './OperationNode' ;
2830import TabNode from './TabNode' ;
29- import useIndicator from '../hooks/useIndicator' ;
30- import type { GetIndicatorSize } from '../hooks/useIndicator' ;
3131
3232export interface TabNavListProps {
3333 id : string ;
@@ -53,8 +53,31 @@ export interface TabNavListProps {
5353 indicatorSize ?: GetIndicatorSize ;
5454}
5555
56+ const getTabSize = ( tab : HTMLElement , containerRect : { x : number ; y : number } ) => {
57+ // tabListRef
58+ const { offsetWidth, offsetHeight, offsetTop, offsetLeft } = tab ;
59+ const { width, height, x, y } = tab . getBoundingClientRect ( ) ;
60+
61+ // Use getBoundingClientRect to avoid decimal inaccuracy
62+ if ( Math . abs ( width - offsetWidth ) < 1 ) {
63+ return [ width , height , x - containerRect . x , y - containerRect . y ] ;
64+ }
65+
66+ return [ offsetWidth , offsetHeight , offsetLeft , offsetTop ] ;
67+ } ;
68+
5669const getSize = ( refObj : React . RefObject < HTMLElement > ) : SizeInfo => {
5770 const { offsetWidth = 0 , offsetHeight = 0 } = refObj . current || { } ;
71+
72+ // Use getBoundingClientRect to avoid decimal inaccuracy
73+ if ( refObj . current ) {
74+ const { width, height } = refObj . current . getBoundingClientRect ( ) ;
75+
76+ if ( Math . abs ( width - offsetWidth ) < 1 ) {
77+ return [ width , height ] ;
78+ }
79+ }
80+
5881 return [ offsetWidth , offsetHeight ] ;
5982} ;
6083
@@ -313,14 +336,20 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
313336 const updateTabSizes = ( ) =>
314337 setTabSizes ( ( ) => {
315338 const newSizes : TabSizeMap = new Map ( ) ;
339+ const listRect = tabListRef . current ?. getBoundingClientRect ( ) ;
340+
316341 tabs . forEach ( ( { key } ) => {
317- const btnNode = tabListRef . current ?. querySelector < HTMLElement > ( `[data-node-key="${ genDataNodeKey ( key ) } "]` ) ;
342+ const btnNode = tabListRef . current ?. querySelector < HTMLElement > (
343+ `[data-node-key="${ genDataNodeKey ( key ) } "]` ,
344+ ) ;
318345 if ( btnNode ) {
346+ const [ width , height , left , top ] = getTabSize ( btnNode , listRect ) ;
347+
319348 newSizes . set ( key , {
320- width : btnNode . offsetWidth ,
321- height : btnNode . offsetHeight ,
322- left : btnNode . offsetLeft ,
323- top : btnNode . offsetTop ,
349+ width,
350+ height,
351+ left,
352+ top,
324353 } ) ;
325354 }
326355 } ) ;
@@ -370,7 +399,7 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
370399 horizontal : tabPositionTopOrBottom ,
371400 rtl,
372401 indicatorSize,
373- } )
402+ } ) ;
374403
375404 // ========================= Effect ========================
376405 useEffect ( ( ) => {
@@ -437,33 +466,33 @@ function TabNavList(props: TabNavListProps, ref: React.Ref<HTMLDivElement>) {
437466 ref = { tabsWrapperRef }
438467 >
439468 < ResizeObserver onResize = { onListHolderResize } >
440- < div
441- ref = { tabListRef }
442- className = { `${ prefixCls } -nav-list` }
443- style = { {
444- transform : `translate(${ transformLeft } px, ${ transformTop } px)` ,
445- transition : lockAnimation ? 'none' : undefined ,
446- } }
447- >
448- { tabNodes }
449- < AddButton
450- ref = { innerAddButtonRef }
451- prefixCls = { prefixCls }
452- locale = { locale }
453- editable = { editable }
469+ < div
470+ ref = { tabListRef }
471+ className = { `${ prefixCls } -nav-list` }
454472 style = { {
455- ... ( tabNodes . length === 0 ? undefined : tabNodeStyle ) ,
456- visibility : hasDropdown ? 'hidden ' : null ,
473+ transform : `translate( ${ transformLeft } px, ${ transformTop } px)` ,
474+ transition : lockAnimation ? 'none ' : undefined ,
457475 } }
458- />
459-
460- < div
461- className = { classNames ( `${ prefixCls } -ink-bar` , {
462- [ `${ prefixCls } -ink-bar-animated` ] : animated . inkBar ,
463- } ) }
464- style = { indicatorStyle }
465- />
466- </ div >
476+ >
477+ { tabNodes }
478+ < AddButton
479+ ref = { innerAddButtonRef }
480+ prefixCls = { prefixCls }
481+ locale = { locale }
482+ editable = { editable }
483+ style = { {
484+ ...( tabNodes . length === 0 ? undefined : tabNodeStyle ) ,
485+ visibility : hasDropdown ? 'hidden' : null ,
486+ } }
487+ />
488+
489+ < div
490+ className = { classNames ( `${ prefixCls } -ink-bar` , {
491+ [ `${ prefixCls } -ink-bar-animated` ] : animated . inkBar ,
492+ } ) }
493+ style = { indicatorStyle }
494+ />
495+ </ div >
467496 </ ResizeObserver >
468497 </ div >
469498 </ ResizeObserver >
0 commit comments