From f4ee0cee59cd5792af167a1def4515d8120bf477 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 20 Oct 2026 12:00:16 +0200 Subject: Add UI design: one frame for every tab, next steps as dialogs Co-Authored-By: Claude Opus 5.5 --- .../specs/2026-10-20-sb-builder-ui-design.md | 162 +++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 docs/superpowers/specs/2026-10-20-sb-builder-ui-design.md (limited to 'docs/superpowers/specs') diff --git a/docs/superpowers/specs/2026-10-20-sb-builder-ui-design.md b/docs/superpowers/specs/2026-10-20-sb-builder-ui-design.md new file mode 100644 index 0000000..7c7b254 --- /dev/null +++ b/docs/superpowers/specs/2026-10-20-sb-builder-ui-design.md @@ -0,0 +1,162 @@ +# sb-builder: one UI frame for every tab + +Date: 2026-10-20 +Status: approved +Builds on: phases 1, 2 and 4 (tabs, Jobs, Packages, Results, Hints) + +## Goal + +Every tab looks and works the same, and a multi-step task (check upstream, +update hints, preview, build) never sends the user hunting for the next +button in another place. Rules go into AGENTS.md so later tabs follow them. + +## What is wrong today + +- Action buttons sit at the bottom in Packages and Hints, in a side pane in + Results, at the top in Jobs. +- The ribbon opens tabs; tabs open and close. +- A step's follow-up lives elsewhere: Packages action -> auto switch to Jobs + -> Run it at the top of Jobs. Hints: Check upstream (bottom) -> tick -> + Update selected (bottom) -> diff dialog -> Build these -> Jobs -> Run it + (top). +- The Jobs Start menu name says nothing of what it holds. + +## Window frame + +Top to bottom: main ribbon, small ribbon, tab bar, the tab's view (its +filter bar first), status bar. + +- **Permanent tabs**: Dashboard (default), Packages, Hints, Results, Jobs, + created at startup, not closable. Each loads its data the first time it is + shown (Packages, Hints and Results call `inventory`/`results` then, not at + startup). Navigation: tab bar, Ctrl+PgUp/PgDn, Dashboard tiles (Packages, + Recent jobs, slackrepo results as today). The ribbon does not open tabs. + `File` menu unchanged. +- **Main ribbon**: `QToolBar`, 32 px icons, text under icon, the current + tab's actions in workflow order. Refilled on tab change. +- **Small ribbon**: `QToolBar` right under it, 16 px icons, text beside + icon, the tab's view controls. Hidden when the tab has none. +- Each tab exposes `actions` and `view_actions`, lists of `QAction` it owns, + so enabled and checked state survive tab switches. Icons are freedesktop + theme names with a `QStyle` fallback, as the ribbon does now. +- An action that does not apply is disabled with a tooltip saying why; + never hidden, so the ribbon does not shift. +- Filter bars (search, chips, `N shown · M selected` or `N of M`) stay at + the top of the view; their Refresh buttons move to the small ribbon. + +## Selection + +- Change actions act on the **ticked** rows; view actions (Show build log) + on the **highlighted** row. +- A click anywhere on a row toggles its tick (done for Packages and Hints). +- Ctrl+A ticks the visible rows, Ctrl+Shift+A unticks all (done); the + small ribbon's Select visible and Clear carry the same shortcuts. + +## Ribbons per tab + +| Tab | Main ribbon | Small ribbon | +|---|---|---| +| Dashboard | Refresh | none | +| Packages | Build, Update, Rebuild, Remove, Update all, New hint, Publish | Select visible, Clear, Refresh | +| Hints | Check upstream, Update selected, Delete hint | Select visible, Clear, No download (checkable), Refresh | +| Results | Show build log | Refresh | +| Jobs | Pull overlay (menu: one entry per overlay), Check shadowing, Run it, Kill | none | + +Disabled reasons (tooltips): + +- Build, Update, Rebuild, Remove: "tick packages first". +- New hint: "none of the ticked packages is without a hint". +- Update selected: "tick outdated packages after Check upstream". +- Delete hint: "none of the ticked packages has a hint". +- Show build log: "select a result with a log". +- Run it: "select a finished preview". +- Kill: "no job running". +- Check upstream while running: "checking…". + +Update all, Publish, Pull overlay and Check shadowing are always enabled +(the helper refuses a second job with the busy answer, as today). + +Packages' detail pane keeps **Open in Hints** as a link (navigation, not an +action). Its New hint button moves to the ribbon. + +### New hint on ticked packages + +`hint-new` takes one or more packages and no version: `hint-new ... +[--no-dl]`. Each gets the `.info` pin; Update selected from upstream sets a +version later. The GUI sends no `--no-dl` here (Update selected has the +toggle); the helper keeps the flag. Every package must be without a hint, else the job is +refused before it starts, as today for one. Helper `VERSION` 0.6.0 in both +files, VM redeploy. The New hint dialog goes away. + +## Next-step dialogs + +- Shown only for jobs started from this GUI session: the main window keeps + the ids `job-start` returned. Jobs seen on reconnect or started elsewhere + only notify, as today. +- Non-modal, one per job, never reopened by polling. +- **Preview ended ok** (`slackrepo` with `--preview`): dialog titled + `Preview: `, with the whole job log + (`job-follow` from offset 0; the job has ended, so the stream closes by + itself), a **publish** checkbox (default `builds.publish`), **Run it** + (default button) and **Not now**. Run it goes through the signing-key + check (`start_signed`) and starts the real run. +- **sbpull or sbshadow preview ended ok with a shadow plan** (`shadow:` or + `unshadow:` lines, as `SHADOW_PLAN` today): same dialog, **Apply + shadowing** (`sbshadow --yes`, after a confirm: it changes the repo) and + **Not now**. Without a plan, no dialog. +- **Hint job ended** (`hint-update`, `hint-new`) or a delete: the existing + diff dialog; Build these starts `slackrepo update --preview`, whose end + opens the preview dialog. +- A real run ending, a failed or killed job: notification only. +- **Run it** in the Jobs ribbon, with a finished preview selected, reopens + that preview's dialog (also for a shadowing preview), so Not now loses + nothing. The Jobs top bar (Start, Apply shadowing, Run it, publish, Kill) + goes away. + +The hugo flow becomes: Hints, Check upstream -> Update selected -> diff +dialog, Build these -> preview dialog, Run it. No tab switch. + +## Jobs tab signal + +- Starting a job no longer switches to Jobs; the user stays on the tab. +- While a job runs, the Jobs tab shows a running icon (`system-run`) and + accent-colored text (palette highlight). +- When it ends, the icon becomes the end status (`✔` ok, `✘` failed, + killed, lost) and stays until the Jobs tab is shown, then clears. +- The status bar job button stays. + +## AGENTS.md: UI guidelines + +A new section, binding for every tab: + +1. Tabs are permanent; each loads lazily on first show. +2. Main ribbon: the tab's actions in workflow order. Small ribbon: view + controls. Nothing actionable lives inside a view except navigation links. +3. Change actions act on ticked rows, view actions on the highlighted row. + A row click toggles its tick; Ctrl+A / Ctrl+Shift+A select visible / + clear. +4. An inapplicable action is disabled with a tooltip saying why, never + hidden. +5. When a job this session started ends, its next step opens as a + non-modal dialog where the user is; the Jobs tab shows activity; a + dismissed step can be taken again from the ribbon. +6. A modal confirm only for destructive or outward steps (delete hint, + publish, apply shadowing). + +## Testing + +`test_gui.py` with the fake remote, offscreen: + +- ribbon contents per tab (action texts in order) after switching tabs; +- disabled states and tooltips (nothing ticked, no preview selected, no job + running); +- tabs are not closable and present from the start; data loaded on first + show only (no `inventory` call before Packages or Hints is shown); +- a preview this session started ends -> dialog -> Run it starts the real + run through the signing check; Not now, then Jobs' Run it reopens it; +- a preview not started by this session ends -> no dialog; +- Jobs tab icon running -> end status -> cleared on showing Jobs; +- New hint on two ticked packages -> `hint-new a b`. + +`test_remote.py`: `hint-new` with several packages, refusing a version and +a package that has a hint. -- cgit v1.2.3