feat: optimize compact mode UX — shortcuts, settings sync, and safety#3100
feat: optimize compact mode UX — shortcuts, settings sync, and safety#3100
Conversation
📋 Review SummaryThis PR delivers a comprehensive UX optimization for the compact mode (Ctrl+O) feature, building on top of #3047. The implementation is well-structured and addresses discoverability, settings synchronization, and safety concerns for tool approval prompts. The code quality is generally high with good attention to i18n, documentation, and consistent patterns across the codebase. 🔍 General Feedback
🎯 Specific Feedback🟡 High
🟢 Medium
🔵 Low
✅ Highlights
|
… improvements - Add Ctrl+O to keyboard shortcuts list (?) and /help command - Sync compact mode toggle from Settings dialog with CompactModeContext - Protect tool approval prompts from being hidden in compact mode (MainContent forces live rendering during WaitingForConfirmation) - Remove snapshot freezing on toggle — treat as persistent preference, not temporary peek (differs from Claude Code's session-scoped model) - Add compact mode tip to startup Tips rotation for non-intrusive discovery - Remove compact mode indicator from footer to reduce UI clutter - Add competitive analysis design doc (EN + ZH) comparing with Claude Code - Update user docs (settings.md) and i18n translations (en/zh/ru/pt) Relates to #3047, #2767, #2770 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove frozenSnapshot state, useEffect, and all related logic from AppContainer, MainContent, CompactModeContext, and test files - Simplify MainContent to always render live pendingHistoryItems - Delete compact-mode-design-zh.md (redundant Chinese translation) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
a04f4cf to
a7acd1e
Compare
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
There was a problem hiding this comment.
Pull request overview
This PR improves the CLI “compact mode” UX by increasing shortcut discoverability, syncing Settings changes to live UI state, and removing the “snapshot freeze” behavior so rendering stays live (especially for confirmations and streaming).
Changes:
- Expose
Ctrl+Ocompact-mode toggle in the?shortcuts overlay,/help, and startup Tips. - Sync compact mode toggles in Settings to the in-session UI state via
CompactModeContext. - Remove frozen-snapshot rendering and the compact footer indicator; update docs and add a design/competitive analysis document.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/cli/src/ui/contexts/CompactModeContext.tsx | Simplifies compact mode context; adds setCompactMode for in-session sync. |
| packages/cli/src/ui/components/Tips.tsx | Adds compact-mode tip to startup tips rotation. |
| packages/cli/src/ui/components/SettingsDialog.tsx | Syncs ui.compactMode setting changes to CompactModeContext. |
| packages/cli/src/ui/components/messages/ToolMessage.test.tsx | Updates provider value shape after context change. |
| packages/cli/src/ui/components/MainContent.tsx | Removes frozen-snapshot rendering path; always renders live pending items. |
| packages/cli/src/ui/components/KeyboardShortcuts.tsx | Adds ctrl+o shortcut; adjusts column split counts. |
| packages/cli/src/ui/components/Help.tsx | Adds Ctrl+O to help shortcut list. |
| packages/cli/src/ui/components/Footer.tsx | Removes persistent compact indicator in footer. |
| packages/cli/src/ui/AppContainer.tsx | Removes frozen-snapshot state; provides setCompactMode via context; keeps refreshStatic() on Ctrl+O. |
| packages/cli/src/i18n/locales/en.js | Adds new compact-mode related translation keys. |
| packages/cli/src/i18n/locales/zh.js | Adds new compact-mode related translation keys (ZH). |
| packages/cli/src/i18n/locales/ru.js | Adds new compact-mode related translation keys (RU). |
| packages/cli/src/i18n/locales/pt.js | Adds new compact-mode related translation keys (PT). |
| docs/users/configuration/settings.md | Updates ui.compactMode documentation to reflect Settings toggle + safety guarantees. |
| docs/design/compact-mode/compact-mode-design.md | Adds compact mode competitive analysis / design doc. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Special handling for compact mode to sync with CompactModeContext | ||
| if (key === 'ui.compactMode' && newValue !== compactMode) { | ||
| setCompactMode?.(newValue as boolean); | ||
| } |
There was a problem hiding this comment.
Toggling ui.compactMode here updates React state, but it doesn’t trigger refreshStatic(). Because chat history is rendered inside Ink’s <Static>, the already-rendered history won’t be retroactively re-rendered like it is when toggling via Ctrl+O (which calls refreshStatic() in AppContainer). Consider calling useUIActions().refreshStatic() after setCompactMode so the UI updates immediately and consistently regardless of toggle entry point.
There was a problem hiding this comment.
Fixed in e45c997. Added useUIActions().refreshStatic() call after setCompactMode so Ink's <Static> history re-renders immediately, consistent with the Ctrl+O toggle path in AppContainer.
| // Column distribution for different layouts (4+4+4 for 3 cols, 6+6 for 2 cols) | ||
| const COLUMN_SPLITS: Record<number, number[]> = { | ||
| 3: [4, 4, 4], | ||
| 2: [6, 6], | ||
| 1: [12], | ||
| 3: [5, 4, 4], | ||
| 2: [7, 6], | ||
| 1: [13], | ||
| }; |
There was a problem hiding this comment.
The layout comment is now inaccurate: the column splits were changed to 5+4+4 / 7+6 / 13. Please update the comment so it matches the actual COLUMN_SPLITS values to avoid confusion during future changes.
There was a problem hiding this comment.
Fixed in e45c997. Updated comment to 5+4+4 for 3 cols, 7+6 for 2 cols.
| | Toggle semantics | Temporary peek at details | Persistent preference switch | | ||
| | Persistence | Session-only, resets on restart | Persisted to settings.json | | ||
| | Scope | Global screen switch (prompt ↔ transcript) | Per-component rendering toggle | | ||
| | Frozen snapshot | None (no concept) | Infrastructure exists, currently unused | |
There was a problem hiding this comment.
This document states that Qwen Code has a frozenSnapshot infrastructure (and that it’s “currently unused”), but this PR removes frozenSnapshot entirely from the UI code. Please update the table row to reflect the current implementation so the design doc doesn’t contradict the source.
| | Frozen snapshot | None (no concept) | Infrastructure exists, currently unused | | |
| | Frozen snapshot | None (no concept) | None (removed from UI code) | |
There was a problem hiding this comment.
Fixed in e45c997. Updated table row to None (removed) — frozenSnapshot was fully removed in this PR.
| ``` | ||
| ┌─────────────────────────────────────┐ | ||
| │ CompactModeContext │ | ||
| │ compactMode: boolean (default: false)│ | ||
| │ frozenSnapshot: items[] | null │ | ||
| │ setCompactMode: (v) => void │ | ||
| └──────────┬──────────────────────────┘ | ||
| │ |
There was a problem hiding this comment.
The Qwen Code architecture diagram still includes frozenSnapshot: items[] | null, but CompactModeContext no longer exposes or uses frozenSnapshot after this PR. Please update the diagram accordingly.
There was a problem hiding this comment.
Fixed in e45c997. Removed frozenSnapshot: items[] | null from the architecture diagram.
| | Component | File | Key Logic | | ||
| | --------------- | ------------------------------------- | ------------------------------------------------- | | ||
| | Toggle handler | `AppContainer.tsx:1684-1694` | Toggles `compactMode`, persists, clears snapshot | | ||
| | Context | `CompactModeContext.tsx` | `compactMode`, `frozenSnapshot`, `setCompactMode` | | ||
| | Tool group | `ToolGroupMessage.tsx:105-110` | `showCompact` with 4 force-expand conditions | | ||
| | Tool message | `ToolMessage.tsx:346-350` | Hides `displayRenderer` in compact mode | | ||
| | Compact display | `CompactToolGroupDisplay.tsx:49-108` | Single-line summary with status + hint | | ||
| | Confirmation | `ToolConfirmationMessage.tsx:113-147` | Simplified 3-option compact approval | | ||
| | Tips | `Tips.tsx:14-29` | Startup tip rotation includes compact mode hint | | ||
| | Settings sync | `SettingsDialog.tsx:189-192` | Syncs with CompactModeContext | | ||
| | MainContent | `MainContent.tsx:63-72` | frozenSnapshot with WaitingForConfirmation guard | | ||
| | Thinking | `HistoryItemDisplay.tsx:123-133` | Hides `gemini_thought` in compact mode | |
There was a problem hiding this comment.
The “Key Source Files” section references frozenSnapshot behavior (e.g., “clears snapshot”, and MainContent using a frozenSnapshot guard). Since frozenSnapshot was removed in this PR, these entries are now outdated and should be revised to match the current code paths.
There was a problem hiding this comment.
Fixed in e45c997. Updated all Key Source Files entries — removed snapshot references from Toggle handler, Context, Settings sync, and MainContent descriptions.
| 'to search history': 'to search history', | ||
| 'to paste images': 'to paste images', | ||
| 'for external editor': 'for external editor', | ||
| 'to toggle compact mode': 'to toggle compact mode', | ||
| 'Jump through words in the input': 'Jump through words in the input', |
There was a problem hiding this comment.
New i18n keys were added here for compact-mode discoverability, but other built-in locales (notably de.js and ja.js) do not define them, so those UIs will fall back to the English keys. Please add corresponding entries to all supported built-in locale files to keep translations consistent.
There was a problem hiding this comment.
Fixed in e45c997. Added to toggle compact mode, compact mode: on (Ctrl+O off), and the Tips string to both de.js and ja.js locales.
| // Special handling for compact mode to sync with CompactModeContext | ||
| if (key === 'ui.compactMode' && newValue !== compactMode) { | ||
| setCompactMode?.(newValue as boolean); | ||
| } |
There was a problem hiding this comment.
This PR adds new integration behavior for ui.compactMode (syncing the Settings toggle to CompactModeContext), but there doesn’t appear to be a test asserting that setCompactMode is called when the setting is toggled (similar to the existing VimModeContext integration coverage). Adding a focused test would help prevent regressions in Settings↔UI sync.
There was a problem hiding this comment.
Fixed in e45c997. Added a focused test should sync compact mode with CompactModeContext when toggled that verifies both setCompactMode and refreshStatic are called when ui.compactMode is toggled in the Settings dialog.
- Add refreshStatic() call after setCompactMode in SettingsDialog so already-rendered Static history updates immediately - Fix outdated column split comment in KeyboardShortcuts (5+4+4) - Update design doc: remove all frozenSnapshot references, renumber optimization recommendations, fix file reference descriptions - Add missing i18n keys for de.js and ja.js locales - Add test for SettingsDialog compact mode sync with CompactModeContext Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
hasConfirmingTool only checks ToolCallStatus.Confirming, but subagent approvals arrive via resultDisplay.pendingConfirmation while the tool status remains Executing. Add hasSubagentPendingConfirmation to the showCompact guard so tool groups with pending subagent confirmations are always force-expanded. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Comprehensive UX optimization for compact mode (Ctrl+O), built on top of #3047:
Ctrl+Oto?shortcuts overlay,/helpcommand, and startup Tips rotationMainContentforces live rendering duringWaitingForConfirmationstateFiles changed (15)
AppContainer.tsx,MainContent.tsx,CompactModeContext.tsxFooter.tsx,Help.tsx,KeyboardShortcuts.tsx,Tips.tsx,SettingsDialog.tsxen.js,zh.js,ru.js,pt.jssettings.md,compact-mode-design.md,compact-mode-design-zh.mdRelates to #3047, #2767, #2770
Test plan
?with empty input — verifyctrl+o to toggle compact modeappears in shortcuts list/help— verifyCtrl+Oshortcut is listedCtrl+Oduring streaming — verify live output continues (no frozen snapshot)!shell mode — verify shell remains expanded🤖 Generated with Claude Code