main
tsx 126 lines 3.63 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
8 import {Resizable} from 're-resizable';
9 import React, {
10 useId,
11 unstable_ViewTransition as ViewTransition,
12 unstable_addTransitionType as addTransitionType,
13 startTransition,
14 } from 'react';
15 import {EXPAND_ACCORDION_TRANSITION} from '../lib/transitionTypes';
16
17 type TabsRecord = Map<string, React.ReactNode>;
18
19 export default function AccordionWindow(props: {
20 defaultTab: string | null;
21 tabs: TabsRecord;
22 tabsOpen: Set<string>;
23 setTabsOpen: (newTab: Set<string>) => void;
24 changedPasses: Set<string>;
25 }): React.ReactElement {
26 return (
27 <div className="flex-1 min-w-[550px] sm:min-w-0">
28 <div className="flex flex-row h-full">
29 {Array.from(props.tabs.keys()).map(name => {
30 return (
31 <AccordionWindowItem
32 name={name}
33 key={name}
34 tabs={props.tabs}
35 tabsOpen={props.tabsOpen}
36 setTabsOpen={props.setTabsOpen}
37 hasChanged={props.changedPasses.has(name)}
38 />
39 );
40 })}
41 </div>
42 </div>
43 );
44 }
45
46 function AccordionWindowItem({
47 name,
48 tabs,
49 tabsOpen,
50 setTabsOpen,
51 hasChanged,
52 }: {
53 name: string;
54 tabs: TabsRecord;
55 tabsOpen: Set<string>;
56 setTabsOpen: (newTab: Set<string>) => void;
57 hasChanged: boolean;
58 isFailure: boolean;
59 }): React.ReactElement {
60 const id = useId();
61 const isShow = tabsOpen.has(name);
62
63 const transitionName = `accordion-window-item-${id}`;
64
65 const toggleTabs = (): void => {
66 startTransition(() => {
67 addTransitionType(EXPAND_ACCORDION_TRANSITION);
68 const nextState = new Set(tabsOpen);
69 if (nextState.has(name)) {
70 nextState.delete(name);
71 } else {
72 nextState.add(name);
73 }
74 setTabsOpen(nextState);
75 });
76 };
77
78 // Replace spaces with non-breaking spaces
79 const displayName = name.replace(/ /g, '\u00A0');
80
81 return (
82 <div key={name} className="flex flex-row">
83 {isShow ? (
84 <ViewTransition
85 name={transitionName}
86 update={{
87 [EXPAND_ACCORDION_TRANSITION]: 'expand-accordion',
88 default: 'none',
89 }}>
90 <Resizable className="border-r" minWidth={550} enable={{right: true}}>
91 <h2
92 title="Minimize tab"
93 aria-label="Minimize tab"
94 onClick={toggleTabs}
95 className={`p-4 duration-150 ease-in border-b cursor-pointer border-grey-200 ${
96 hasChanged ? 'font-bold' : 'font-light'
97 } text-secondary hover:text-link`}>
98 - {displayName}
99 </h2>
100 {tabs.get(name) ?? <div>No output for {name}</div>}
101 </Resizable>
102 </ViewTransition>
103 ) : (
104 <ViewTransition
105 name={transitionName}
106 update={{
107 [EXPAND_ACCORDION_TRANSITION]: 'expand-accordion',
108 default: 'none',
109 }}>
110 <div className="relative items-center h-full px-1 py-6 align-middle border-r border-grey-200">
111 <button
112 title={`Expand compiler tab: ${name}`}
113 aria-label={`Expand compiler tab: ${name}`}
114 style={{transform: 'rotate(90deg) translate(-50%)'}}
115 onClick={toggleTabs}
116 className={`flex-grow-0 w-5 transition-colors duration-150 ease-in ${
117 hasChanged ? 'font-bold' : 'font-light'
118 } text-secondary hover:text-link`}>
119 {displayName}
120 </button>
121 </div>
122 </ViewTransition>
123 )}
124 </div>
125 );
126 }