Skip to content

feat: redesign tool confirmation as fixed bottom bar with fullscreen mode #60

@platypusrex

Description

@platypusrex

Problem

When the model sends 10+ tool calls, the ConfirmingView renders inline inside the scrollbox message list (tool-message.tsx line 634). The confirmation UI gets buried off-screen and users must scroll to find it. This is especially bad for sequential unsafe tools (write_file, run_command) where each stacks a pending->confirming sequence.

The InputBox is already disabled during confirmation (index.tsx line 480), so it occupies space for no reason.

Solution

Replace the inline ConfirmingView with a fixed-position ConfirmationBar that replaces the InputBox during confirmation. Add Ctrl+F fullscreen toggle for reviewing large diffs.

Normal confirmation mode (~20 lines)

+-------------------------------------+-----------+
| <scrollbox> (chat messages)         | SidePanel |
| ...                                 |           |
+------------------------------ ------+           |
| ConfirmationBar (~20 lines)         |           |
|   triangle write_file src/foo.ts    |           |
|   +---------------------------+     |           |
|   | scrollable diff preview   |     |           |
|   | ...                       |     |           |
|   +---------------------------+     |           |
|   [Y]es [N]o [A]lways              |           |
|             Ctrl+F: fullscreen      |           |
+------------------------------ ------+-----------+
  • Replaces InputBox (which is disabled during confirmation anyway)
  • Shows: tool header, scrollable diff/command preview (~20 lines), [Y]es [N]o [A]lways buttons
  • Ctrl+F hint at bottom

Fullscreen mode (Ctrl+F toggle)

+------------------------------------------------+
| ConfirmationBar (full terminal)                |
|   triangle write_file src/foo.ts               |
|   +------------------------------------------+ |
|   | full scrollable diff preview             | |
|   | ...                                      | |
|   | ...                                      | |
|   +------------------------------------------+ |
|   [Y]es [N]o [A]lways                         |
|              Ctrl+F: exit fullscreen           |
+------------------------------------------------+
  • Hides scrollbox AND SidePanel
  • ConfirmationBar fills entire terminal with flexGrow={1}
  • Full scrollable diff preview with maximum width
  • Ctrl+F returns to normal mode
  • Y/N/A/Esc still work in fullscreen

Inline indicator

The ToolMessage confirming case shows a minimal InlineTool:

triangle write_file src/foo.ts (awaiting confirmation...)

No keyboard handler, no preview inline — all interaction moves to the bottom bar.

File Changes

File Change
src/tui/components/confirmation-bar.tsx New — standalone component with scrollable preview, action buttons, keyboard handler (Y/N/A/Ctrl+F)
src/tui/components/tool-message.tsx Remove ConfirmingView component entirely. Confirming case in ToolMessage switch returns InlineTool with suffix="(awaiting confirmation...)". Remove onConfirmationResponse, isActiveConfirmation, isModalOpen from ToolMessageProps.
src/tui/components/index.ts Add ConfirmationBar export
src/tui/index.tsx Add confirmationFullscreen signal. Derive confirmingMessage from displayMessages() + confirmingToolId(). Wrap <scrollbox> in <Show when={!confirmationFullscreen()}>. Wrap <SidePanel> in <Show when={!confirmationFullscreen()}>. In flexShrink={0} container: <Show when={confirmingToolId()} fallback={<InputBox .../>}> renders <ConfirmationBar>. When fullscreen, bar gets flexGrow={1}. Remove isActiveConfirmation, onConfirmationResponse, isModalOpen props from <ToolMessage> usage.

Data Flow

  1. onConfirmationNeeded -> setConfirmingToolId(toolId) + tool state becomes 'confirming'
  2. confirmingToolId() is non-null -> InputBox hides, ConfirmationBar renders
  3. ConfirmationBar finds its ToolDisplayMessage from displayMessages() by matching ID
  4. User presses Ctrl+F -> confirmationFullscreen toggles -> scrollbox + sidebar hide/show
  5. User presses Y/N/A -> handleToolConfirmation() -> clears confirmingToolId -> bar unmounts, InputBox returns
  6. If fullscreen was active, it auto-resets when confirmation clears

Keyboard

Key Action
Y Allow tool execution
N / Esc / Q Deny tool execution
A Always allow this tool type
Ctrl+F Toggle fullscreen preview

Acceptance Criteria

  • Confirmation bar replaces InputBox during confirmation
  • Diff preview is scrollable within the ~20 line compact height
  • Command preview shows $ command with cwd
  • Ctrl+F toggles fullscreen (hides scrollbox + sidebar)
  • Ctrl+F again returns to normal mode
  • Y/N/A work in both normal and fullscreen modes
  • Inline ToolMessage shows "awaiting confirmation..." indicator (no preview, no keyboard)
  • When 10+ tool calls stack, confirmation is always visible at bottom
  • Fullscreen auto-clears when confirmation resolves
  • No regressions: modal suppression still works (command menu / session picker open -> keys suppressed)

Related

Part of the message history consistency work (#56). The current inline confirmation stacking was identified as a UX issue during Phase 7 testing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions