refactor(settings): regroup SettingsPage into 7 progressive-disclosure groups
Phase 9c follow-up. The 2309-line hand-rolled accordion is replaced with
seven SettingsGroup-wrapped top-level groups, each containing the
relevant existing sub-sections as nested SettingsGroups:
1. Audio — microphone (input device).
2. Vocabulary — terms & profiles, profiles & templates (legacy manager
moved in here so all profile / vocabulary state lives together).
3. Transcription — engine, format mode, model management, compute device,
language. Defaults to open to preserve the prior accordion's landing.
4. AI & Processing — post-processing toggles, AI Assistant tier and
model management, if-then implementation rules. AI Assistant and
if-then rules moved out of their original positions to sit alongside
the deterministic post-processing toggles.
5. Tasks & Rituals — rituals (incl. launch-at-login, kept bundled with
the existing Rituals UI block to avoid splitting that block), tasks
page (sparkline), nudges.
6. Output & Capture — read aloud (TTS, lazy-loaded on first open via the
new SettingsGroup `onopen` hook), capture & export.
7. Appearance & System — global hotkey, appearance (theme/zone/font/
locale), accessibility, about (engine status + diagnostics).
Deviations from Codex's 7-group spec:
- Launch-at-login stays inside the Rituals sub-group (was bundled there
in the existing markup; relocating would require splitting the
Rituals UI block, which is out of scope for this pass).
- Profiles & Templates legacy manager pulled into the Vocabulary group
rather than appearance/system.
Implementation notes:
- SettingsGroup gains an optional `onopen` callback prop, fired once on
the first closed→open transition. Used by Read aloud to lazy-load TTS
voices and by AI & Processing to refresh LLM status. Replaces the
former toggleAiSection / toggleReadAloudSection imperative handlers.
- The centralised openSection state is removed; each <details> manages
its own disclosure.
- Tokens are inherited from app.css; the prior global token darkening
(commit 2da0a5b) covers all section labels via the existing utility
classes — no per-component label-class swaps were added.
Search box deferred to a follow-up commit. Forcing `open=true` on
SettingsGroup based on a filter input would require either a controlled
`open` prop or a {#key} re-mount strategy, both of which add risk to
this restructure pass.
Tauri-bridged commands cannot be exercised in browser-only `npm run
dev`; structural verification done via npm build, npm check, and a
live dev server fetch of /settings. Real persistence smoke needs a
tauri dev session.
Verification:
- cargo fmt --check: pre-existing whitespace diffs in src-tauri/src/
live.rs and src-tauri/src/lib.rs only (untouched by this commit).
- cargo clippy --all-targets -- -D warnings: clean.
- cargo test: 283 tests pass.
- npm run check: 1 pre-existing error in vite.config.js:5; 0 new.
- npm run build: clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in: