docs/SIDEBAR.md: the dormant card's muted rendering, its resume action, and its lowest-precedence ordering. docs/PREVIEW.md: a session that isn't Running never gets a live attach through the preview path either — its pane reads the same as its card.
110 lines
5.7 KiB
Markdown
110 lines
5.7 KiB
Markdown
# PREVIEW.md — the sidebar preview contract
|
|
|
|
One rule for what the content pane shows while the operator is only moving
|
|
around the sidebar, so the web client and the TUI behave the same. Read this
|
|
before changing either. If the behaviour needs to change, change it here first.
|
|
|
|
## The rule
|
|
|
|
Highlighting a session in the sidebar shows that session in the content pane,
|
|
as if it were focused, **without focusing it and without changing the layout**.
|
|
Moving the highlight elsewhere puts back exactly what was on screen before.
|
|
|
|
A preview is a view, not a state. Nothing about it is durable:
|
|
|
|
- The layout is byte-for-byte identical before the preview and after it ends.
|
|
- Nothing is persisted while a preview is up (the web client's layout is saved
|
|
to `localStorage`; a preview never reaches it).
|
|
- The daemon is never told the previewed pane is focused, so a preview never
|
|
clears a session's `AwaitingInput` glow (`docs/SIDEBAR.md`).
|
|
- The keyboard stays in the sidebar: the previewed terminal is on screen but
|
|
does not take focus, so the next `j`/`k` still walks the list.
|
|
|
|
## Where the preview is shown
|
|
|
|
| The previewed session is… | What happens |
|
|
|---|---|
|
|
| Already in a pane, in the active tab | That pane comes forward (its tab's focus moves to it). |
|
|
| Already in a pane, in another tab | That tab is brought forward. The active tab is restored when the preview ends. |
|
|
| Not in any pane | A throwaway tab carries it. It is removed when the preview ends. |
|
|
|
|
A session that is not `Running` — a dormant one, most often — never gets a
|
|
live attach here or anywhere else a pane is filled: the daemon has nothing to
|
|
answer a `409 not_attachable` and the socket would just die (WS close 1006).
|
|
Its pane shows the same metadata-and-resume view `docs/SIDEBAR.md` describes
|
|
for its card, honest about the fact that there is nothing to preview yet.
|
|
|
|
The throwaway tab never counts as an open session: the tab bar does not appear
|
|
because of it, the mobile shell does not switch away from the session list for
|
|
it, and the sidebar does not mark the session as open.
|
|
|
|
## How a preview reads
|
|
|
|
A preview is provisional, so it never wears the accent — the accent is what
|
|
says "this is the one you picked". It has a hue of its own, and every surface
|
|
involved in the preview carries that same hue, so the pane and the row it came
|
|
from read as one thing rather than two unrelated highlights.
|
|
|
|
Web client (`--preview` and friends in `web/src/styles.css`):
|
|
|
|
| Surface | While previewing |
|
|
|---|---|
|
|
| The previewed pane's titlebar | Tinted in the preview hue, at full strength, in place of the focused pane's accent tint. |
|
|
| The canvas | A `preview` chip, top right, and a dashed inset ring. |
|
|
| A throwaway tab | Dashed border, italic label. |
|
|
| The sidebar row being previewed | Filled with the preview hue, over whatever open state the row already had — but the row of the session already showing in the pane keeps its accent fill, since previewing it changes nothing on screen. |
|
|
| The sidebar row of the session the operator picked | Keeps its accent fill for the whole preview. A preview never moves the accent; only opening another session does. |
|
|
| A hovered sidebar row, and the keyboard cursor on a session | A lighter wash of the same hue, because both are what previews a row. |
|
|
|
|
Rows say it with fill, not with an edge — see the tier ladder in
|
|
`docs/SIDEBAR.md`, which previewing sits at the bottom of. The dashed edges
|
|
belong to the pane: the canvas ring and the throwaway tab.
|
|
|
|
The hue is a palette token, not a fixed colour: a palette whose accent already
|
|
sits on it moves it (`--preview-h`), so "previewing" and "picked" never collide.
|
|
|
|
The TUI marks a preview in text only — the title bar reads `<name> · preview`
|
|
— and has no preview colour role yet.
|
|
|
|
## What ends a preview
|
|
|
|
- The highlight moves to another session — that session is previewed instead.
|
|
- The highlight leaves every session (a folder row, or the list losing the
|
|
keyboard, or the pointer leaving the list): the previous view comes back.
|
|
- Any real layout change (split, close, new tab, tab switch, drag): the preview
|
|
is discarded first, so a throwaway tab is never baked into the arrangement.
|
|
|
|
## What commits a preview
|
|
|
|
Choosing the previewed session — clicking or pressing Enter on its row,
|
|
clicking into its pane, or handing the keyboard to the pane (web: `Tab` from
|
|
the list; TUI: the attach binding) — keeps exactly what is on screen. A
|
|
throwaway tab becomes a real one; a focus move inside an existing tab stands.
|
|
Nothing moves a second time on commit.
|
|
|
|
## Timing
|
|
|
|
**A preview is never delayed.** Landing on a row — by pointer or by `j`/`k` —
|
|
shows it on the next frame, and so does leaving every row. There is no
|
|
settling period in front of the first preview, because that period would sit
|
|
in front of the one preview the operator actually meant.
|
|
|
|
What is bounded is how *often* the pane may swap: at most once per 120 ms.
|
|
A burst inside one window — `j` held down, or the pointer sweeping the length
|
|
of the sidebar — shows the row it started on, then the row it ended on, and
|
|
none of the rows in between. So a walk costs a couple of pane mounts rather
|
|
than one per row, without the operator ever waiting on one.
|
|
|
|
The highlight itself is not bounded by any of this: the row lights up on the
|
|
same frame as the input, whatever the pane behind it is doing.
|
|
|
|
Touch has no hover, and a tap already opens a session, so touch never previews.
|
|
|
|
## Cost
|
|
|
|
A previewed session that no pane holds needs a live attach. Both clients keep
|
|
it connected after the preview ends — the web client parks it in the connection
|
|
pool's LRU, the TUI keeps its emulator until it falls out of the preview
|
|
budget — so stepping back onto a row is instant rather than re-fetching
|
|
scrollback.
|