diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 40b24d7..872f868 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -54,6 +54,36 @@ export default function App() { const tmDragY0 = useRef(0) const tmDragH0 = useRef(0) + // Focus mode — collapses sidebar, bundles nav, terminal for distraction-free reading + const [focusMode, setFocusMode] = useState(false) + const focusSavedState = useRef(null) + + const toggleFocusMode = useCallback(() => { + if (!focusMode) { + // Save current states then collapse everything + focusSavedState.current = { sidebarCollapsed, bundlesCollapsed, termCollapsed } + setSidebarCollapsed(true) + setBundlesCollapsed(true) + setTermCollapsed(true) + setFocusMode(true) + } else { + // Restore previous states + const saved = focusSavedState.current || {} + setSidebarCollapsed(saved.sidebarCollapsed ?? false) + setBundlesCollapsed(saved.bundlesCollapsed ?? false) + setTermCollapsed(saved.termCollapsed ?? false) + setFocusMode(false) + } + }, [focusMode, sidebarCollapsed, bundlesCollapsed, termCollapsed]) + + // If the user manually opens any panel while in focus mode, exit focus mode + // so the button icon reverts to "expand" (next click re-collapses everything) + useEffect(() => { + if (focusMode && (!sidebarCollapsed || !bundlesCollapsed || !termCollapsed)) { + setFocusMode(false) + } + }, [sidebarCollapsed, bundlesCollapsed, termCollapsed, focusMode]) + // Track previous scenario id to teardown on switch const prevActiveIdRef = useRef(null) @@ -330,6 +360,8 @@ export default function App() { isExamMode={!!examSession} examProgress={examProgress} totalExamWeight={totalExamWeight} + focusMode={focusMode} + onToggleFocus={toggleFocusMode} /> diff --git a/frontend/src/components/ScenarioPanel.jsx b/frontend/src/components/ScenarioPanel.jsx index 61ef502..8b189f5 100644 --- a/frontend/src/components/ScenarioPanel.jsx +++ b/frontend/src/components/ScenarioPanel.jsx @@ -24,7 +24,7 @@ async function resetProgress(scope, opts) { }) } -export default function ScenarioPanel({ scenario, onProgressUpdate, onScenarioStart, isExamMode, examProgress, totalExamWeight }) { +export default function ScenarioPanel({ scenario, onProgressUpdate, onScenarioStart, isExamMode, examProgress, totalExamWeight, focusMode, onToggleFocus }) { const [tab, setTab] = useState('problem') const [setupState, setSetupState] = useState('idle') // idle | running | done | error const [validating, setValidating] = useState(false) @@ -216,6 +216,29 @@ export default function ScenarioPanel({ scenario, onProgressUpdate, onScenarioSt
{scenario.title}
+ {onToggleFocus && !isExamMode && ( + + )} {isExamMode && scenario.progress?.started_at && (
@@ -238,6 +261,29 @@ export default function ScenarioPanel({ scenario, onProgressUpdate, onScenarioSt
)} + {onToggleFocus && isExamMode && ( + + )} {scenario.progress?.status !== 'not_started' && scenario.progress?.attempts > 0 && (