@@ -136,6 +136,25 @@ const variantStyle = {
136136 secondary : styles . modifiers . secondary
137137} ;
138138
139+ const getHashFromHref = ( href ?: string ) => {
140+ const hashIndex = href ?. indexOf ( '#' ) ?? - 1 ;
141+
142+ return hashIndex >= 0 ? href . slice ( hashIndex ) : undefined ;
143+ } ;
144+
145+ const getTabHashActiveKey = ( { children, component, isNav } : Pick < TabsProps , 'children' | 'component' | 'isNav' > ) => {
146+ if ( ! canUseDOM || ! ( component === TabsComponent . nav || isNav ) || ! window . location . hash ) {
147+ return undefined ;
148+ }
149+
150+ return Children . toArray ( children )
151+ . filter ( ( child ) : child is TabElement => isValidElement ( child ) )
152+ . filter ( ( { props } ) => ! props . isHidden )
153+ . find (
154+ ( { props } ) => ! props . isDisabled && ! props . isAriaDisabled && getHashFromHref ( props . href ) === window . location . hash
155+ ) ?. props . eventKey ;
156+ } ;
157+
139158interface TabsState {
140159 /** Used to signal if the scroll buttons should be used */
141160 enableScrollButtons : boolean ;
@@ -164,13 +183,18 @@ class Tabs extends Component<TabsProps, TabsState> {
164183 private direction = 'ltr' ;
165184 constructor ( props : TabsProps ) {
166185 super ( props ) ;
186+ const hashActiveKey = getTabHashActiveKey ( props ) ;
187+
167188 this . state = {
168189 enableScrollButtons : false ,
169190 showScrollButtons : false ,
170191 renderScrollButtons : false ,
171192 disableBackScrollButton : true ,
172193 disableForwardScrollButton : true ,
173- shownKeys : this . props . defaultActiveKey !== undefined ? [ this . props . defaultActiveKey ] : [ this . props . activeKey ] , // only for mountOnEnter case
194+ shownKeys :
195+ this . props . defaultActiveKey !== undefined
196+ ? [ hashActiveKey ?? this . props . defaultActiveKey ]
197+ : [ hashActiveKey ?? this . props . activeKey ] , // only for mountOnEnter case
174198 uncontrolledActiveKey : this . props . defaultActiveKey ,
175199 uncontrolledIsExpandedLocal : this . props . defaultIsExpanded ,
176200 ouiaStateId : getDefaultOUIAId ( Tabs . displayName ) ,
@@ -221,6 +245,7 @@ class Tabs extends Component<TabsProps, TabsState> {
221245 ) {
222246 const { shownKeys } = this . state ;
223247 const { onSelect, defaultActiveKey } = this . props ;
248+
224249 // if defaultActiveKey Tabs are uncontrolled, set new active key internally
225250 if ( defaultActiveKey !== undefined ) {
226251 this . setState ( {
@@ -401,6 +426,7 @@ class Tabs extends Component<TabsProps, TabsState> {
401426 const { activeKey, mountOnEnter, isOverflowHorizontal, children, defaultActiveKey } = this . props ;
402427 const { shownKeys, overflowingTabCount, enableScrollButtons, uncontrolledActiveKey } = this . state ;
403428 const isOnCloseUpdate = ! ! prevProps . onClose !== ! ! this . props . onClose ;
429+
404430 if (
405431 ( defaultActiveKey !== undefined && prevState . uncontrolledActiveKey !== uncontrolledActiveKey ) ||
406432 ( defaultActiveKey === undefined && prevProps . activeKey !== activeKey ) ||
@@ -530,7 +556,8 @@ class Tabs extends Component<TabsProps, TabsState> {
530556 const uniqueId = id || getUniqueId ( ) ;
531557 const defaultComponent = isNav && ! component ? 'nav' : 'div' ;
532558 const Component : any = component !== undefined ? component : defaultComponent ;
533- const localActiveKey = defaultActiveKey !== undefined ? uncontrolledActiveKey : activeKey ;
559+ const hashActiveKey = getTabHashActiveKey ( { children, component, isNav } ) ;
560+ const localActiveKey = hashActiveKey ?? ( defaultActiveKey !== undefined ? uncontrolledActiveKey : activeKey ) ;
534561
535562 const isExpandedLocal = defaultIsExpanded !== undefined ? uncontrolledIsExpandedLocal : isExpanded ;
536563 /* Uncontrolled expandable tabs */
0 commit comments