feat(tui): keyboard-navigable chapter palette#13
Merged
Conversation
User feedback: 'also make it everything not case sensitive'.
Three sites normalized:
1. chaptersForBook(canonical): upper-cases the input before BOOK_CHAPTERS
lookup. chaptersForBook('gen') and chaptersForBook('GEN') both return 50.
2. bookIdFromCanonical(canonical): upper-cases before delegating to
makeBookId. bookIdFromCanonical('jhn') returns 'JHN' as BookId.
3. tui-driver useKeyboard handler: normalizes keyEvent.name to lowercase
once at the top, so all letter keybinds (q, n, p) accept either case
(Q, N, P with Shift) without explicit pair-checks. Special keys (up,
down, tab, escape, [, ], /) are already lowercase emitted by OpenTUI.
makeBookId itself stays strict — it's the domain invariant gate; only
canonical uppercase IDs cross it. The two helpers above wrap it with
case-insensitive input handling.
Tests: 208 → 214 (+6 case-insensitivity assertions). tsc clean.
Bug: pressing Tab on a book suggestion showed the chapter grid for
exactly one render, then immediately disappeared back to book mode.
Root cause: OpenTUI's controlled <input> synthesizes an onInput event
whenever its value prop changes — including programmatic changes.
SuggestionAccepted rewrites state.query to '{DisplayName} ' (e.g.
'John ') to autocomplete the book token. That value change fires
onInput with 'John ', which dispatches QueryTyped. QueryTyped's old
handler unconditionally reset phase to 'book', clearing bookChosen
and chapters.
Fix: QueryTyped now preserves phase: 'chapter' when the new query
still has the chosen book's display name as a case-insensitive prefix
(e.g. 'John ', 'John 3', 'JOHN 3:16' all keep chapter mode). Free-
typing past the book name (e.g. backspacing to 'Joh') correctly drops
back to book mode. This is also the foundation for typing chapter
digits to filter the chapter list in a future iteration.
Tests: +2 (chapter-phase preservation, case-insensitive variant);
existing 'resets to book phase' test still passes because its query
'j' doesn't have the book prefix. 214 → 216. tsc clean.
…apter
- Add ChapterGridMoved {Up,Down,Left,Right} actions for 10-wide stride grid nav
- Decode trailing digit suffix in query to highlight chapter (e.g. "John 10")
- Enter in chapter phase commits highlighted chapter into verse picker;
query containing ':' still routes through parseReference for direct refs
- Auto-highlight top book suggestion (fzf-style) so Tab/Enter accept without arrow-down
- Driver gates arrow keys to grid actions when phase is chapter
ivanmaierg
added a commit
that referenced
this pull request
May 13, 2026
Archive two verified-PASS SDD changes and merge the cli-loading-state delta into openspec/specs/cli/spec.md as the new canonical CLI spec. - cli-loading-state: PASS, 99/99 tests, withLoading helper shipped - palette-chapter-picker: PASS WITH WARNINGS (PR #13); warnings carried forward in the archive report (dead-code actions, spec wording)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
John 3:16) still parse and load the passage immediately — no UX regression.Changes
src/domain/book-chapters.ts— new module with the 66-entry canonical chapter counts.src/tui/reader/reader-reducer.tsbook/chapter), intents (view/pick-verse), and verse-picker state.ChapterGridMoved {Up,Down,Left,Right}(10-wide stride for Up/Down).QueryTypeddecodes trailing digits as chapter highlight (John 10→ highlight 10).SuggestionAccepted(Enter) commits the highlighted chapter into the verse picker; queries containing:still parse as direct refs.src/tui/tui-driver.tsx— driver gate routes arrow keys toChapterGridMoved*when phase ischapter, separate from verse-picker keys.src/tui/reader/— chapter grid + verse-picker overlay views.Testing
reader-reducer.test.tscovers all new transitions: digit-suffix highlight, grid arrow nav, Enter-commits-chapter, fzf auto-highlight, case-insensitive lookups).src/cli/loading.test.ts— unrelated to this branch (present onmain); tracked separately.