Release v0.51.288 — Release JD (stage-r24 — collapsible approval card #3515) - #3697
Conversation
Adds a collapse toggle to the approval card header so users can shrink it to a thin header strip and keep the tool-call rationale/transcript above readable. Full ARIA (aria-expanded/controls/label), chevron swap, and transcript reflow that preserves near-bottom scroll. Closes #3007. Co-authored-by: Rod Boev <rod.boev@gmail.com>
…3515) Codex regression-gate finding: showApprovalCard's sameApproval check didn't include approval_id and didn't clear .collapsed in the !sameApproval branch, so a NEW/parallel approval arriving while the card was already collapsed could render collapsed with its command + action buttons hidden. Add approval_id to the signature; clear .collapsed for a distinct approval before syncing. +2 regression tests.
|
| Filename | Overview |
|---|---|
| static/messages.js | Core logic for collapse/expand toggle, ARIA sync, and transcript reflow. Key invariants (expand on new approval, clear on hide, scroll preservation) are correctly handled; minor point: onceBtn.focus() fires unconditionally even when the card is collapsed for a same-approval re-render. |
| static/index.html | Adds collapse button with correct ARIA attributes and id="approvalBtns" on the actions container; clean diff with no regressions to existing markup. |
| static/style.css | Collapse styles follow existing patterns (clarify card); cascade ordering correctly lets .messages.approval-collapsed override .messages.approval-open for padding-bottom. |
| tests/test_3007_approval_card_collapse.py | 14 text-based assertions cover all new functions, CSS classes, HTML attributes, the !sameApproval expanded-reset branch, and call-count invariants for _syncApprovalTranscriptSpace. |
| CHANGELOG.md | Version entry added correctly; format and attribution match existing entries. |
Sequence Diagram
sequenceDiagram
participant Server
participant showApprovalCard
participant hideApprovalCard
participant toggleApprovalCardCollapsed
participant DOM
Server->>showApprovalCard: new approval (distinct sig)
showApprovalCard->>DOM: card.classList.remove("collapsed")
showApprovalCard->>DOM: card.classList.add("visible")
showApprovalCard->>DOM: "_syncApprovalCollapseButton() → aria-expanded=true, chevron-down"
showApprovalCard->>DOM: _syncApprovalTranscriptSpace(card) → approval-open, --approval-card-height
Note over DOM: User reads transcript, clicks chevron
DOM->>toggleApprovalCardCollapsed: onclick
toggleApprovalCardCollapsed->>DOM: card.classList.toggle("collapsed", true)
toggleApprovalCardCollapsed->>DOM: "_syncApprovalCollapseButton() → aria-expanded=false, chevron-up"
toggleApprovalCardCollapsed->>DOM: _syncApprovalTranscriptSpace(card) → approval-collapsed, --approval-dock-height
Note over DOM: User re-expands to act
DOM->>toggleApprovalCardCollapsed: onclick
toggleApprovalCardCollapsed->>DOM: card.classList.toggle("collapsed", false)
toggleApprovalCardCollapsed->>DOM: "_syncApprovalCollapseButton() → aria-expanded=true, chevron-down"
toggleApprovalCardCollapsed->>DOM: _syncApprovalTranscriptSpace(card) → remove approval-collapsed, --approval-card-height
DOM->>hideApprovalCard: respondApproval() or session end
hideApprovalCard->>DOM: card.classList.remove("visible", "collapsed")
hideApprovalCard->>DOM: _syncApprovalTranscriptSpace(null) → remove approval-open/collapsed, remove CSS vars
Reviews (1): Last reviewed commit: "fix(approval): clear collapsed state for..." | Re-trigger Greptile
| const onceBtn = $("approvalBtnOnce"); | ||
| if (onceBtn && document.activeElement !== $('msg')) { | ||
| setTimeout(() => onceBtn.focus({preventScroll: true}), 50); | ||
| } |
There was a problem hiding this comment.
When
showApprovalCard is called for an already-visible, already-collapsed card (sameApproval === true), card.classList.remove("collapsed") is intentionally skipped — so the card stays collapsed. The onceBtn.focus() call that follows will try to focus a button that has display:none via .approval-card.collapsed .approval-btns, which silently fails. The focus hint to the user is lost and the call is wasted. Adding a collapsed guard makes the intent explicit.
| const onceBtn = $("approvalBtnOnce"); | |
| if (onceBtn && document.activeElement !== $('msg')) { | |
| setTimeout(() => onceBtn.focus({preventScroll: true}), 50); | |
| } | |
| const onceBtn = $("approvalBtnOnce"); | |
| if (onceBtn && !card.classList.contains("collapsed") && document.activeElement !== $('msg')) { | |
| setTimeout(() => onceBtn.focus({preventScroll: true}), 50); | |
| } |
…esquena#3515) (nesquena#3697) * feat(approval): make the approval card collapsible (nesquena#3515) Adds a collapse toggle to the approval card header so users can shrink it to a thin header strip and keep the tool-call rationale/transcript above readable. Full ARIA (aria-expanded/controls/label), chevron swap, and transcript reflow that preserves near-bottom scroll. Closes nesquena#3007. Co-authored-by: Rod Boev <rod.boev@gmail.com> * docs(changelog): v0.51.288 — Release JD (stage-r24) * fix(approval): clear collapsed state for a distinct queued approval (nesquena#3515) Codex regression-gate finding: showApprovalCard's sameApproval check didn't include approval_id and didn't clear .collapsed in the !sameApproval branch, so a NEW/parallel approval arriving while the card was already collapsed could render collapsed with its command + action buttons hidden. Add approval_id to the signature; clear .collapsed for a distinct approval before syncing. +2 regression tests. --------- Co-authored-by: Rod Boev <rod.boev@gmail.com> Co-authored-by: nesquena-hermes <[email protected]>
Release stage-r24 (v0.51.288) — collapsible approval card (#3515)
Phase-3 (next tier up), Nathan-approved via screenshots (expanded + collapsed, desktop 1920 +
mobile 390, all live-driven). Closes #3007.
What it does
Adds a chevron collapse toggle to the tool-call approval card header. Collapsed → the card
shrinks to a ~46px "Approval required" strip (desc/command/counter/buttons hidden) so the
transcript + tool-call rationale scrolled above stays readable. Re-expand to act. State resets
to expanded on each new approval (showApprovalCard re-syncs), so a fresh/pending approval is
never silently hidden.
Footprint (low blast radius)
static/index.html (collapse button + ids), static/messages.js (toggle + sync + transcript
reflow), static/style.css (.approval-card.collapsed rules). NO render-pipeline (renderMd/
renderMessages), NO send-path, NO new API routes.
Verified
46px, approvalBtns display:none, messages gains .approval-collapsed reflow class, near-bottom
scroll preserved. Expanded/collapsed verified at 1920 + 390.
What to check
can always re-expand to act, the collapse state can't get stuck/persist across a NEW approval
(so a fresh pending approval is never hidden), and hideApprovalCard clears both visible +
collapsed + transcript-space classes. No keyboard/Enter-to-approve regression while collapsed.
SAFE TO SHIP or MUST-FIX.
padding vars are set/removed correctly on show/hide/collapse; no orphaned --approval-card-height
after hide. Focused code read + one small targeted check only; do NOT write extensive
reproduction harnesses.
Files: static/index.html, static/messages.js, static/style.css, tests/test_3007_approval_card_collapse.py.