@@ -8,7 +8,7 @@ import { tcls } from '@/lib/tailwind';
88import { Button , Link } from '../primitives' ;
99
1010/**
11- * A set of tabs representing site sections for multi-section sites
11+ * A set of navigational tabs representing site sections for multi-section sites
1212 */
1313export function SiteSectionTabs ( props : { sections : SiteSection [ ] ; section : SiteSection } ) {
1414 const { sections, section : currentSection } = props ;
@@ -22,34 +22,36 @@ export function SiteSectionTabs(props: { sections: SiteSection[]; section: SiteS
2222 const currentTabRef = React . useRef < HTMLAnchorElement > ( null ) ;
2323 const navRef = React . useRef < HTMLDivElement > ( null ) ;
2424
25- const [ currentIndex , setCurrentIndex ] = React . useState (
26- sections . findIndex ( ( section ) => section . id === currentSection ?. id ) ,
27- ) ;
25+ // we don't set the current tab with a click event because the tab will navigate to a different section and trigger a page reload.
26+ const currentIndex = sections . findIndex ( ( section ) => section . id === currentSection ?. id ) ;
27+
2828 const [ tabDimensions , setTabDimensions ] = React . useState < {
2929 left : number ;
3030 width : number ;
3131 } | null > ( null ) ;
3232
33- React . useEffect ( ( ) => {
33+ const updateTabDimensions = React . useCallback ( ( ) => {
3434 if ( currentTabRef . current && navRef . current ) {
3535 const rect = currentTabRef . current . getBoundingClientRect ( ) ;
3636 const navRect = navRef . current . getBoundingClientRect ( ) ;
3737 setTabDimensions ( { left : rect . left - navRect . left , width : rect . width } ) ;
3838 }
39- } , [ currentIndex ] ) ;
39+ } , [ ] ) ;
40+
41+ React . useEffect ( ( ) => {
42+ updateTabDimensions ( ) ;
43+ } , [ currentIndex , updateTabDimensions ] ) ;
4044
4145 React . useLayoutEffect ( ( ) => {
42- function onResize ( ) {
43- if ( currentTabRef . current && navRef . current ) {
44- const rect = currentTabRef . current . getBoundingClientRect ( ) ;
45- const navRect = navRef . current . getBoundingClientRect ( ) ;
46- setTabDimensions ( { left : rect . left - navRect . left , width : rect . width } ) ;
47- }
46+ window . addEventListener ( 'load' , updateTabDimensions ) ;
47+ window . addEventListener ( 'resize' , updateTabDimensions ) ;
48+ ( ) => {
49+ window . removeEventListener ( 'resize' , updateTabDimensions ) ;
50+ window . removeEventListener ( 'load' , updateTabDimensions ) ;
4851 }
49- window . addEventListener ( 'resize' , onResize ) ;
50- ( ) => window . removeEventListener ( 'resize' , onResize ) ;
51- } , [ ] ) ;
52+ } , [ updateTabDimensions ] ) ;
5253
54+ const opacity = Boolean ( tabDimensions ) ? 1 : 0.0 ;
5355 const scale = ( tabDimensions ?. width ?? 0 ) * 0.01 ;
5456 const startPos = `${ tabDimensions ?. left ?? 0 } px` ;
5557
@@ -62,6 +64,7 @@ export function SiteSectionTabs(props: { sections: SiteSection[]; section: SiteS
6264 className = "flex flex-nowrap items-center max-w-screen mb-px"
6365 style = {
6466 {
67+ '--tab-opacity' : `${ opacity } ` ,
6568 '--tab-scale' : `${ scale } ` ,
6669 '--tab-start' : `${ startPos } ` ,
6770 } as React . CSSProperties
@@ -80,9 +83,12 @@ export function SiteSectionTabs(props: { sections: SiteSection[]; section: SiteS
8083 'after:absolute' ,
8184 'after:-bottom-px' ,
8285 'after:left-0' ,
86+ 'after:opacity-[--tab-opacity]' ,
8387 'after:scale-x-[--tab-scale]' ,
84- 'after:transition-transform' ,
88+ 'after:transition-all' ,
89+ 'after:motion-reduce:transition-none' ,
8590 'after:translate-x-[var(--tab-start)]' ,
91+ 'after:will-change-transform' ,
8692 'after:h-0.5' ,
8793 'after:w-[100px]' ,
8894 'after:bg-primary' ,
@@ -97,7 +103,6 @@ export function SiteSectionTabs(props: { sections: SiteSection[]; section: SiteS
97103 label = { tab . label }
98104 href = { tab . path }
99105 ref = { currentIndex === index ? currentTabRef : null }
100- onClick = { ( ) => setCurrentIndex ( index ) }
101106 />
102107 ) ) }
103108 </ div >
@@ -111,9 +116,9 @@ export function SiteSectionTabs(props: { sections: SiteSection[]; section: SiteS
111116 */
112117const Tab = React . forwardRef <
113118 HTMLSpanElement ,
114- { active : boolean ; href : string ; label : string ; onClick ?: ( ) => void }
119+ { active : boolean ; href : string ; label : string ; }
115120> ( function Tab ( props , ref ) {
116- const { active, href, label, onClick } = props ;
121+ const { active, href, label } = props ;
117122 return (
118123 < Link
119124 className = { tcls (
@@ -124,7 +129,6 @@ const Tab = React.forwardRef<
124129 ) }
125130 role = "tab"
126131 href = { href }
127- onClick = { onClick }
128132 >
129133 < span ref = { ref } className = { tcls ( 'inline-flex w-full truncate' ) } >
130134 { label }
0 commit comments