Skip to content

fix(ui): hand focus to a column clicked while the sidebar has it - #282

Open
miadisabelle wants to merge 1 commit into
johannesjo:mainfrom
miadisabelle:contrib/pointer-task-activation
Open

miadisabelle wants to merge 1 commit into
johannesjo:mainfrom
miadisabelle:contrib/pointer-task-activation

Conversation

@miadisabelle

Copy link
Copy Markdown
Contributor

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

sidebarFocused is a hard gate — while it's 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, 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

activateTaskFromPointer activates the task and clears sidebarFocused when setActiveTask accepted 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 to getTaskFocusedPanel(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

  • 4 client tests on the real store, focus registry, focusSidebar/navigateRow and the title bar's handleDragReorder, with a copy of TaskPanel's focus effect (mounting TaskPanel itself would pull in most of the app). A control shows setActiveTask leaving 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 the leavingSidebar guard).
  • 5 store tests against the real focus gate; the two covering the fix fail without its clearing line.
  • TaskPanel.reasoning.client.test.tsx mocks the store module explicitly, so it gains the new function beside setActiveTask.

npm run compile, check:static and both suites pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SK5d1Qh4JcJVF39HEkFBxX

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`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant