diff --git a/frontend/src/core/components/shared/Tooltip.tsx b/frontend/src/core/components/shared/Tooltip.tsx index 10fefec02..2580b3530 100644 --- a/frontend/src/core/components/shared/Tooltip.tsx +++ b/frontend/src/core/components/shared/Tooltip.tsx @@ -83,7 +83,10 @@ export const Tooltip: React.FC = ({ } }, []); - const sidebarContext = sidebarTooltip ? useSidebarContext() : null; + // Always call the hook unconditionally to satisfy React's rules of hooks. + // The context is only used when sidebarTooltip is true. + const sidebarContextValue = useSidebarContext(); + const sidebarContext = sidebarTooltip ? sidebarContextValue : null; const isControlled = controlledOpen !== undefined; const open = (isControlled ? !!controlledOpen : internalOpen) && !disabled; diff --git a/frontend/src/core/components/shared/rightRail/ViewerAnnotationControls.tsx b/frontend/src/core/components/shared/rightRail/ViewerAnnotationControls.tsx index 54eec53f9..f4bbb386f 100644 --- a/frontend/src/core/components/shared/rightRail/ViewerAnnotationControls.tsx +++ b/frontend/src/core/components/shared/rightRail/ViewerAnnotationControls.tsx @@ -55,11 +55,6 @@ export default function ViewerAnnotationControls({ currentView, disabled = false const isAnnotateActive = selectedTool === 'annotate'; const annotationsHidden = viewerContext ? !viewerContext.isAnnotationsVisible : false; - // Don't show any annotation controls in sign mode - if (isSignMode) { - return null; - } - // Persist annotations to file if there are unsaved changes const saveAnnotationsIfNeeded = async () => { if (!viewerContext?.exportActions?.saveAsCopy || currentView !== 'viewer' || !historyApiRef?.current?.canUndo()) return; @@ -135,6 +130,11 @@ export default function ViewerAnnotationControls({ currentView, disabled = false } }; + // Don't show any annotation controls in sign mode + // NOTE: This early return is placed AFTER all hooks to satisfy React's rules of hooks + if (isSignMode) { + return null; + } return ( <> diff --git a/frontend/src/core/contexts/FileContext.tsx b/frontend/src/core/contexts/FileContext.tsx index 378d43050..f63ae0f69 100644 --- a/frontend/src/core/contexts/FileContext.tsx +++ b/frontend/src/core/contexts/FileContext.tsx @@ -54,8 +54,10 @@ function FileContextInner({ }: FileContextProviderProps) { const [state, dispatch] = useReducer(fileContextReducer, initialFileContextState); - // IndexedDB context for persistence - const indexedDB = enablePersistence ? useIndexedDB() : null; + // Always call the hook unconditionally to satisfy React's rules of hooks. + // IndexedDB context is only used when enablePersistence is true. + const indexedDBValue = useIndexedDB(); + const indexedDB = enablePersistence ? indexedDBValue : null; // File ref map - stores File objects outside React state const filesRef = useRef>(new Map());