Add focus activation, 3-zone drag nesting, and click-to-navigate
Implement remaining Round 3 enhancements: - ArrowDown when panel unfocused activates it at first item (like Outline view) - 3-zone drag-drop: top/bottom thirds insert above/below, middle third nests as child - Click on todo text to focus it in editor (onClick callback) - Dragging parent automatically moves nested children (stopPropagation fix) - Cross-file move inserts todo below heading with blank line (addBlankLine param) - Updated CLAUDE.md with sidebar view architecture documentation Build: 85 tests pass, production build succeeds. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
46
CLAUDE.md
46
CLAUDE.md
@@ -95,3 +95,49 @@ From AGENTS.md and Obsidian best practices:
|
||||
- Keep startup lightweight; defer heavy work until needed
|
||||
- Use stable command IDs (don't rename after release)
|
||||
- Provide sensible defaults for all settings
|
||||
|
||||
## Sidebar View Architecture
|
||||
|
||||
### Key Files
|
||||
- `src/views/todo-sidebar-view.ts` — Main sidebar panel (`TodoSidebarView` extends `ItemView`)
|
||||
- `src/views/todo-item-component.ts` — Pure DOM factory for individual todo `<li>` elements
|
||||
- `src/core/todo-parser.ts` — Parses markdown into `TodoGroup[]` with nested `TodoItem` trees
|
||||
- `src/core/todo-transformer.ts` — Pure functions for modifying file content (toggle, move, indent)
|
||||
- `src/modals/note-select-modal.ts` — First step of cross-file move: pick target note
|
||||
- `src/modals/heading-select-modal.ts` — Second step: pick heading within target note
|
||||
|
||||
### Data Flow
|
||||
1. `parseTodosGroupedByHeading(content)` → `TodoGroup[]` (each group has a heading + tree of todos)
|
||||
2. `buildTodoTree(flatTodos)` — stack-based algorithm: todos whose indent > parent's become children
|
||||
3. `renderGroups()` renders each group; `createTodoItemEl()` renders items recursively
|
||||
4. `flatTodoList: FlatTodoEntry[]` is rebuilt each render for keyboard navigation
|
||||
|
||||
### Event Listener Lifecycle (Critical)
|
||||
- **Register keydown listener ONCE in `onOpen()`**, not in `renderGroups()` — otherwise listeners accumulate on every file change and arrow keys skip items
|
||||
- Use `this.currentFile` inside handlers instead of closure variables (file changes between renders)
|
||||
- `registerEvent()` wrappers handle cleanup automatically on view close
|
||||
|
||||
### Keyboard Navigation
|
||||
- `focusedIndex = -1` means panel is not yet activated (no visual focus)
|
||||
- First ArrowDown/ArrowUp when `focusedIndex === -1` sets it to 0 (activates focus like Outline view)
|
||||
- `flatTodoList` flattens the entire tree depth-first; arrow keys walk this list linearly
|
||||
- Container has `tabindex="0"` so it can receive keyboard events without stealing focus on render
|
||||
|
||||
### Drag and Drop
|
||||
- Parent `<li>` and all nested `<li>` are `draggable="true"`; `stopPropagation` on `dragstart` prevents child drag from bubbling to parent
|
||||
- `handleDragStart` stores `draggedTodo` and `draggedChildLines` (via `collectChildLineNumbers`)
|
||||
- Item drop zones use 3 zones (top/middle/bottom thirds):
|
||||
- Top → insert above
|
||||
- Middle → nest as child (increase indent, insert after target's last descendant)
|
||||
- Bottom → insert below
|
||||
- Group (heading) drop zones allow dropping onto the heading area to move to end of that section
|
||||
- `performNest` adjusts indentation with `indentTodoLines(lines, delta)` before inserting
|
||||
|
||||
### Hotkey Matching (Platform-Aware)
|
||||
- Uses `app.hotkeyManager.getHotkeys(commandId)` and `getDefaultHotkeys(commandId)` (internal API)
|
||||
- `Platform.isMacOS` distinguishes Mod (Cmd on Mac, Ctrl on Windows) from Ctrl
|
||||
- See `matchesHotkey()` in `todo-sidebar-view.ts` for the full matching logic
|
||||
|
||||
### Cross-File Move
|
||||
- Always pass `addBlankLine: true` to `insertTodoUnderHeading` from modals — inserts a blank line between the heading and the moved todo for readability
|
||||
- In-file drag moves use `moveTodoWithChildren` directly (no blank line needed)
|
||||
|
||||
Reference in New Issue
Block a user