aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md2
-rw-r--r--docs/superpowers/specs/2026-08-20-compose-and-send-design.md45
2 files changed, 41 insertions, 6 deletions
diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
index a35d9fa..3d5bcc3 100644
--- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
+++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
@@ -203,7 +203,7 @@ taking that too literally.
| 131 | The markdown dialect and extensions are fixed | v2 | S | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** Configurable in the shape Hugo's config uses. Deliberately fixed initially: CommonMark plus autolink, strikethrough and tasklist |
| 132 | Every action must have a shortcut, and that no longer serves | policy | S | open, 2026-08-20, raised by the user during the item 123 brainstorm. `everyActionHasAShortcut` was written when the action list was short; item 123 adds six more, and each new action consumes a chord whether or not anyone would press it. Replacement is the shape `everyActionIsReachableFromAMenu()` already has: menu reachability required, shortcuts a chosen subset. **Not** done inside 123, which would confuse two changes |
| 133 | The composer shows no markdown syntax highlighting | v2 | S | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** A `QSyntaxHighlighter` over the composer's editor, so `**bold**` reads as bold while the buffer stays plain markdown. Standard Qt, no dependency. Deliberately after 123's formatting toolbar: agreeing with the grammar about nesting and about code spans suppressing what is inside them is the expensive part, and the toolbar is what makes the feature usable |
-| 134 | The busy indicator is built inline and is about to be built twice | maintenance | S | open, 2026-08-20, raised by the user during the item 123 brainstorm. An indeterminate `QProgressBar` beside a status label, built inline in `MainWindow` as `m_syncProgress`, and item 123's composer needs the same pairing. Extract a widget class and convert `MainWindow` to it. **Not blocked on 123**, and better done first: if 123 lands first it creates the class itself and this row closes with it. The user's position is general, build once and reuse, so the inline habit `CLAUDE.md` records is a description of the code rather than a rule to follow |
+| 134 | The busy indicator is built inline and is about to be built twice | maintenance | S | open, 2026-08-20, raised by the user during the item 123 brainstorm. An indeterminate `QProgressBar` beside a status label, built inline in `MainWindow` as `m_syncProgress`, and item 123's composer needs the same pairing. Extract a widget class and convert `MainWindow` to it. It must expose BOTH modes, not just the indeterminate one `MainWindow` happens to need: item 123's send popup drains a determinate bar during its undo countdown and switches the same widget to indeterminate when the command starts. **Not blocked on 123**, and better done first: if 123 lands first it creates the class itself and this row closes with it. The user's position is general, build once and reuse, so the inline habit `CLAUDE.md` records is a description of the code rather than a rule to follow |
Sizes are rough: XS under an hour, S a sitting, M a session.
diff --git a/docs/superpowers/specs/2026-08-20-compose-and-send-design.md b/docs/superpowers/specs/2026-08-20-compose-and-send-design.md
index f410d00..aade2d1 100644
--- a/docs/superpowers/specs/2026-08-20-compose-and-send-design.md
+++ b/docs/superpowers/specs/2026-08-20-compose-and-send-design.md
@@ -262,14 +262,49 @@ declares a struct field named `signals`.
countdown through to completion. It is modelled on Gmail's undo-send, and it is
what settles what "cancel" can mean here.
+Three rows, the same three in every state, so nothing reflows and the window
+never jumps:
+
+```
++-----------------------------------------+
+| Sending in 5... | status label
+| ##################................. | bar, DETERMINATE, draining
+| [ Undo ] | enabled
++-----------------------------------------+
+
++-----------------------------------------+
+| Sending... | then: Filing sent copy...
+| #######################################| bar, INDETERMINATE
+| [ Undo ] | visible, disabled
++-----------------------------------------+
+```
+
+**The bar changes mode, it does not change place.** During the countdown it is
+determinate and drains as the seconds pass, because a countdown has measurable
+progress. It becomes indeterminate (`setRange(0, 0)`) when `send_command`
+starts, because a send does not. This is why item 134's widget class must expose
+both modes rather than hardcoding the indeterminate one.
+
+**Undo stays visible after it disables**, rather than disappearing. A control
+that vanishes re-lays out the popup mid-operation, and a greyed Undo says why
+cancelling is no longer possible where an absent one only looks like it was
+never offered.
+
+The stages, in order:
+
```
-Sending in 5... [ Undo ] countdown running, Undo live
-Sending... [ Undo ] send_command running, Undo disabled
-Filing sent copy... DraftStore writing to the sent folder
-Removing draft... the draft revision is unlinked
- popup and composer both close
+Sending in N... the countdown, Undo live
+Sending... send_command running, Undo disabled
+Filing sent copy... DraftStore writing to the account's sent folder
+Removing draft... the draft revision is unlinked
+ popup and composer both close
```
+**The status label takes its width from the longest string it can hold, in the
+current language, not from its content.** Italian "Rimozione della bozza..." is
+longer than "Removing draft...", so a label sized to content resizes the popup
+between stages, which is the jumping the fixed layout exists to avoid.
+
**The delay is where cancelling is safe, and it is the only place it is.**
Nothing has reached a server during the countdown, so Undo means genuinely
nothing happened. Killing `send_command` once it is running does not: the