Files
vyndr/web/src/contexts/ExplainModeContext.tsx
T

58 lines
1.8 KiB
TypeScript

'use client';
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
// "Explain Like I'm New" toggle. When on, every annotated UI element renders
// a small tooltip explaining what the number/grade/line actually means. The
// preference is per-browser, stored in localStorage.
interface ExplainModeContextValue {
explainMode: boolean;
toggleExplainMode: () => void;
setExplainMode: (next: boolean) => void;
}
const STORAGE_KEY = 'vyndr_explain_mode';
const ExplainModeContext = createContext<ExplainModeContextValue | null>(null);
export default function ExplainModeProvider({ children }: { children: React.ReactNode }) {
const [explainMode, setExplainModeState] = useState(false);
useEffect(() => {
if (typeof window === 'undefined') return;
const stored = window.localStorage.getItem(STORAGE_KEY);
if (stored === '1') setExplainModeState(true);
}, []);
const setExplainMode = useCallback((next: boolean) => {
setExplainModeState(next);
if (typeof window !== 'undefined') {
window.localStorage.setItem(STORAGE_KEY, next ? '1' : '0');
}
}, []);
const toggleExplainMode = useCallback(() => {
setExplainMode(!explainMode);
}, [explainMode, setExplainMode]);
const value = useMemo(
() => ({ explainMode, toggleExplainMode, setExplainMode }),
[explainMode, toggleExplainMode, setExplainMode]
);
return <ExplainModeContext.Provider value={value}>{children}</ExplainModeContext.Provider>;
}
export function useExplainMode(): ExplainModeContextValue {
const ctx = useContext(ExplainModeContext);
if (!ctx) {
// SSR / outside-provider fallback. Treating off as the safe default.
return {
explainMode: false,
toggleExplainMode: () => {},
setExplainMode: () => {},
};
}
return ctx;
}