11import '@h5web/lib' ; // eslint-disable-line import/no-duplicates -- make sure lib styles come first in CSS bundle
22
33import { KeepZoomProvider } from '@h5web/lib' ; // eslint-disable-line import/no-duplicates
4- import { useToggle } from '@react-hookz/web' ;
54import { Suspense , useState } from 'react' ;
65import { ErrorBoundary } from 'react-error-boundary' ;
7- import { ReflexContainer , ReflexElement , ReflexSplitter } from 'react-reflex' ;
6+ import {
7+ Group ,
8+ Panel ,
9+ Separator ,
10+ useDefaultLayout ,
11+ usePanelRef ,
12+ } from 'react-resizable-panels' ;
813
914import styles from './App.module.css' ;
1015import BreadcrumbsBar from './breadcrumbs/BreadcrumbsBar' ;
@@ -18,6 +23,10 @@ import Sidebar from './Sidebar';
1823import VisConfigProvider from './VisConfigProvider' ;
1924import Visualizer from './visualizer/Visualizer' ;
2025
26+ const SIDEBAR_ID = 'h5w-sidebar' ;
27+ const MAIN_AREA_ID = 'h5w-main-area' ;
28+ const RESIZE_TARGET_MIN_SIZE = { coarse : 6 , fine : 6 } ; // match CSS width (.splitter::before)
29+
2130interface Props {
2231 sidebarOpen ?: boolean ;
2332 initialPath ?: string ;
@@ -36,7 +45,6 @@ function App(props: Props) {
3645 } = props ;
3746
3847 const [ selectedPath , setSelectedPath ] = useState < string > ( initialPath ) ;
39- const [ isSidebarOpen , toggleSidebarOpen ] = useToggle ( initialSidebarOpen ) ;
4048 const [ isInspecting , setInspecting ] = useState ( false ) ;
4149
4250 const { valuesStore } = useDataContext ( ) ;
@@ -45,6 +53,17 @@ function App(props: Props) {
4553 valuesStore . abortAll ( 'entity changed' , true ) ;
4654 }
4755
56+ const { defaultLayout, onLayoutChanged } = useDefaultLayout ( {
57+ id : 'h5web:layout' ,
58+ } ) ;
59+
60+ const sidebarPanelRef = usePanelRef ( ) ;
61+ const [ isSidebarOpen , setSidebarOpen ] = useState (
62+ initialSidebarOpen
63+ ? ! defaultLayout || defaultLayout [ SIDEBAR_ID ] > 0
64+ : false ,
65+ ) ;
66+
4867 return (
4968 < ErrorBoundary
5069 FallbackComponent = { ErrorFallback }
@@ -54,32 +73,49 @@ function App(props: Props) {
5473 }
5574 } }
5675 >
57- < ReflexContainer
76+ < Group
5877 className = { styles . root }
78+ resizeTargetMinimumSize = { RESIZE_TARGET_MIN_SIZE }
79+ defaultLayout = { initialSidebarOpen ? defaultLayout : undefined }
80+ onLayoutChanged = { onLayoutChanged }
5981 data-fullscreen-root
6082 data-allow-dark-mode = { disableDarkMode ? undefined : '' }
61- orientation = "vertical"
83+ data-sidebar-collapsed = { ! isSidebarOpen || undefined }
6284 >
63- < ReflexElement
85+ < Panel
86+ id = { SIDEBAR_ID }
6487 className = { styles . sidebarArea }
65- style = { { display : isSidebarOpen ? undefined : 'none' } }
66- flex = { 25 }
88+ panelRef = { sidebarPanelRef }
89+ defaultSize = { initialSidebarOpen ? '25%' : '0%' }
6790 minSize = { 150 }
91+ collapsible
92+ onResize = { ( { inPixels : size } ) => {
93+ const isNowOpen = size > 0 ;
94+ if (
95+ ( isNowOpen && ! isSidebarOpen ) ||
96+ ( ! isNowOpen && isSidebarOpen )
97+ ) {
98+ setSidebarOpen ( isNowOpen ) ;
99+ }
100+ } }
68101 >
69102 < Sidebar selectedPath = { selectedPath } onSelect = { onSelectPath } />
70- </ ReflexElement >
103+ </ Panel >
71104
72- < ReflexSplitter
73- className = { styles . splitter }
74- style = { { display : isSidebarOpen ? undefined : 'none' } }
75- />
105+ < Separator className = { styles . splitter } />
76106
77- < ReflexElement className = { styles . mainArea } flex = { 75 } minSize = { 500 } >
107+ < Panel id = { MAIN_AREA_ID } className = { styles . mainArea } minSize = { 500 } >
78108 < BreadcrumbsBar
79109 path = { selectedPath }
80110 isSidebarOpen = { isSidebarOpen }
81111 isInspecting = { isInspecting }
82- onToggleSidebar = { toggleSidebarOpen }
112+ onToggleSidebar = { ( ) => {
113+ if ( isSidebarOpen ) {
114+ sidebarPanelRef . current ?. collapse ( ) ;
115+ } else {
116+ sidebarPanelRef . current ?. expand ( ) ;
117+ }
118+ } }
83119 onChangeInspecting = { setInspecting }
84120 onSelectPath = { onSelectPath }
85121 getFeedbackURL = { getFeedbackURL }
@@ -107,8 +143,8 @@ function App(props: Props) {
107143 </ KeepZoomProvider >
108144 </ DimMappingProvider >
109145 </ VisConfigProvider >
110- </ ReflexElement >
111- </ ReflexContainer >
146+ </ Panel >
147+ </ Group >
112148 </ ErrorBoundary >
113149 ) ;
114150}
0 commit comments