Files
agent-evals/frontend/src/hooks/useTheme.ts
Evan Reichard a80de1730c feat: implement WYSIWYG markdown editor
Add complete markdown editor with Go backend and React/TypeScript frontend.

Backend:
- Cobra CLI with configurable host, port, data-dir, static-dir flags
- REST API for CRUD operations on markdown files (GET, POST, PUT, DELETE)
- File storage with flat .md structure
- Comprehensive Logrus logging for all operations
- Static asset serving for frontend

Frontend:
- React 18 + TypeScript + Tailwind CSS
- Live markdown editor with GFM preview (react-markdown)
- File management UI (list, create, open, save, delete)
- Theme system (Light/Dark/System) with localStorage persistence
- Responsive design (320px - 1920px+)

Testing:
- 6 backend tests covering CRUD round-trip, validation, error handling
- 19 frontend tests covering API, theme system, and UI components
- All tests passing with single 'make test' command

Build:
- Frontend compiles to optimized assets in dist/
- Backend can serve frontend via --static-dir flag
2026-02-06 08:53:52 -05:00

52 lines
1.5 KiB
TypeScript

import { useState, useEffect } from 'react';
import type { Theme } from '../types';
const THEME_KEY = 'markdown-editor-theme';
export function useTheme() {
const [theme, setThemeState] = useState<Theme>(() => {
const stored = localStorage.getItem(THEME_KEY);
if (stored && ['light', 'dark', 'system'].includes(stored)) {
return stored as Theme;
}
return 'system';
});
const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>('light');
useEffect(() => {
const root = window.document.documentElement;
const updateTheme = () => {
let resolved: 'light' | 'dark';
if (theme === 'system') {
resolved = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
} else {
resolved = theme;
}
resolvedTheme !== resolved && setResolvedTheme(resolved);
if (resolved === 'dark') {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
};
updateTheme();
if (theme === 'system') {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handler = () => updateTheme();
mediaQuery.addEventListener('change', handler);
return () => mediaQuery.removeEventListener('change', handler);
}
}, [theme]);
const setTheme = (newTheme: Theme) => {
setThemeState(newTheme);
localStorage.setItem(THEME_KEY, newTheme);
};
return { theme, resolvedTheme, setTheme };
}