55 */
66
77import { useState , useEffect , lazy , Suspense } from 'react' ;
8+ import { motion , AnimatePresence } from 'framer-motion' ;
89import Header from './components/Header' ;
910import Footer from './components/Footer' ;
1011import ArrayVisualizer from './components/ArrayVisualizer' ;
@@ -17,6 +18,7 @@ const PythonCodePanel = lazy(() => import('./components/PythonCodePanel'));
1718const ComplexityPanel = lazy ( ( ) => import ( './components/ComplexityPanel' ) ) ;
1819import { useSortingVisualization } from './hooks/useSortingVisualization' ;
1920import { usePathfindingVisualization } from './hooks/usePathfindingVisualization' ;
21+ import { useFullScreen } from './hooks/useFullScreen' ;
2022import { generateRandomArray } from './utils/arrayHelpers' ;
2123import { createEmptyGrid } from './utils/gridHelpers' ;
2224import { algorithms } from './algorithms' ;
@@ -43,6 +45,8 @@ function App() {
4345 const [ mode , setMode ] = useState ( VISUALIZATION_MODES . MANUAL ) ;
4446 const [ isPythonPanelOpen , setIsPythonPanelOpen ] = useState ( false ) ;
4547
48+ const { isFullScreen, toggleFullScreen } = useFullScreen ( ) ;
49+
4650 const sortingVisualization = useSortingVisualization ( array , speed , mode ) ;
4751 const pathfindingVisualization = usePathfindingVisualization (
4852 gridSize ,
@@ -139,104 +143,180 @@ function App() {
139143 >
140144 Skip to main content
141145 </ a >
142- < Header />
143- < main className = "flex-1 pt-20 p-6 pb-32" role = "main" id = "main-content" >
144- < div className = "max-w-7xl mx-auto" >
145- < div className = "grid grid-cols-1 lg:grid-cols-4 gap-6" >
146- { /* Settings Panel */ }
147- < aside
148- className = "lg:col-span-1"
149- role = "complementary"
150- aria-label = "Algorithm settings"
151- >
152- < SettingsPanel
153- algorithmType = { algorithmType }
154- onAlgorithmTypeChange = { handleAlgorithmTypeChange }
155- selectedAlgorithm = {
156- algorithmType === ALGORITHM_TYPES . SORTING
157- ? selectedAlgorithm
158- : selectedPathfindingAlgorithm
159- }
160- onAlgorithmChange = { handleAlgorithmChange }
161- speed = { speed }
162- onSpeedChange = { setSpeed }
163- arraySize = { arraySize }
164- onArraySizeChange = { handleArraySizeChange }
165- gridSize = { gridSize }
166- onGridSizeChange = { handleGridSizeChange }
167- isPlaying = { visualization . isPlaying }
168- mode = { mode }
169- onModeChange = { setMode }
170- />
171- </ aside >
172146
173- { /* Visualization Area */ }
174- < section
175- className = "lg:col-span-3 space-y-6"
176- role = "region"
177- aria-label = "Algorithm visualization"
147+ < AnimatePresence mode = "wait" >
148+ { isFullScreen ? (
149+ < motion . div
150+ key = "fullscreen"
151+ initial = { { opacity : 0 } }
152+ animate = { { opacity : 1 } }
153+ exit = { { opacity : 0 } }
154+ transition = { { duration : 0.3 } }
155+ className = "w-screen h-screen bg-gray-900 flex flex-col p-4"
156+ role = "main"
157+ id = "main-content"
158+ >
159+ { /* Full Screen Visualizer */ }
160+ < div className = "flex-1 mb-4" >
161+ { algorithmType === ALGORITHM_TYPES . SORTING ? (
162+ < ArrayVisualizer
163+ array = { sortingVisualization . array }
164+ states = { sortingVisualization . states }
165+ description = { sortingVisualization . description }
166+ isComplete = { sortingVisualization . isComplete }
167+ algorithm = { selectedAlgorithm }
168+ onStepForward = { sortingVisualization . stepForward }
169+ onStepBackward = { sortingVisualization . stepBackward }
170+ mode = { mode }
171+ />
172+ ) : (
173+ < GridVisualizer
174+ states = { pathfindingVisualization . states }
175+ description = { pathfindingVisualization . description }
176+ isComplete = { pathfindingVisualization . isComplete }
177+ algorithm = { selectedPathfindingAlgorithm }
178+ gridSize = { gridSize }
179+ onStepForward = { pathfindingVisualization . stepForward }
180+ onStepBackward = { pathfindingVisualization . stepBackward }
181+ mode = { mode }
182+ />
183+ ) }
184+ </ div >
185+
186+ { /* Full Screen Control Panel */ }
187+ < ControlPanel
188+ isPlaying = { visualization . isPlaying }
189+ isComplete = { visualization . isComplete }
190+ mode = { mode }
191+ onPlay = { visualization . play }
192+ onPause = { visualization . pause }
193+ onReset = { visualization . reset }
194+ onStepForward = { visualization . stepForward }
195+ onStepBackward = { visualization . stepBackward }
196+ currentStep = { visualization . currentStep }
197+ totalSteps = { visualization . totalSteps }
198+ onGenerateArray = { handleGenerateArray }
199+ algorithmType = { algorithmType }
200+ isFullScreen = { isFullScreen }
201+ onToggleFullScreen = { toggleFullScreen }
202+ />
203+ </ motion . div >
204+ ) : (
205+ < motion . div
206+ key = "normal"
207+ initial = { { opacity : 0 } }
208+ animate = { { opacity : 1 } }
209+ exit = { { opacity : 0 } }
210+ transition = { { duration : 0.3 } }
211+ className = "flex flex-col min-h-screen"
212+ >
213+ < Header />
214+ < main
215+ className = "flex-1 pt-20 p-6 pb-32"
216+ role = "main"
217+ id = "main-content"
178218 >
179- { /* Visualizer */ }
180- < div
181- className = "h-[650px]"
182- role = "img"
183- aria-label = { `${ algorithmType === ALGORITHM_TYPES . SORTING ? selectedAlgorithm : selectedPathfindingAlgorithm } algorithm visualization` }
184- >
185- { algorithmType === ALGORITHM_TYPES . SORTING ? (
186- < ArrayVisualizer
187- array = { sortingVisualization . array }
188- states = { sortingVisualization . states }
189- description = { sortingVisualization . description }
190- isComplete = { sortingVisualization . isComplete }
191- algorithm = { selectedAlgorithm }
192- onStepForward = { sortingVisualization . stepForward }
193- onStepBackward = { sortingVisualization . stepBackward }
194- mode = { mode }
195- />
196- ) : (
197- < GridVisualizer
198- states = { pathfindingVisualization . states }
199- description = { pathfindingVisualization . description }
200- isComplete = { pathfindingVisualization . isComplete }
201- algorithm = { selectedPathfindingAlgorithm }
202- gridSize = { gridSize }
203- onStepForward = { pathfindingVisualization . stepForward }
204- onStepBackward = { pathfindingVisualization . stepBackward }
205- mode = { mode }
206- />
207- ) }
219+ < div className = "max-w-7xl mx-auto" >
220+ < div className = "grid grid-cols-1 lg:grid-cols-4 gap-6" >
221+ { /* Settings Panel */ }
222+ < aside
223+ className = "lg:col-span-1"
224+ role = "complementary"
225+ aria-label = "Algorithm settings"
226+ >
227+ < SettingsPanel
228+ algorithmType = { algorithmType }
229+ onAlgorithmTypeChange = { handleAlgorithmTypeChange }
230+ selectedAlgorithm = {
231+ algorithmType === ALGORITHM_TYPES . SORTING
232+ ? selectedAlgorithm
233+ : selectedPathfindingAlgorithm
234+ }
235+ onAlgorithmChange = { handleAlgorithmChange }
236+ speed = { speed }
237+ onSpeedChange = { setSpeed }
238+ arraySize = { arraySize }
239+ onArraySizeChange = { handleArraySizeChange }
240+ gridSize = { gridSize }
241+ onGridSizeChange = { handleGridSizeChange }
242+ isPlaying = { visualization . isPlaying }
243+ mode = { mode }
244+ onModeChange = { setMode }
245+ />
246+ </ aside >
247+
248+ { /* Visualization Area */ }
249+ < section
250+ className = "lg:col-span-3 space-y-6"
251+ role = "region"
252+ aria-label = "Algorithm visualization"
253+ >
254+ { /* Visualizer */ }
255+ < div
256+ className = "h-[650px]"
257+ role = "img"
258+ aria-label = { `${ algorithmType === ALGORITHM_TYPES . SORTING ? selectedAlgorithm : selectedPathfindingAlgorithm } algorithm visualization` }
259+ >
260+ { algorithmType === ALGORITHM_TYPES . SORTING ? (
261+ < ArrayVisualizer
262+ array = { sortingVisualization . array }
263+ states = { sortingVisualization . states }
264+ description = { sortingVisualization . description }
265+ isComplete = { sortingVisualization . isComplete }
266+ algorithm = { selectedAlgorithm }
267+ onStepForward = { sortingVisualization . stepForward }
268+ onStepBackward = { sortingVisualization . stepBackward }
269+ mode = { mode }
270+ />
271+ ) : (
272+ < GridVisualizer
273+ states = { pathfindingVisualization . states }
274+ description = { pathfindingVisualization . description }
275+ isComplete = { pathfindingVisualization . isComplete }
276+ algorithm = { selectedPathfindingAlgorithm }
277+ gridSize = { gridSize }
278+ onStepForward = { pathfindingVisualization . stepForward }
279+ onStepBackward = { pathfindingVisualization . stepBackward }
280+ mode = { mode }
281+ />
282+ ) }
283+ </ div >
284+
285+ { /* Control Panel */ }
286+ < ControlPanel
287+ isPlaying = { visualization . isPlaying }
288+ isComplete = { visualization . isComplete }
289+ mode = { mode }
290+ onPlay = { visualization . play }
291+ onPause = { visualization . pause }
292+ onReset = { visualization . reset }
293+ onStepForward = { visualization . stepForward }
294+ onStepBackward = { visualization . stepBackward }
295+ currentStep = { visualization . currentStep }
296+ totalSteps = { visualization . totalSteps }
297+ onGenerateArray = { handleGenerateArray }
298+ algorithmType = { algorithmType }
299+ isFullScreen = { isFullScreen }
300+ onToggleFullScreen = { toggleFullScreen }
301+ />
302+ </ section >
303+ </ div >
208304 </ div >
305+ </ main >
306+ < Footer />
209307
210- { /* Control Panel */ }
211- < ControlPanel
212- isPlaying = { visualization . isPlaying }
213- isComplete = { visualization . isComplete }
214- mode = { mode }
215- onPlay = { visualization . play }
216- onPause = { visualization . pause }
217- onReset = { visualization . reset }
218- onStepForward = { visualization . stepForward }
219- onStepBackward = { visualization . stepBackward }
220- currentStep = { visualization . currentStep }
221- totalSteps = { visualization . totalSteps }
222- onGenerateArray = { handleGenerateArray }
223- algorithmType = { algorithmType }
308+ { /* Floating Action Button - Only show when panel is closed */ }
309+ { ! isPythonPanelOpen && (
310+ < FloatingActionButton
311+ onClick = { ( ) => setIsPythonPanelOpen ( true ) }
312+ disabled = { ! selectedAlgorithm }
224313 />
225- </ section >
226- </ div >
227- </ div >
228- </ main >
229- < Footer />
230-
231- { /* Floating Action Button - Only show when panel is closed */ }
232- { ! isPythonPanelOpen && (
233- < FloatingActionButton
234- onClick = { ( ) => setIsPythonPanelOpen ( true ) }
235- disabled = { ! selectedAlgorithm }
236- />
237- ) }
314+ ) }
315+ </ motion . div >
316+ ) }
317+ </ AnimatePresence >
238318
239- { /* Python Code Panel */ }
319+ { /* Python Code Panel - Always available */ }
240320 < Suspense
241321 fallback = {
242322 < div className = "fixed inset-0 bg-black/50 flex items-center justify-center z-50" >
0 commit comments