|  | 
| 6 | 6 |  */ | 
| 7 | 7 | 
 | 
| 8 | 8 | import {Resizable} from 're-resizable'; | 
| 9 |  | -import React, {useCallback} from 'react'; | 
|  | 9 | +import React, { | 
|  | 10 | +  useCallback, | 
|  | 11 | +  useId, | 
|  | 12 | +  unstable_ViewTransition as ViewTransition, | 
|  | 13 | +  unstable_addTransitionType as addTransitionType, | 
|  | 14 | +  startTransition, | 
|  | 15 | +} from 'react'; | 
|  | 16 | +import {EXPAND_ACCORDION_TRANSITION} from '../lib/transitionTypes'; | 
| 10 | 17 | 
 | 
| 11 | 18 | type TabsRecord = Map<string, React.ReactNode>; | 
| 12 | 19 | 
 | 
| @@ -50,49 +57,69 @@ function AccordionWindowItem({ | 
| 50 | 57 |   setTabsOpen: (newTab: Set<string>) => void; | 
| 51 | 58 |   hasChanged: boolean; | 
| 52 | 59 | }): React.ReactElement { | 
|  | 60 | +  const id = useId(); | 
| 53 | 61 |   const isShow = tabsOpen.has(name); | 
| 54 | 62 | 
 | 
| 55 |  | -  const toggleTabs = useCallback(() => { | 
| 56 |  | -    const nextState = new Set(tabsOpen); | 
| 57 |  | -    if (nextState.has(name)) { | 
| 58 |  | -      nextState.delete(name); | 
| 59 |  | -    } else { | 
| 60 |  | -      nextState.add(name); | 
| 61 |  | -    } | 
| 62 |  | -    setTabsOpen(nextState); | 
| 63 |  | -  }, [tabsOpen, name, setTabsOpen]); | 
|  | 63 | +  const transitionName = `accordion-window-item-${id}`; | 
|  | 64 | + | 
|  | 65 | +  const toggleTabs = () => { | 
|  | 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 | +  }; | 
| 64 | 77 | 
 | 
| 65 | 78 |   // Replace spaces with non-breaking spaces | 
| 66 | 79 |   const displayName = name.replace(/ /g, '\u00A0'); | 
| 67 | 80 | 
 | 
| 68 | 81 |   return ( | 
| 69 | 82 |     <div key={name} className="flex flex-row"> | 
| 70 | 83 |       {isShow ? ( | 
| 71 |  | -        <Resizable className="border-r" minWidth={550} enable={{right: true}}> | 
| 72 |  | -          <h2 | 
| 73 |  | -            title="Minimize tab" | 
| 74 |  | -            aria-label="Minimize tab" | 
| 75 |  | -            onClick={toggleTabs} | 
| 76 |  | -            className={`p-4 duration-150 ease-in border-b cursor-pointer border-grey-200 ${ | 
| 77 |  | -              hasChanged ? 'font-bold' : 'font-light' | 
| 78 |  | -            } text-secondary hover:text-link`}> | 
| 79 |  | -            - {displayName} | 
| 80 |  | -          </h2> | 
| 81 |  | -          {tabs.get(name) ?? <div>No output for {name}</div>} | 
| 82 |  | -        </Resizable> | 
|  | 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> | 
| 83 | 103 |       ) : ( | 
| 84 |  | -        <div className="relative items-center h-full px-1 py-6 align-middle border-r border-grey-200"> | 
| 85 |  | -          <button | 
| 86 |  | -            title={`Expand compiler tab: ${name}`} | 
| 87 |  | -            aria-label={`Expand compiler tab: ${name}`} | 
| 88 |  | -            style={{transform: 'rotate(90deg) translate(-50%)'}} | 
| 89 |  | -            onClick={toggleTabs} | 
| 90 |  | -            className={`flex-grow-0 w-5 transition-colors duration-150 ease-in ${ | 
| 91 |  | -              hasChanged ? 'font-bold' : 'font-light' | 
| 92 |  | -            } text-secondary hover:text-link`}> | 
| 93 |  | -            {displayName} | 
| 94 |  | -          </button> | 
| 95 |  | -        </div> | 
|  | 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> | 
| 96 | 123 |       )} | 
| 97 | 124 |     </div> | 
| 98 | 125 |   ); | 
|  | 
0 commit comments