main
tsx 81 lines 2.53 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7 import React, {
8 startTransition,
9 useId,
10 unstable_ViewTransition as ViewTransition,
11 unstable_addTransitionType as addTransitionType,
12 } from 'react';
13 import clsx from 'clsx';
14 import {TOGGLE_TAB_TRANSITION} from '../lib/transitionTypes';
15
16 export default function TabbedWindow({
17 tabs,
18 activeTab,
19 onTabChange,
20 }: {
21 tabs: Map<string, React.ReactNode>;
22 activeTab: string;
23 onTabChange: (tab: string) => void;
24 }): React.ReactElement {
25 const id = useId();
26 const transitionName = `tab-highlight-${id}`;
27
28 const handleTabChange = (tab: string): void => {
29 startTransition(() => {
30 addTransitionType(TOGGLE_TAB_TRANSITION);
31 onTabChange(tab);
32 });
33 };
34
35 return (
36 <div className="flex-1 min-w-[550px] sm:min-w-0">
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 enter={{default: 'none'}}
53 exit={{default: 'none'}}
54 share={{
55 [TOGGLE_TAB_TRANSITION]: 'tab-highlight',
56 default: 'none',
57 }}
58 update={{default: 'none'}}>
59 <div className="absolute inset-0 bg-highlight rounded-full" />
60 </ViewTransition>
61 )}
62 <ViewTransition
63 enter={{default: 'none'}}
64 exit={{default: 'none'}}
65 update={{
66 [TOGGLE_TAB_TRANSITION]: 'tab-text',
67 default: 'none',
68 }}>
69 <span className="relative z-1">{tab}</span>
70 </ViewTransition>
71 </button>
72 );
73 })}
74 </div>
75 <div className="flex-1 overflow-hidden w-full h-full">
76 {tabs.get(activeTab)}
77 </div>
78 </div>
79 </div>
80 );
81 }