diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-17 19:55:36 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-17 19:55:36 +0200 |
| commit | 380195f7cd5e57acf2c1cf2bc41069e6b0b979ed (patch) | |
| tree | 32a88fb22a7fbe8f1fd5c105156d1f928c93950d /docs/TUI-GUIDELINES.md | |
| download | bokf-380195f7cd5e57acf2c1cf2bc41069e6b0b979ed.tar.gz bokf-380195f7cd5e57acf2c1cf2bc41069e6b0b979ed.zip | |
Initial commit: daemon, clients, docs, Docker deploy pipelinev0.1.0
Diffstat (limited to 'docs/TUI-GUIDELINES.md')
| -rw-r--r-- | docs/TUI-GUIDELINES.md | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/docs/TUI-GUIDELINES.md b/docs/TUI-GUIDELINES.md new file mode 100644 index 0000000..180c72b --- /dev/null +++ b/docs/TUI-GUIDELINES.md @@ -0,0 +1,108 @@ +# bokftui guidelines + +Rules for the ncurses client so every view behaves the same. When in doubt, +copy the behaviour of the voucher list / voucher form; they are the reference +implementations. Inspired by Midnight Commander, htop, mutt and calcurse. + +## Session start + +After login the org picker ("Välj organisation att representera") is always +shown; the selected org is fixed for the session (`--org ID` bypasses it for +scripts). The fiscal year is chosen from the dashboard and is changeable +during the session. + +## Universal keys + +| Key | Meaning | +|---|---| +| `Ctrl+N` | Add: new verifikat (dashboard, voucher list/detail), new mall (Mallar), new fiscal year (year picker), open editor (IB), upload file (Underlag) | +| `F5` | Refresh the view | +| `Esc` / `q` | Back one level. At the dashboard it does nothing — Esc never exits the app | +| `Ctrl+C` | Quit the application (closes the session). The only key that exits | +| `1`–`9` | In lists: jump to that row. In menus: activate that item | +| `g` | Live goto: "Gå till rad/nummer:" updates the selection as you type digits (backspace steps back); Enter closes the prompt without opening anything | +| arrows, PgUp/PgDn, Home/End | Move/scroll; selection always stays visible | +| `e` | Edit the shown object (IB, where applicable) | +| `a` | Add/upload (Underlag) | +| `c` | Correct (voucher detail) | +| `Ctrl+F` | Attach a file (voucher form) / pick a file (Underlag) via the file browser | +| `F7` | Clear the current row — only inside row editors (never "new") | +| `F9` | Save/post the current form | + +Every screen prints its keys in the footer via `hints()`. If a key exists, the +footer shows it; if the footer shows it, the key works. + +## Lists (`select_list`, `menu`) + +- Rows are numbered `NN. text`, right-aligned so 2- and 3-digit numbers line up. +- Verifikation ids are shown concatenated as `series+number` (`V-8`, `A8`), + using the org's `default_series` (Inställningar) for new vouchers. +- The last row may be an action (e.g. `+ Nytt verifikat (Ctrl+N)`); selecting it + runs the action instead of opening a detail view. +- Selection memory: lists remember the selected row by identity (voucher id), + not index, across detail round-trips, refreshes and screen re-entry. +- Digits move the highlight; only Enter activates. Menus are the exception: + digits activate directly (they are shortcuts). +- Empty lists are never a dead end: show a message or keep the add-row. + +## Forms + +- Layout: bold header fields at the top, then a bold column header, then rows; + footer hints carry the keys. +- Field navigation: `Tab` / `Shift-Tab` forward/back, arrows Up/Down between + rows. `Enter` advances in simple forms; it never saves unless the screen is + a one-line prompt. +- The active field is drawn reverse-video and holds the hardware cursor at the + caret. The caret is a real position: ←/→/Home/End/Del work inside the field, + `Ctrl+U` clears it (see `field_edit`). +- First keystroke in a freshly focused field replaces its content + (`field_fresh`), so prefilled values like dates can be typed over. +- Date fields (`date_field_edit`, `date_prompt`) accept digits only and insert + the dashes themselves: type `20260315` and the field shows `2026-03-15`. + Backspace deletes a digit (with its separator), ←/→/Home/End move by digit, + and the caret renders like in any other field. Validation (`util_parse_iso_date`) + happens on F5/F9. +- Derived values (account names, balances) are dim and non-editable. +- Row tables: always exactly one empty trailing row; entering data appends a + new empty row; an empty row followed by another empty row collapses. + `F7` clears the selected row. +- Validation: `F5` validates without writing and reports exactly what is wrong + (field, row number). Server `dry_run` is used where available. +- Saving: `F9` writes, shows a confirmation message, and returns to the + previous view. `Esc` cancels without saving. +- File browser (`file_browser`): starts in the org's `attachment_dir` (or + `$HOME`; a leading `~` is expanded to `$HOME`), `.. (uppåt)` is the first row, directories sort first with a + trailing `/`, hidden files are skipped. Enter enters a directory or picks a + file; `Esc` cancels. Selected files are uploaded immediately as unlinked + underlag and linked when the voucher is posted. + +## Messages + +- Info/confirmation: `message(title, ...)` box, dismissed with Enter. +- Quitting: only `Ctrl+C` (from anywhere) or "Logga ut / avsluta" ends the + app; `Esc`/`q` only navigate. After `Ctrl+C` every screen unwinds, the + session is closed and the terminal restored. +- Errors: `show_error(title, resp)` prints `CODE: message` from the server + error object; if the response is missing/empty it says + "Inget svar från servern (kör daemonen?)". Never render an empty error. +- Irreversible actions (close year, lock, archive) ask first. + +## Layout and text + +- Screen frame: title top-left, dim status line under it + (`org | label start - end | role | user`), hints in the last line. +- Columns are padded with `pad_field()` (UTF-8 display width) and truncated to + their column; amounts right-aligned via `kr_format()`; never pad with `%s` + widths directly on user text. +- Selection = reverse video, headers = bold, derived data = dim. +- All user-visible TUI text is Swedish; server messages are English. + +## Adding a view — checklist + +1. Data comes from public protocol commands only. +2. Wrap the screen in `frame()`/`hints()`; return `Esc`/`q` to the parent. +3. Use `menu()` or `select_list()` instead of writing a new loop; pass + `allow_new`/`allow_refresh` so the universal keys apply. +4. Forms use the shared editor (`field_edit`) and the row-normalising helpers. +5. Support `F5` if the data can change elsewhere. +6. Update `PROTOCOL.md` §8 and this file if you add a new key or interaction. |
