44 * This source code is licensed under the MIT license found in the
55 * LICENSE file in the root directory of this source tree.
66 */
7- import React from 'react' ;
7+ import React , {
8+ startTransition ,
9+ useId ,
10+ unstable_ViewTransition as ViewTransition ,
11+ unstable_addTransitionType as addTransitionType ,
12+ } from 'react' ;
813import clsx from 'clsx' ;
914
1015export default function TabbedWindow ( {
@@ -16,30 +21,50 @@ export default function TabbedWindow({
1621 activeTab : string ;
1722 onTabChange : ( tab : string ) => void ;
1823} ) : React . ReactElement {
24+ const id = useId ( ) ;
25+ const transitionName = `tab-highlight-${ id } ` ;
26+
27+ const handleTabChange = ( tab : string ) : void => {
28+ startTransition ( ( ) => {
29+ addTransitionType ( 'tab' ) ;
30+ onTabChange ( tab ) ;
31+ } ) ;
32+ } ;
33+
1934 return (
20- < div className = "flex-1 min-w-[550px] sm:min-w-0" >
21- < div className = "flex flex-col h-full max-w-full" >
22- < div className = "flex p-2 flex-shrink-0" >
23- { Array . from ( tabs . keys ( ) ) . map ( tab => {
24- const isActive = activeTab === tab ;
25- return (
26- < button
27- key = { tab }
28- onClick = { ( ) => onTabChange ( tab ) }
29- className = { clsx (
30- 'active:scale-95 transition-transform py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full text-sm' ,
31- ! isActive && 'hover:bg-primary/5' ,
32- isActive && 'bg-highlight text-link' ,
33- ) } >
34- { tab }
35- </ button >
36- ) ;
37- } ) }
38- </ div >
39- < div className = "flex-1 overflow-hidden w-full h-full" >
40- { tabs . get ( activeTab ) }
41- </ div >
35+ < div className = "flex-1 min-w-[550px] sm:min-w-0" >
36+
37+ < div className = "flex flex-col h-full max-w-full" >
38+ < div className = "flex p-2 flex-shrink-0" >
39+ { Array . from ( tabs . keys ( ) ) . map ( tab => {
40+ const isActive = activeTab === tab ;
41+ return (
42+ < button
43+ key = { tab }
44+ onClick = { ( ) => handleTabChange ( tab ) }
45+ className = { clsx (
46+ 'transition-transform py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full text-sm relative' ,
47+ isActive ? 'text-link' : 'hover:bg-primary/5' ,
48+ ) } >
49+ { isActive && (
50+ < ViewTransition
51+ name = { transitionName }
52+ share = { { tab : 'tab-highlight' } }
53+ update = { { default : 'none' } } >
54+ < div className = "absolute inset-0 bg-highlight rounded-full" />
55+ </ ViewTransition >
56+ ) }
57+ < ViewTransition update = { { tab : 'tab-text' , default : 'none' } } >
58+ < span className = "relative z-1" > { tab } </ span >
59+ </ ViewTransition >
60+ </ button >
61+ ) ;
62+ } ) }
4263 </ div >
64+ < div className = "flex-1 overflow-hidden w-full h-full" >
65+ { tabs . get ( activeTab ) }
66+ </ div >
67+ </ div >
4368 </ div >
4469 ) ;
4570}
0 commit comments