@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react
22import { flatNavItems } from '../nav' ;
33import { useOutline } from './OutlineContext' ;
44import { OutlineProvider } from './OutlineProvider' ;
5+ import { NavigationContext } from '../contexts/NavigationContext' ;
56
67function BackToTop ( ) {
78 const [ visible , setVisible ] = useState ( false ) ;
@@ -232,49 +233,53 @@ export function PageLayout({
232233 setActiveSectionId ( id ) ;
233234 } , [ ] ) ;
234235
236+ const navigationValue = useMemo ( ( ) => ( { navigate : onNavigate } ) , [ onNavigate ] ) ;
237+
235238 return (
236- < OutlineProvider key = { activeTab } >
237- < BackToTop />
238- < OutlineHeader
239- activeSectionId = { activeSectionId }
240- setActiveSectionId = { setActiveSectionId }
241- onSelectSection = { onSelectSection }
242- />
243- { children }
244-
245- { /* Navigation Footer */ }
246- < div className = "mt-12 pt-6 border-t border-[var(--border-subtle)]" >
247- < div className = "flex items-center justify-between gap-4" >
248- < button
249- disabled = { ! prev }
250- onClick = { ( ) => prev && onNavigate ( prev . id ) }
251- className = { `group flex items-center gap-2 px-4 py-2.5 rounded-md text-sm font-mono border transition-all duration-200 ${
252- prev
253- ? 'bg-[var(--bg-panel)] border-[var(--border-subtle)] text-[var(--text-secondary)] hover:bg-[var(--bg-elevated)] hover:border-[var(--cyber-blue-dim)] hover:text-[var(--cyber-blue)]'
254- : 'bg-[var(--bg-void)] border-[var(--border-subtle)] text-[var(--text-muted)] cursor-not-allowed opacity-50'
255- } `}
256- >
257- < span className = { `transition-transform duration-200 ${ prev ? 'group-hover:-translate-x-1' : '' } ` } > ←</ span >
258- < span className = "max-w-[120px] truncate" > { prev ? prev . label : 'EOF' } </ span >
259- </ button >
260- < div className = "text-xs text-[var(--text-muted)] font-mono hidden sm:block" >
261- // navigate
239+ < NavigationContext . Provider value = { navigationValue } >
240+ < OutlineProvider key = { activeTab } >
241+ < BackToTop />
242+ < OutlineHeader
243+ activeSectionId = { activeSectionId }
244+ setActiveSectionId = { setActiveSectionId }
245+ onSelectSection = { onSelectSection }
246+ />
247+ { children }
248+
249+ { /* Navigation Footer */ }
250+ < div className = "mt-12 pt-6 border-t border-[var(--border-subtle)]" >
251+ < div className = "flex items-center justify-between gap-4" >
252+ < button
253+ disabled = { ! prev }
254+ onClick = { ( ) => prev && onNavigate ( prev . id ) }
255+ className = { `group flex items-center gap-2 px-4 py-2.5 rounded-md text-sm font-mono border transition-all duration-200 ${
256+ prev
257+ ? 'bg-[var(--bg-panel)] border-[var(--border-subtle)] text-[var(--text-secondary)] hover:bg-[var(--bg-elevated)] hover:border-[var(--cyber-blue-dim)] hover:text-[var(--cyber-blue)]'
258+ : 'bg-[var(--bg-void)] border-[var(--border-subtle)] text-[var(--text-muted)] cursor-not-allowed opacity-50'
259+ } `}
260+ >
261+ < span className = { `transition-transform duration-200 ${ prev ? 'group-hover:-translate-x-1' : '' } ` } > ←</ span >
262+ < span className = "max-w-[120px] truncate" > { prev ? prev . label : 'EOF' } </ span >
263+ </ button >
264+ < div className = "text-xs text-[var(--text-muted)] font-mono hidden sm:block" >
265+ // navigate
266+ </ div >
267+ < button
268+ disabled = { ! next }
269+ onClick = { ( ) => next && onNavigate ( next . id ) }
270+ className = { `group flex items-center gap-2 px-4 py-2.5 rounded-md text-sm font-mono border transition-all duration-200 ${
271+ next
272+ ? 'bg-[var(--bg-panel)] border-[var(--border-subtle)] text-[var(--text-secondary)] hover:bg-[var(--bg-elevated)] hover:border-[var(--terminal-green-dim)] hover:text-[var(--terminal-green)]'
273+ : 'bg-[var(--bg-void)] border-[var(--border-subtle)] text-[var(--text-muted)] cursor-not-allowed opacity-50'
274+ } `}
275+ >
276+ < span className = "max-w-[120px] truncate" > { next ? next . label : 'EOF' } </ span >
277+ < span className = { `transition-transform duration-200 ${ next ? 'group-hover:translate-x-1' : '' } ` } > →</ span >
278+ </ button >
262279 </ div >
263- < button
264- disabled = { ! next }
265- onClick = { ( ) => next && onNavigate ( next . id ) }
266- className = { `group flex items-center gap-2 px-4 py-2.5 rounded-md text-sm font-mono border transition-all duration-200 ${
267- next
268- ? 'bg-[var(--bg-panel)] border-[var(--border-subtle)] text-[var(--text-secondary)] hover:bg-[var(--bg-elevated)] hover:border-[var(--terminal-green-dim)] hover:text-[var(--terminal-green)]'
269- : 'bg-[var(--bg-void)] border-[var(--border-subtle)] text-[var(--text-muted)] cursor-not-allowed opacity-50'
270- } `}
271- >
272- < span className = "max-w-[120px] truncate" > { next ? next . label : 'EOF' } </ span >
273- < span className = { `transition-transform duration-200 ${ next ? 'group-hover:translate-x-1' : '' } ` } > →</ span >
274- </ button >
275280 </ div >
276- </ div >
277- </ OutlineProvider >
281+ </ OutlineProvider >
282+ </ NavigationContext . Provider >
278283 ) ;
279284}
280285
0 commit comments