Repository navigation
fix(tui): make composer tabs and footer hints clickable - #57307
AdityaZxxx wants to merge 2 commits into
Conversation
The composer panel's tab row and hint row were plain <text> with no mouse handlers, so the tabs and hints could only be reached from the keyboard even though the list rows and the esc label in the same panel were clickable. The tab switch was also the only composer action that was not a named keymap command, so it was not rebindable or dispatchable. composer.subagent.toggle-activity had the mirror problem: its id was missing from TuiKeybind.Definitions, so it could never be overridden through the config. Register the three ids in Definitions, dispatch them from the mouse handlers, and let the footer hints render the configured bindings.
|
The following comment was made by an LLM, it may be inaccurate: |
There was a problem hiding this comment.
Looks good. I checked it in the TUI from source with real mouse events, on the base and on this branch. On the base, clicking the show inactive hint, the Shell tab label and the tabs hint does nothing. With this PR they toggle the filter, open the Shell tab and move to the next tab. The composer keymap and mouse tests pass (15/15), and packages/tui typechecks.
Public API: adds three config keybind keys, composer.tab.previous (default left), composer.tab.next (right) and composer.subagent.toggle-activity (ctrl+a). This is backwards compatible: the defaults match the old inline bindings, and before this change a config entry for composer.subagent.toggle-activity was silently ignored.
One small gap: the keybinds docs table doesn't list the new keys yet (see inline).
Related: #56153
| "prompt.history.previous": keybind("up", "Previous history item"), | ||
| "prompt.history.next": keybind("down", "Next history item"), | ||
|
|
||
| "composer.tab.previous": keybind("left", "Previous composer tab"), |
There was a problem hiding this comment.
These three ids are now user-configurable keys, but the composer table in services/www/src/docs/content/cli/keybinds.mdx (around line 330) still only lists the composer.subagent.* and composer.shell.* entries. Could you add composer.tab.previous / composer.tab.next / composer.subagent.toggle-activity there so people can find them? #56002 asks for exactly this setting.
The composer table only listed the subagent and shell entries. Add the tab and toggle ids introduced for anomalyco#51903 and anomalyco#56002, plus the terminal entries that landed with persistent session terminals, so the documented set matches TuiKeybind.Definitions.


Issue for this PR
Closes #51903
Closes #56002
Type of change
What does this PR do?
The composer's tab row and hint row were plain
<text>with no mouse handlers, soSubagents/Shell/Terminalsand the footer hints could only be reached from the keyboard. The list rows and theesclabel in the same panel were already clickable, so the panel was inconsistent with itself.The tab switch was also the only composer action that was not a named keymap command. It was registered as an inline
{ bind: "left" }/{ bind: "right" }, so it was not rebindable, not dispatchable and not visible to plugins.composer.subagent.toggle-activityhad the mirror problem: it had anid, but the id was missing fromTuiKeybind.Definitions, soconfig.keybinds.get(id)was always empty and only the inlinebind: "ctrl+a"could ever bind it. BecauseDefinitionsalso drives the config schema, adding that id tocli.jsonwas silently dropped instead of rejected.Three ids now resolve through
Definitions, so the defaults live in one place, the user can override them, and the footer hint renders the configured key:composer/index.tsx Keymap.createLayer(() => ({ - { bind: "left", title: "Previous tab", group: "Composer", run: () => switchTab(-1) }, - { bind: "right", title: "Next tab", group: "Composer", run: () => switchTab(1) }, + { id: "composer.tab.previous", title: "Previous tab", group: "Composer", run: () => switchTab(-1) }, + { id: "composer.tab.next", title: "Next tab", group: "Composer", run: () => switchTab(1) }, }))The chrome becomes clickable, and the mouse path runs the same command the keyboard path runs:
composer/index.tsx <text>{t.label}</text> + onMouseUp={() => ctx.select(t.id)} <text>{hint.label} {hint.shortcut}</text> + onMouseUp={() => keymap.dispatch(hint.command)}ComposerHintcarries the command id andComposerContextgainsselect(id), so each action has one implementation rather than a mouse copy of it.composer.subagent.toggle-activitykeepsctrl+aas its default, andcomposer.tab.previous/composer.tab.nextkeepleft/right. Thetabshint now renders the configured bindings instead of a hardcoded←/→.How did you verify your code works?
From
packages/tui:New file
packages/tui/test/cli/tui/composer-mouse.test.tsxcovers:show active/show inactivehint toggles the subagent activity filtertabshint switches to the next tabkillhint removes the selected shellcomposer.subagent.toggle-activityrebinds to a custom key, the footer hint shows that key, and the key still toggles the filtercomposer.tab.nextrebinds to a custom key, the arrow key stops switching tabs, and thetabshint shows the configured binding"none"-bound toggle still runs from its hint —dispatchCommandresolves active layers rather than bindings, matching the existingprompt/footer.tsxprecedentFull package suite, typecheck and lint:
The composer fixture was extracted from
composer-keymap.test.tsxintocomposer-fixture.tsxso both files share it; that file's existing tests are unchanged.Screenshots / recordings
The composer panel rendered by the test fixture, showing the tab row and the hint row this PR makes clickable:
Checklist
Added by the opencode bot (AI-generated).
Related: #56153
Public API: adds config keybinds composer.tab.previous, composer.tab.next, composer.subagent.toggle-activity (backwards compatible, defaults unchanged)