@@ -5,27 +5,36 @@ import { PickOptional } from '../../helpers/typeUtils';
55import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon' ;
66import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon' ;
77import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon' ;
8- import { getUniqueId , isElementInView , formatBreakpointMods , getLanguageDirection } from '../../helpers/util' ;
8+ import {
9+ getUniqueId ,
10+ isElementInView ,
11+ formatBreakpointMods ,
12+ getLanguageDirection ,
13+ getInlineStartProperty
14+ } from '../../helpers/util' ;
915import { TabContent } from './TabContent' ;
1016import { TabProps } from './Tab' ;
1117import { TabsContextProvider } from './TabsContext' ;
12- import { OverflowTab } from './OverflowTab' ;
18+ import { OverflowTab , HorizontalOverflowPopperProps } from './OverflowTab' ;
1319import { Button } from '../Button' ;
1420import { getOUIAProps , OUIAProps , getDefaultOUIAId , canUseDOM } from '../../helpers' ;
1521import { GenerateId } from '../../helpers/GenerateId/GenerateId' ;
22+ import linkAccentLength from '@patternfly/react-tokens/dist/esm/c_tabs_link_accent_length' ;
23+ import linkAccentStart from '@patternfly/react-tokens/dist/esm/c_tabs_link_accent_start' ;
1624
1725export enum TabsComponent {
1826 div = 'div' ,
1927 nav = 'nav'
2028}
21-
2229export interface HorizontalOverflowObject {
2330 /** Flag which shows the count of overflowing tabs when enabled */
2431 showTabCount ?: boolean ;
2532 /** The text which displays when an overflowing tab isn't selected */
2633 defaultTitleText ?: string ;
2734 /** The aria label applied to the button which toggles the tab overflow menu */
2835 toggleAriaLabel ?: string ;
36+ /** Additional props to spread to the popper menu. */
37+ popperProps ?: HorizontalOverflowPopperProps ;
2938}
3039
3140type TabElement = React . ReactElement < TabProps , React . JSXElementConstructor < TabProps > > ;
@@ -139,6 +148,9 @@ interface TabsState {
139148 uncontrolledIsExpandedLocal : boolean ;
140149 ouiaStateId : string ;
141150 overflowingTabCount : number ;
151+ isInitializingAccent : boolean ;
152+ currentLinkAccentLength : string ;
153+ currentLinkAccentStart : string ;
142154}
143155
144156class Tabs extends Component < TabsProps , TabsState > {
@@ -158,7 +170,10 @@ class Tabs extends Component<TabsProps, TabsState> {
158170 uncontrolledActiveKey : this . props . defaultActiveKey ,
159171 uncontrolledIsExpandedLocal : this . props . defaultIsExpanded ,
160172 ouiaStateId : getDefaultOUIAId ( Tabs . displayName ) ,
161- overflowingTabCount : 0
173+ overflowingTabCount : 0 ,
174+ isInitializingAccent : true ,
175+ currentLinkAccentLength : linkAccentLength . value ,
176+ currentLinkAccentStart : linkAccentStart . value
162177 } ;
163178
164179 if ( this . props . isVertical && this . props . expandable !== undefined ) {
@@ -328,30 +343,68 @@ class Tabs extends Component<TabsProps, TabsState> {
328343 }
329344 } ;
330345
346+ setAccentStyles = ( shouldInitializeStyle ?: boolean ) => {
347+ const currentItem = this . tabList . current . querySelector ( 'li.pf-m-current' ) as HTMLElement ;
348+ if ( ! currentItem ) {
349+ return ;
350+ }
351+
352+ const { isVertical } = this . props ;
353+ const { offsetWidth, offsetHeight, offsetTop } = currentItem ;
354+ const lengthValue = isVertical ? offsetHeight : offsetWidth ;
355+ const startValue = isVertical ? offsetTop : getInlineStartProperty ( currentItem , this . tabList . current ) ;
356+ this . setState ( {
357+ currentLinkAccentLength : `${ lengthValue } px` ,
358+ currentLinkAccentStart : `${ startValue } px` ,
359+ ...( shouldInitializeStyle && { isInitializingAccent : true } )
360+ } ) ;
361+
362+ setTimeout ( ( ) => {
363+ this . setState ( { isInitializingAccent : false } ) ;
364+ } , 0 ) ;
365+ } ;
366+
367+ handleResize = ( ) => {
368+ this . handleScrollButtons ( ) ;
369+ this . setAccentStyles ( ) ;
370+ } ;
371+
331372 componentDidMount ( ) {
332373 if ( ! this . props . isVertical ) {
333374 if ( canUseDOM ) {
334- window . addEventListener ( 'resize' , this . handleScrollButtons , false ) ;
375+ window . addEventListener ( 'resize' , this . handleResize , false ) ;
335376 }
336377 this . direction = getLanguageDirection ( this . tabList . current ) ;
337378 // call the handle resize function to check if scroll buttons should be shown
338379 this . handleScrollButtons ( ) ;
339380 }
381+
382+ this . setAccentStyles ( true ) ;
340383 }
341384
342385 componentWillUnmount ( ) {
343386 if ( ! this . props . isVertical ) {
344387 if ( canUseDOM ) {
345- window . removeEventListener ( 'resize' , this . handleScrollButtons , false ) ;
388+ window . removeEventListener ( 'resize' , this . handleResize , false ) ;
346389 }
347390 }
348391 clearTimeout ( this . scrollTimeout ) ;
349392 this . leftScrollButtonRef . current ?. removeEventListener ( 'transitionend' , this . hideScrollButtons ) ;
350393 }
351394
352395 componentDidUpdate ( prevProps : TabsProps , prevState : TabsState ) {
353- const { activeKey, mountOnEnter, isOverflowHorizontal, children } = this . props ;
354- const { shownKeys, overflowingTabCount, enableScrollButtons } = this . state ;
396+ this . direction = getLanguageDirection ( this . tabList . current ) ;
397+ const { activeKey, mountOnEnter, isOverflowHorizontal, children, defaultActiveKey } = this . props ;
398+ const { shownKeys, overflowingTabCount, enableScrollButtons, uncontrolledActiveKey } = this . state ;
399+ const isOnCloseUpdate = ! ! prevProps . onClose !== ! ! this . props . onClose ;
400+ if (
401+ ( defaultActiveKey !== undefined && prevState . uncontrolledActiveKey !== uncontrolledActiveKey ) ||
402+ ( defaultActiveKey === undefined && prevProps . activeKey !== activeKey ) ||
403+ isOnCloseUpdate
404+ ) {
405+ this . setAccentStyles ( isOnCloseUpdate ) ;
406+ }
407+
355408 if ( prevProps . activeKey !== activeKey && mountOnEnter && shownKeys . indexOf ( activeKey ) < 0 ) {
356409 this . setState ( {
357410 shownKeys : shownKeys . concat ( activeKey )
@@ -364,6 +417,7 @@ class Tabs extends Component<TabsProps, TabsState> {
364417 Children . toArray ( prevProps . children ) . length !== Children . toArray ( children ) . length
365418 ) {
366419 this . handleScrollButtons ( ) ;
420+ this . setAccentStyles ( true ) ;
367421 }
368422
369423 const currentOverflowingTabCount = this . countOverflowingElements ( this . tabList . current ) ;
@@ -380,8 +434,6 @@ class Tabs extends Component<TabsProps, TabsState> {
380434 } else if ( prevState . enableScrollButtons && ! enableScrollButtons ) {
381435 this . setState ( { showScrollButtons : false } ) ;
382436 }
383-
384- this . direction = getLanguageDirection ( this . tabList . current ) ;
385437 }
386438
387439 static getDerivedStateFromProps ( nextProps : TabsProps , prevState : TabsState ) {
@@ -450,7 +502,10 @@ class Tabs extends Component<TabsProps, TabsState> {
450502 shownKeys,
451503 uncontrolledActiveKey,
452504 uncontrolledIsExpandedLocal,
453- overflowingTabCount
505+ overflowingTabCount,
506+ isInitializingAccent,
507+ currentLinkAccentLength,
508+ currentLinkAccentStart
454509 } = this . state ;
455510 const filteredChildren = Children . toArray ( children )
456511 . filter ( ( child ) : child is TabElement => isValidElement ( child ) )
@@ -485,6 +540,7 @@ class Tabs extends Component<TabsProps, TabsState> {
485540 unmountOnExit,
486541 localActiveKey,
487542 uniqueId,
543+ setAccentStyles : this . setAccentStyles ,
488544 handleTabClick : ( ...args ) => this . handleTabClick ( ...args ) ,
489545 handleTabClose : onClose
490546 } }
@@ -493,6 +549,7 @@ class Tabs extends Component<TabsProps, TabsState> {
493549 aria-label = { ariaLabel }
494550 className = { css (
495551 styles . tabs ,
552+ styles . modifiers . animateCurrent ,
496553 isFilled && styles . modifiers . fill ,
497554 isSubtab && styles . modifiers . subtab ,
498555 isVertical && styles . modifiers . vertical ,
@@ -505,10 +562,12 @@ class Tabs extends Component<TabsProps, TabsState> {
505562 formatBreakpointMods ( inset , styles ) ,
506563 variantStyle [ variant ] ,
507564 hasOverflowTab && styles . modifiers . overflow ,
565+ isInitializingAccent && styles . modifiers . initializingAccent ,
508566 className
509567 ) }
510568 { ...getOUIAProps ( Tabs . displayName , ouiaId !== undefined ? ouiaId : this . state . ouiaStateId , ouiaSafe ) }
511569 id = { id && id }
570+ style = { { [ linkAccentLength . name ] : currentLinkAccentLength , [ linkAccentStart . name ] : currentLinkAccentStart } }
512571 { ...props }
513572 >
514573 { expandable && isVertical && (
0 commit comments