Skip to content

[Feature] Sheet navigation primitive — partial overlay with back-strip #27

@fissible

Description

@fissible

Summary

A sheet is a new shellframe navigation primitive that overlays the current screen but leaves a 1–2 row "back strip" visible at the top, showing the content beneath. Sheets are dismissible by pressing Esc, pressing Up from the topmost focused element (which shifts focus to the back strip), or (once click support exists) clicking anywhere in the back strip.

First consumer: fissible/shellql#12 — the "Open Database" form triggered by pressing `[o]` on the welcome screen.

Motivation

Modals (`shellframe_modal`) are appropriate for short confirmations and single-line prompts. Sheets are better suited for:

  • Forms with multiple fields (e.g., network connection: host/port/user/db)
  • Any prompt that benefits from visible context of the screen underneath
  • Future deep-navigation flows (e.g. browse → filter → inspect)

The peek strip keeps the user oriented ("where did I come from?") without requiring a full screen transition.

Behaviour

┌──────────────────────────────────────┐
│  [back strip — 1–2 rows of underlay] │  ← shows previous screen content; Up/click → dismiss
├──────────────────────────────────────┤
│                                      │
│         Sheet content area           │  ← full remaining height; no bottom constraint
│         (form, list, etc.)           │
│                                      │
└──────────────────────────────────────┘
  • Back strip height: 1–2 rows
  • Dismissal: Esc anywhere in sheet; Up from topmost widget → focus moves to back strip → Enter/Esc/click dismisses
  • No bottom constraint: sheet content fills from strip to screen bottom — suitable for longer forms
  • Stacking: sheets can stack up to a depth of 2 above main chrome. Deeper sheets start one row lower so each layer's back strip is visible. A third push replaces the second sheet rather than adding a third layer.

API sketch

# Push a sheet over the current screen (analogous to shellframe_shell)
shellframe_sheet "_myapp" "OPEN_DB"

# Pop the topmost sheet (call from sheet's quit or back-strip action)
shellframe_sheet_pop

# Query current sheet depth (0 = no sheets active)
shellframe_sheet_depth

The sheet's render/key/action hooks follow the same naming convention as screens:

_myapp_OPEN_DB_render()          { … }
_myapp_OPEN_DB_<region>_render() { … }
_myapp_OPEN_DB_<region>_on_key() { … }
_myapp_OPEN_DB_quit()            { shellframe_sheet_pop; }

Implementation notes

  • `shellframe_sheet` draws the back strip (saved terminal rows from the previous render) then runs the normal draw cycle for the sheet screen
  • `_SHELLFRAME_SHEET_STACK` array tracks pushed sheet names + saved back-strip content
  • When focus is at the topmost widget and Up is pressed, shift focus to a synthetic `backstrip` region; its action calls `shellframe_sheet_pop`
  • `shellframe_sheet_pop` restores the full previous screen and resumes the parent input loop

Files

  • `src/shell.sh` — sheet stack management, draw integration
  • New: `src/sheet.sh` (or extend shell.sh directly)

Effort

M (~half day) | Deps: existing shell.sh focus model, panel, input widgets

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions