ISSUE-E7-03 — Refactor useChordState into Focused Single-Concern Hooks
Objective
Break the monolithic useChordState hook (309 lines, 7 useState calls, 5 useCallback functions, multiple unrelated concerns) into smaller, independently testable hooks.
Background
client/src/features/chromatic-circle/hooks/useChordState.ts currently manages all of the following in a single function:
| Concern |
State/callbacks |
| Pointer drag detection |
dragStart, currentDrag, dragHasMoved |
| Named chord selection |
selectedChord, selectChord |
| Custom chord construction |
customNotes, toggleCustomNote, clearCustomNotes, isCustomMode |
| Primitive chord shape |
derived from selectedChord.type |
| Screen-reader announcements |
announcement string, setter |
The combined size makes the hook impossible to unit-test (too many internal dependencies) and difficult to reason about (unrelated state changes may trigger re-renders together).
Proposed Split
useDragState (new)
// Owns: dragStart, currentDrag, dragHasMoved
// Exported from: chromatic-circle/hooks/useDragState.ts
useChordSelection (new)
// Owns: selectedChord, selectChord callback
// Exported from: chromatic-circle/hooks/useChordSelection.ts
useCustomChordState (new)
// Owns: customNotes, toggleCustomNote, clearCustomNotes, isCustomMode
// Exported from: chromatic-circle/hooks/useCustomChordState.ts
useChordState (thin orchestrator — keep same public interface)
// Composes the three new hooks + announcement state
// Public surface unchanged — callers require no edits
// Target: ≤150 lines
Files To Add
client/src/features/chromatic-circle/hooks/useDragState.ts
client/src/features/chromatic-circle/hooks/useChordSelection.ts
client/src/features/chromatic-circle/hooks/useCustomChordState.ts
Files To Edit
client/src/features/chromatic-circle/hooks/useChordState.ts — gutted to orchestrator; delegates to new hooks.
client/src/features/chromatic-circle/hooks/index.ts — export new hooks if not already done.
Files Not To Edit
- Any component that calls
useChordState — the public interface must remain identical.
Acceptance Criteria
Verification Commands
cd client
npm run lint
npm run build
npm test
ISSUE-E7-03 — Refactor
useChordStateinto Focused Single-Concern HooksObjective
Break the monolithic
useChordStatehook (309 lines, 7useStatecalls, 5useCallbackfunctions, multiple unrelated concerns) into smaller, independently testable hooks.Background
client/src/features/chromatic-circle/hooks/useChordState.tscurrently manages all of the following in a single function:dragStart,currentDrag,dragHasMovedselectedChord,selectChordcustomNotes,toggleCustomNote,clearCustomNotes,isCustomModeselectedChord.typeannouncementstring, setterThe combined size makes the hook impossible to unit-test (too many internal dependencies) and difficult to reason about (unrelated state changes may trigger re-renders together).
Proposed Split
useDragState(new)useChordSelection(new)useCustomChordState(new)useChordState(thin orchestrator — keep same public interface)Files To Add
client/src/features/chromatic-circle/hooks/useDragState.tsclient/src/features/chromatic-circle/hooks/useChordSelection.tsclient/src/features/chromatic-circle/hooks/useCustomChordState.tsFiles To Edit
client/src/features/chromatic-circle/hooks/useChordState.ts— gutted to orchestrator; delegates to new hooks.client/src/features/chromatic-circle/hooks/index.ts— export new hooks if not already done.Files Not To Edit
useChordState— the public interface must remain identical.Acceptance Criteria
useChordState.tsis ≤150 lines and only composes the three hooks.useChordStaterequires any change.npm run lintpasses with--max-warnings=0.npm run buildsucceeds with no TypeScript errors.Verification Commands