# Keyboard and dialog layout

Every key the questionnaire dialog reacts to, the rows it appends for you, and how it
adapts to the size of your terminal.

## Keys

| Key | What it does | Where it applies |
| --- | --- | --- |
| `↑` / `↓` | Move between rows. Wraps at both ends. | Option list, Submit picker |
| `PgUp` / `PgDn` | Scroll the transcript above the dialog by a full page. Follows `tui.altScreen.pageUp` / `tui.altScreen.pageDown`. | Everywhere in the dialog, on fullscreen hosts |
| `Enter` | Confirm the focused option, commit typed text, close notes, or activate the focused Submit-picker row. | Everywhere |
| `Shift+Enter` | Insert a newline. | `Type something.` input, notes editor |
| `Esc` | Cancel the whole questionnaire. | Everywhere except the notes editor, where it closes notes |
| `Tab` / `Shift+Tab` | Next / previous tab, wrapping. `→` / `←` do the same. | Multi-question dialogs only |
| `Space` | Toggle the focused checkbox. | Multi-select questions |
| `n` | Open the notes editor for the focused question — or, on the Submit tab, the global note for the whole questionnaire. | Every question tab; the Submit tab in multi-question dialogs |
| `Ctrl+G` | Open Pi's configured external editor with the current custom-answer draft. | `Type something.` input |
| `Ctrl+U` | Clear the current custom-answer draft. | `Type something.` input |
| `Ctrl+]` | Collapse or expand the dialog. Configurable via `collapseKey`. | Everywhere, including while collapsed |

The table names the default keys; the dialog actually follows your Pi keybindings.
Confirm listens to both `tui.select.confirm` and `tui.input.submit`, and a key bound to
`tui.input.newLine` always inserts a newline even if it also matches confirm. So a
Slack-style configuration — `enter` folded into `tui.input.newLine`, submit moved to
`ctrl+enter` — keeps working: `enter` breaks lines, and your submit key confirms
everywhere `Enter` does.

In a multi-select question, `Enter` on a regular row toggles its checkbox exactly like
`Space` — it does not submit. Committing the question means focusing the `Next` row and
pressing `Enter`. That is deliberate: it makes `Enter` a zero-cost way to flip boxes
without leaving the home row.

`Space` is suppressed on two rows: `Next` (it is a command, not a choice) and
`Type something.` (it is an inline text input, so the space character belongs to your
answer).

## Scrolling the transcript above the dialog

The dialog is docked in place of the chat editor, so the transcript keeps the rows above
it and its last lines are never hidden underneath the dialog. `PgUp` / `PgDn`
scroll the transcript by a full page, and the mouse wheel scrolls it a few lines per
notch; the alt-screen bindings (`tui.altScreen.lineUp` / `lineDown` / `halfPageUp` /
`halfPageDown` / `top` / `bottom`) work too. Pi handles these keys itself, exactly as it
does for the chat editor; arrows still move between the dialog's rows and `Enter` /
typing keep answering it. This holds
inside the `Type something.` and notes editors as well: there `PgUp` / `PgDn` scroll the
transcript rather than paging through your draft, while the arrows keep moving the cursor.

A page matches Pi's own: the transcript viewport height minus a four-line overlap, so
consecutive pages never skip a line.

This works on Pi's fullscreen (alt-screen) host, where the transcript owns a scrollable
viewport. On the legacy main-screen host, `PgUp` / `PgDn` fall back to the dialog's own
option-list paging, and the terminal owns scrolling.

If you want the whole dialog out of the way instead, use [collapse mode](#collapse-mode).

## The rows the dialog adds

| Row | Label | Appended to |
| --- | --- | --- |
| Custom answer | `Type something.` | Every question — single-select and multi-select, with or without previews |
| Commit | `Next` | Multi-select questions only |

Focusing `Type something.` switches the row into an inline multiline editor. In preview
mode it expands to the full pane width while you type, so a long custom answer is not
squeezed into the narrow options column. `Shift+Enter` inserts a line break; vertical
arrows move between lines and return to row navigation at the draft's top and bottom.
The draft replaces the static row label while you browse other options and is isolated
per question. `Ctrl+G` round-trips it through Pi's configured external editor; `Ctrl+U`
clears it, while `Esc` remains the explicit way to cancel the questionnaire. Confirming
it produces an answer of `kind: "custom"`.

Both labels are reserved — the model cannot author an option that collides with them.
Both localize with the rest of the UI chrome; the reserved-label check always compares
against the canonical English strings.

## Notes

`n` opens a notes editor on any question tab, whether the question is single- or
multi-select and whether or not its options carry previews. Notes are stored in a
side-band keyed by tab index, not inside the answer, so writing a note does not mark a
question as answered — the Submit tab still lists it as outstanding. The note merges into
the answer when you confirm it, and reaches the model as `user notes: <text>`.

On the Submit tab, `n` opens the global note editor instead — one note covering the whole
questionnaire. It lives outside every answer, so it survives tab switches and never marks
a question as answered; it reaches the model as `global note: <text>`, and submitting with
nothing but a global note still returns an answered result rather than a decline.

Inside the editor, `Shift+Enter` inserts a newline, while `Esc` and `Enter` close it; other
keystrokes edit the buffer, so `n` types an `n`. Pasted line breaks are preserved.

## Collapse mode

`Ctrl+]` gets the dialog out of the way: it shrinks to a single dim hint row that names
the key to press, and the transcript above it takes back the freed rows. Press the same
key to bring the questionnaire back with your answers intact. The dialog keeps keyboard
focus while collapsed, and a held key does not toggle it repeatedly.

While collapsed, every keystroke other than cancel is ignored, so you cannot mutate
answers you cannot see.

The default `ctrl+]` is free in Terminal.app, iTerm2, Warp, tmux, zellij and screen. On
keyboard layouts where `]` sits on the shifted layer — Latin American `es-AR` / `es-MX`,
among others — set a different `collapseKey`, or `"off"` to disable the shortcut.

## Layout

Options render in a vertical list. When any option in a single-select question carries a
`preview`, the dialog splits into a side-by-side layout with the option list on the left
and a bordered monospace preview box on the right — but only when both the terminal and
the dialog pane are at least 100 columns wide. Below that, the preview stacks underneath
the options instead.

### Many options: the scrolling option list

An option list is budgeted in terminal **rows**, not items: an option whose label and
description wrap to four rows costs four. When the whole list (options plus the
`Type something.` and `Next` rows) fits in 20 rows it renders exactly as before. Otherwise
it becomes a window of exactly 20 rows centred on the focused option:

```
  ↑ 3 more
   4. Option 4
      a long description that wraps
      onto a second row
❯  5. Option 5
      short description
   …
  ↓ 6 more · 5/13
```

- Only whole options are shown; leftover rows are padded so the height never changes
  while you scroll — however unevenly descriptions wrap.
- The top row counts options hidden above (blank at the top of the list); the bottom row
  counts options hidden below and shows the focused row's position.
- The same window applies to multi-select lists (checkbox state is kept for rows scrolled
  out of view) and to the left column of the side-by-side preview layout.
- A focused row taller than the window — a long multi-line custom answer — is always
  shown whole; the dialog's own overflow scrolling takes over from there.

### Many questions: the windowed tab strip

When the tab strip (one tab per question plus Submit) is wider than the terminal, it
switches to a windowed view instead of clipping at the right edge:

```
 ← [7/13] ‹5  ■ Approach  [ □ Storage ]  □ Caching   □ Logging  3›  ✓ Submit  →
```

- The focused tab is always visible; the window grows around it to fill the width.
  On the Submit tab the window anchors on the last question.
- `Submit` stays pinned on the right.
- `[7/13]` is the focused tab's position among all tabs (questions + Submit).
- `‹5` / `3›` count the question tabs hidden on each side. A marker is colored as a
  warning while any tab it hides is unanswered, and as success once they all are.

When everything fits, the strip renders exactly as before — no counter, no markers.

When the dialog is taller than its row budget — the terminal height minus the rows left
for the status line, the footer and a few transcript lines (eight on a 32+-row terminal,
fewer on smaller ones) — the body scrolls between a sticky heading and
a sticky footer, and an overflow indicator shows which direction is clipped: `↑` for
content above, `↓` for content below, `↕` for both.

The footer hint line adapts to context — it drops the notes hint and appends the
`Shift+Enter` newline hint whenever a text editor has the keyboard, with `Ctrl+U` still at
the far right for custom answers. It adds the tab hint only in multi-question dialogs. The
Submit tab follows the same idiom: its bottom hint row sits below the picker and carries
an `n to add a note` part that gives way to the `Shift+Enter` newline hint while the
global-note editor is open; a committed note shows as a `Note` entry in the review list.
`Ctrl+G` remains Pi's global external-editor shortcut and is not repeated there. On narrow
terminals the right edge clips with `…` so the core hints survive.
