fix(ui): hand focus to a column clicked while the sidebar has it - #282
Open
miadisabelle wants to merge 1 commit into
Open
miadisabelle wants to merge 1 commit into
miadisabelle wants to merge 1 commit into
Conversation
After moving through the sidebar with Alt+Up/Down, clicking a task or terminal column's title bar or header selected it but left the keyboard with the sidebar: no panel in the column showed focus, typing went nowhere, and Alt+Up/Down kept moving the sidebar highlight. `sidebarFocused` is a hard gate. While it is set, `isPanelFocused` returns false for every panel and `scheduleTaskFocus` declines to move DOM focus. The column's pointer handlers call `setActiveTask`, which clears the new-task panel and placeholder gates but deliberately not this one, because keyboard jumps use it too and keep the sidebar focused. The title bar's drag handler also prevents the mousedown default, so a tap there moves no DOM focus by itself. Clicks inside a terminal, notes or prompt were already fine: their handlers call `setTaskFocusedPanel`, which clears the gate. `activateTaskFromPointer` activates the task and clears `sidebarFocused` when `setActiveTask` accepted the id. For a column that was already active while the sidebar had focus, whose focus effect does not run again because nothing about the selection changed, it also moves DOM focus to `getTaskFocusedPanel(id)` — the same target Enter on a sidebar row uses. The pointer-driven switchers use it: a task or terminal column, a title-bar tap, a sub-task chip, a focus-mode pill. Sidebar clicks, keyboard jumps and handlers inside a column's own content keep `setActiveTask`. The document workspace column activates through its own focus-preserving handler and is left as it is. Tests: - 4 client tests on the real store, focus registry, sidebar navigation and title-bar drag handler, with a copy of TaskPanel's focus effect: a control showing `setActiveTask` leaves DOM focus on the sidebar; focus landing in another column, and back in the already-active one (fails without that branch); and focus left where it was when the sidebar did not have it (fails without the `leavingSidebar` guard). - 5 store tests against the real focus gate; the two covering the fix fail without its clearing line. - TaskPanel's reasoning test mocks the store module explicitly, so it gains the new function beside `setActiveTask`.
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.
After moving through the sidebar with Alt+↑/↓, clicking a task or terminal column's title bar or header selects it but leaves the keyboard with the sidebar: no panel shows focus, typing goes nowhere, and Alt+↑/↓ keeps moving the sidebar highlight.
Why
sidebarFocusedis a hard gate — while it's set,isPanelFocusedreturns false for every panel andscheduleTaskFocusdeclines to move DOM focus. The column's pointer handlers callsetActiveTask, which clears the new-task panel and placeholder gates but deliberately not this one, since keyboard jumps share it and are meant to keep the sidebar focused. The title bar's drag handler also prevents the mousedown default, so a tap there moves no DOM focus on its own.Clicks inside a terminal, notes or prompt were already fine — those handlers call
setTaskFocusedPanel, which clears the gate.Fix
activateTaskFromPointeractivates the task and clearssidebarFocusedwhensetActiveTaskaccepted the id. For a column that was already active while the sidebar had focus, nothing about the selection changes, so its focus effect doesn't re-run — the function moves DOM focus togetTaskFocusedPanel(id)itself, the same target Enter on a sidebar row uses.The pointer-driven switchers use it: a task or terminal column, a title-bar tap, a sub-task chip, a focus-mode pill. Sidebar clicks, keyboard jumps and in-column handlers keep
setActiveTask.Out of scope: the document workspace column activates through its own focus-preserving handler (
preserveInteractionFocus), so I left it alone rather than route it without understanding that logic.Tests
focusSidebar/navigateRowand the title bar'shandleDragReorder, with a copy of TaskPanel's focus effect (mountingTaskPanelitself would pull in most of the app). A control showssetActiveTaskleaving DOM focus on the sidebar; then focus lands in another column, back in the already-active one (fails without that branch), and stays where it was when the sidebar didn't have it (fails without theleavingSidebarguard).TaskPanel.reasoning.client.test.tsxmocks the store module explicitly, so it gains the new function besidesetActiveTask.npm run compile,check:staticand both suites pass.🤖 Generated with Claude Code
https://claude.ai/code/session_01SK5d1Qh4JcJVF39HEkFBxX