UI refresh: composer-centric controls, Hermes control center, and dialog polish - #242
UI refresh: composer-centric controls, Hermes control center, and dialog polish#242aronprins wants to merge 23 commits into
Conversation
|
Thanks for this PR, @aronprins — this is a substantial UI overhaul and the description is detailed enough to review clearly. What stands outComposer as control hub — moving model/profile/workspace selectors into the composer footer is a coherent design choice. It reduces the number of places users need to look for controls and aligns with how other modern chat interfaces handle context. The circular context ring replacing the linear pill is a good space trade-off. Hermes Control Center — consolidating the old settings modal into a tabbed 860px surface with fixed-height panes solves the "pane resizes on tab switch" issue that's been a friction point. Resetting to the Conversation tab on close is the right default. Shared dialogs replacing Session list: Things to verify before merging1. Composer footer overflow — with model selector, profile chip, workspace chip, context ring, cancel button, and send button all in the footer, this may get cramped on narrower viewports (e.g., 320–480px wide). Does the footer have a defined minimum width and a graceful collapse strategy? 2. Topbar-less navigation — removing the model/profile chips from the topbar is fine on desktop, but on mobile where the composer may be offscreen during scrolling, users lose access to those controls mid-conversation. Is there a fallback for narrow viewports? 3. 4. Test coverage — the PR adds 5. Theme coverage — the PR mentions a visual sweep across 7 themes. Were these manual checks, or is there automated theme validation? The scope is large but the description is well-organized and the design decisions are well-reasoned. The main pre-merge question is how the composer footer degrades at narrow viewports. Everything else looks like it's been thought through. |
Adds showConfirmDialog() and showPromptDialog() helpers to ui.js, backed by a themed #appDialogOverlay element in index.html. Replaces all 11 native browser confirm()/prompt() call sites across panels.js, sessions.js, ui.js, and workspace.js. The new dialogs support: - Themed styling matching the app's dark/light themes - Keyboard navigation (Esc=cancel, Enter=confirm, Tab=focus trap) - Danger mode (red confirm button) for destructive actions - focusCancel option for destructive prompts - Mobile-responsive layout (full-width stacked buttons at 640px) - ARIA roles and accessible labelling - i18n keys for all labels (en, de, zh, zh-Hant) New test: tests/test_sprint33.py (5 tests) verifying the markup, CSS selectors, helper functions, and that no native confirm/prompt calls remain in any static JS file. Extracted from PR #242 (feat/ui-improvements-round1) by @aronprins. Full PR #242 is under review; this self-contained piece is safe to merge independently.
…rom #242) Replaces the five per-row hover action buttons (pin, move, archive, duplicate, trash) with a single ⋯ trigger button that opens a positioned dropdown menu. Changes: - static/sessions.js: adds _openSessionActionMenu(), closeSessionActionMenu(), _positionSessionActionMenu(), _buildSessionAction() with full keyboard (Escape), click-outside, scroll, and resize handling. Menu uses position:fixed to avoid sidebar clipping. - static/style.css: replaces .session-actions overlay CSS with new .session-actions-trigger and .session-action-menu rules. - tests/test_sprint16.py: updates test_sessions_js_active_skips_project_border → test_sessions_js_uses_action_menu_not_per_row_buttons, asserting the new ⋯ trigger and menu functions exist and old per-row buttons are gone. The dropdown menu includes: - Pin / Unpin conversation - Move to project - Archive / Unarchive conversation - Duplicate conversation - Delete conversation (danger style) Each action item has a label and a descriptive subtitle. The menu closes on Escape, outside click, scroll, and resize-repositions to stay in viewport. Browser tested: menu opens, correct 5 items with icons and subtitles, no JS errors, Escape closes cleanly. Extracted from PR #242 (feat/ui-improvements-round1) by @aronprins.
|
Thanks for this PR, @aronprins — we did a thorough end-to-end review of the full diff and want to share where things stand and what the path to merge looks like. What we didWe read the entire PR, audited all JS and CSS changes, verified every Two self-contained pieces already extracted and submitted as standalone PRsRather than hold all of #242 on the same timeline, we extracted the two pieces that are fully self-contained and low-risk:
Both have passed full QA (629 and 624 tests respectively, zero JS errors in browser). They're ready for review. What remains in #242 (the larger chunk)The rest of the PR — composer footer restructure, Hermes Control Center modal, activity bar removal, workspace panel state machine — is more involved and carries more mobile risk. Specifically: Issues to fix before this part can merge:
Mobile considerations: The composer footer restructure moves model/profile/workspace controls out of the topbar and into the composer footer. Desktop looks great. On mobile, when users scroll a long conversation, those controls scroll out of view with the composer — which is a UX trade-off worth documenting. The We've also added PR #254 — a 14-test mobile layout regression suite that will now run on every QA pass, so future PRs (including this one) have automated coverage for mobile CSS regressions. Suggested next steps for the larger chunk
Once those are addressed, the remaining chunk is in good shape and we'll run the full QA gate (desktop + mobile browser sanity, full pytest, QA harness) before merge. Thanks again for the detailed PR — this is solid work and we want to get it across the line. |
Adds showConfirmDialog() and showPromptDialog() helpers to ui.js, backed by a themed #appDialogOverlay. Replaces all 11 native browser confirm/prompt call sites across panels.js, sessions.js, ui.js, workspace.js. Supports: danger mode, keyboard focus trap (Tab/Escape/Enter), focus restore, ARIA roles, mobile-responsive stacked buttons at 640px. i18n for en/de/zh/zh-Hant. 5 new tests in test_sprint33.py verify markup, CSS, helpers, and absence of native dialog calls. Extracted from PR #242.
Replaces the 5 per-row hover action buttons (pin/move/archive/duplicate/trash) with a single ⋯ trigger that opens a positioned dropdown menu. Menu has full keyboard (Escape), click-outside, scroll, and resize-reposition handling. Position:fixed prevents sidebar clipping. 5 actions: Pin/Unpin, Move to project, Archive/Unarchive, Duplicate, Delete (danger style). Each with icon and descriptive subtitle. Updated test_sprint16.py: test_sessions_js_uses_action_menu_not_per_row_buttons asserts the new trigger and menu functions exist, old per-row classes are gone. Extracted from PR #242.
* fix: custom provider with slash model name no longer rerouted to OpenRouter (#255) When base_url is configured in config.yaml, resolve_model_provider() now trusts the configured provider/base_url entirely and skips the slash-based OpenRouter heuristic. Fixes google/gemma-4-26b-a4b with provider:custom being silently routed to OpenRouter, resulting in 401 errors. Fixes #230 * test: mobile layout regression suite — 14 tests for every QA run (#254) Adds tests/test_mobile_layout.py with 14 static regression tests that run on every QA pass to catch mobile layout breakage before it reaches prod. Covers: breakpoints at 900px/640px, right panel slide-over CSS, mobile overlay, bottom nav, files button, profile dropdown z-index, chip overflow, workspace close, 100dvh, 44px touch targets, 16px font-size on textarea. * feat: /skills slash command lists and filters available Hermes skills (#257) Adds /skills [query] command to commands.js. Fetches from /api/skills, groups by category (alphabetically sorted), displays as a formatted assistant message. Optional query filters by name, description, or category. i18n keys added for en, de, zh, zh-Hant. 1 regression test added. Fixes #248 * feat: shared app dialogs replace native confirm()/prompt() calls (#251) Adds showConfirmDialog() and showPromptDialog() helpers to ui.js, backed by a themed #appDialogOverlay. Replaces all 11 native browser confirm/prompt call sites across panels.js, sessions.js, ui.js, workspace.js. Supports: danger mode, keyboard focus trap (Tab/Escape/Enter), focus restore, ARIA roles, mobile-responsive stacked buttons at 640px. i18n for en/de/zh/zh-Hant. 5 new tests in test_sprint33.py verify markup, CSS, helpers, and absence of native dialog calls. Extracted from PR #242. * fix: Android Chrome mobile — workspace panel close + profile dropdown (#256) Fix #247: toggleMobileFiles() now shows/hides the mobile overlay when toggling the right workspace panel. New closeMobileFiles() helper closes the panel with correct overlay state tracking. Overlay onclick calls both closeMobileSidebar() and closeMobileFiles(). Mobile-only close button (x) added to workspace panel header. Fix #246: profile dropdown uses position:fixed;top:56px;right:8px at max-width:900px, escaping the overflow-x:auto stacking context that was clipping it on Android Chrome. Fix applied during review: closeMobileSidebar() now checks if the right panel is still open before hiding the overlay, preventing the overlay from disappearing when only the sidebar is closed. Fixes #247 Fixes #246 * feat: session ⋯ action dropdown replaces per-row buttons (#252) Replaces the 5 per-row hover action buttons (pin/move/archive/duplicate/trash) with a single ⋯ trigger that opens a positioned dropdown menu. Menu has full keyboard (Escape), click-outside, scroll, and resize-reposition handling. Position:fixed prevents sidebar clipping. 5 actions: Pin/Unpin, Move to project, Archive/Unarchive, Duplicate, Delete (danger style). Each with icon and descriptive subtitle. Updated test_sprint16.py: test_sessions_js_uses_action_menu_not_per_row_buttons asserts the new trigger and menu functions exist, old per-row classes are gone. Extracted from PR #242. * docs: v0.47.0 release notes, bump version, update test counts (645) --------- Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
|
Hi @aronprins — big update since the last review. Here's a complete status of where things stand and exactly what your branch needs to get the remaining work merged. What's already been merged (you can remove these from your branch)Since our last comment, we extracted and merged three self-contained pieces from your PR into master. Your branch still carries all of them — rebasing will eliminate the overlap, but here's what's now in master so you can also surgically remove them if you prefer a clean rebase: Merged in v0.47.0Shared app dialogs (your Session Mobile QA regression suite The one failing test — easy fixYour branch currently fails 1 test: This test was already updated in master as part of the session menu merge. After rebasing onto master, the test will be gone and replaced with Quick check: after rebasing, run: python -m pytest tests/test_sprint16.py -v --tb=shortAll tests in that file should pass. What's left to merge — the real workAfter rebasing, your PR's remaining delta is the core UI redesign. This is the piece worth focusing on. Here's exactly what it contains and what it needs: What remains (genuine new work not in master)
Step-by-step path to mergeStep 1 — Rebase onto current mastergit fetch origin
git rebase origin/masterThis will pick up all the merged pieces (dialogs, session menu, mobile tests, the mobile overlay fix, the profile dropdown fix). There should be zero conflicts — we verified with After rebasing, run: python -m pytest tests/ -q --tb=short 2>&1 | tail -5
# Should show: 645 passed (or more with your test_sprint34.py additions)Step 2 — Fix the three remaining issuesThese were flagged in the original review comment and are still needed: 2a. Profile dropdown .profile-dropdown {
/* existing rules... */
max-width: min(260px, calc(100vw - 32px));
}Without this, on very narrow viewports the 260px dropdown can clip off the right edge of the screen. 2b. 2c. Step 3 — Mobile QA pass (the most important new requirement)We've added a mobile regression test suite ( 375px viewport (iPhone SE / smallest common phone):
414px viewport (iPhone 12/13):
Suggested approach: Open the browser at http://localhost:8787, use DevTools or browser responsive mode to set 375px width, test all three dropdowns (model, profile, workspace) in the composer footer. If any of these fail, add CSS at Step 4 — Run the full gate# Full test suite (must be 645+ passed, 0 failed)
fuser -k 8788/tcp 2>/dev/null; sleep 1
python -m pytest tests/ -q --tb=short
# QA harness (if you have the private qa/ tests)
# If not, skip — we run this gate before merging
# Browser sanity — desktop:
# - Load app, new session, 3 messages, all sidebar panels
# - Open the Control Center (sidebar launcher button)
# - Switch tabs: Conversation / Preferences / System
# - Close and reopen — verify it resets to Conversation tab
# - Check the gear icon is gone from topbar
# - Verify model/profile/workspace chips are in composer footer
# - Click each — verify dropdowns open and work
# Zero JS console errors throughoutSuggested approach: merge whole vs. splitGiven that the remaining work is a cohesive set of interconnected changes (you can't easily ship the Control Center without also shipping the "launcher" button that replaced the gear, and you can't remove the activity bar without The only real complexity is the mobile composer footer QA — everything else is clean, tested, and architecturally sound based on our earlier audit. If you'd rather split further, the cleanest seam would be:
But splitting at this point would create significant merge complexity since the Control Center and composer chips share CSS tokens and the boot.js state machine. Merging whole after the mobile QA pass is cleaner. Summary of what to do
The code quality in this PR is genuinely solid. We're looking forward to getting the full Control Center experience merged. |
415787b to
4333303
Compare
Move the model selector into the composer footer, replace the linear context pill with a compact circular badge plus tooltip, and remove the redundant topbar model pill. Design credit and inspiration: Theo / T3 Code. Reference implementation: https://github.com/pingdotgg/t3code/
Drop the old activity bar, keep turn-scoped state in the composer footer, and route remaining non-chat status messages through toasts. This leaves live tool cards and the message timeline as the primary progress UI, with the composer owning stop/cancel and brief turn status.
Widen the modal to 860px, simplify the tab list to icon+label rows, stretch the tab column's divider to full height, lock the panel to a fixed height so switching tabs no longer resizes the outer shell, and always open on the Conversation tab. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the left-border accent used for active, CLI, and project rows — each state already has a dedicated cue (gold fill, cli badge, project dot), so the border was redundant. Fully round the row, add 2px bottom spacing between rows, and strip the matching JS/CSS overrides. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Snap padding, gap, and border-radius values to the 2/4/6/8/10/12 grid across composer chips, sidebar panels, cron list, settings, approval buttons, dropdowns, and inline message edit — eliminating the 7/9/11px drift that was making sibling elements feel subtly misaligned. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ile QA suite) The mobile layout regression suite (test_mobile_layout.py) requires: - #btnMobileFiles onclick=toggleMobileFiles() in topbar chips - .mobile-files-btn CSS rules for responsive show/hide at 640/900px breakpoints Also adds max-width guard to .profile-dropdown to prevent clipping at narrow viewports.
|
Still working on this - closed accidentally <3 |
- Collapse composer chips to icon-only at <=400px viewports - Add model chip icon (CPU) so it remains tappable when labels are hidden - Show send button always (disabled state when empty, hidden during streaming) - Show context usage indicator on session load, not just after streaming - Add cancel status fallback timeout to prevent stale "Cancelling..." text - Update tests to match new send button and busy state behavior
Remove redundant #btnMobileFiles button that duplicated #btnWorkspacePanelToggle in the mobile topbar. Fix workspace panel close button calling undefined closeMobileFiles() — now calls closeWorkspacePanel(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove mobile-files-btn class from #btnWorkspacePanelToggle — its display:none!important rule was overriding workspace-toggle-btn visibility on non-mobile viewports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Always show the session actions trigger on mobile (no hover state on touch devices) and restore right padding so text truncates with ellipsis before the dots icon. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The "Manage profiles" and "Manage workspaces" links in the composer footer dropdowns called switchPanel() which only changes the active panel content but doesn't open the sidebar. Replaced with mobileSwitchPanel() which also opens the sidebar so the panel is actually visible. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the icon-only chip styling up into the existing max-width:768px media query so chips collapse to icon-only on tablets too, preventing composer footer overflow on mid-size screens. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When overflow-x is set to auto, the CSS spec implicitly changes overflow-y from visible to auto, allowing a vertical scrollbar to appear from slight chip padding/border overflow. Explicitly set overflow-y:hidden to prevent this. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4333303 to
ef015db
Compare
|
All reviewer feedback has been addressed. Latest push includes two additional fixes:
Ready for review 🙏 |
Full Independent Review: PR #242 — UI refresh (rebased on
|
Second sweep complete —
|
Merge ready —
|
Major UI overhaul by @aronprins, rebased and reviewed on pr-242-review. - Composer becomes control hub: model/profile/workspace chips in footer - Hermes Control Center replaces gear settings modal (tabbed, 3 sections) - Activity bar removed; status inline in composer footer - Session ⋯ dropdown replaces inline pin/archive/trash buttons - Workspace panel state machine (closed/browse/preview) - Circular context ring (token count, cost, % used) - OLED theme (7th built-in theme) - Mobile: icon-only chips at ≤640px, composer overflow-x:auto - 742 tests pass; README + CHANGELOG updated for v0.50.0 Co-authored-by: Aron Prins <pwf.aron@gmail.com>
…loses #242) * Polish workspace panel behavior and app dialogs * Replace remaining emoji UI glyphs with Lucide icons * Redesign composer footer around model and context controls Move the model selector into the composer footer, replace the linear context pill with a compact circular badge plus tooltip, and remove the redundant topbar model pill. Design credit and inspiration: Theo / T3 Code. Reference implementation: https://github.com/pingdotgg/t3code/ * Remove obsolete activity bar Drop the old activity bar, keep turn-scoped state in the composer footer, and route remaining non-chat status messages through toasts. This leaves live tool cards and the message timeline as the primary progress UI, with the composer owning stop/cancel and brief turn status. * Move workspace and model switching into composer footer * Move profile switching into composer footer * Refactor Hermes control center UI * Redesign control center settings modal layout Widen the modal to 860px, simplify the tab list to icon+label rows, stretch the tab column's divider to full height, lock the panel to a fixed height so switching tabs no longer resizes the outer shell, and always open on the Conversation tab. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Put session item actions in a dropdown * Use Hermes mark in sidebar control button * Reset control center section on close * Drop session-item left border indicator Remove the left-border accent used for active, CLI, and project rows — each state already has a dedicated cue (gold fill, cli badge, project dot), so the border was redundant. Fully round the row, add 2px bottom spacing between rows, and strip the matching JS/CSS overrides. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Increase session search input vertical padding Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Normalise odd pixel values across UI Snap padding, gap, and border-radius values to the 2/4/6/8/10/12 grid across composer chips, sidebar panels, cron list, settings, approval buttons, dropdowns, and inline message edit — eliminating the 7/9/11px drift that was making sibling elements feel subtly misaligned. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add missing #btnMobileFiles button and .mobile-files-btn CSS (for mobile QA suite) The mobile layout regression suite (test_mobile_layout.py) requires: - #btnMobileFiles onclick=toggleMobileFiles() in topbar chips - .mobile-files-btn CSS rules for responsive show/hide at 640/900px breakpoints Also adds max-width guard to .profile-dropdown to prevent clipping at narrow viewports. * Improve composer footer mobile responsiveness and UX - Collapse composer chips to icon-only at <=400px viewports - Add model chip icon (CPU) so it remains tappable when labels are hidden - Show send button always (disabled state when empty, hidden during streaming) - Show context usage indicator on session load, not just after streaming - Add cancel status fallback timeout to prevent stale "Cancelling..." text - Update tests to match new send button and busy state behavior * Fix duplicate files button and broken workspace close on mobile Remove redundant #btnMobileFiles button that duplicated #btnWorkspacePanelToggle in the mobile topbar. Fix workspace panel close button calling undefined closeMobileFiles() — now calls closeWorkspacePanel(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix model chip icon vertical alignment in composer footer Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix workspace toggle button hidden on desktop by conflicting CSS class Remove mobile-files-btn class from #btnWorkspacePanelToggle — its display:none!important rule was overriding workspace-toggle-btn visibility on non-mobile viewports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix session actions dots button inaccessible on mobile sidebar Always show the session actions trigger on mobile (no hover state on touch devices) and restore right padding so text truncates with ellipsis before the dots icon. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix composer footer manage links not opening sidebar panel The "Manage profiles" and "Manage workspaces" links in the composer footer dropdowns called switchPanel() which only changes the active panel content but doesn't open the sidebar. Replaced with mobileSwitchPanel() which also opens the sidebar so the panel is actually visible. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Widen icon-only composer chips breakpoint from 400px to 768px Move the icon-only chip styling up into the existing max-width:768px media query so chips collapse to icon-only on tablets too, preventing composer footer overflow on mid-size screens. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix composer-left vertical scrollbar by setting overflow-y:hidden When overflow-x is set to auto, the CSS spec implicitly changes overflow-y from visible to auto, allowing a vertical scrollbar to appear from slight chip padding/border overflow. Explicitly set overflow-y:hidden to prevent this. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: resolve rebase conflicts and fix control center test assertions - Resolved 4 conflicts during rebase onto master (workspace.js, boot.js, index.html, test_sprint34.py) - Fixed test_sprint34.py: _controlSection -> _settingsSection, cc-tab -> settings-tabs (matching actual implementation) - Fixed quoting syntax error in test assertion Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update version badge in System tab to v0.49.4 * docs: update README and CHANGELOG for v0.50.0 UI refresh, bump version badge --------- Co-authored-by: Aron Prins <pwf.aron@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
|
🎉 Merged — thank you, @aronprins! v0.50.0 is live. Your UI overhaul is the biggest single contribution to the project and it shows — the composer footer layout, the Control Center, the context ring, the We've added a Contributors section to the README that calls out your contribution specifically. We'd love to see more PRs from you. |
* fix: custom provider with slash model name no longer rerouted to OpenRouter (nesquena#255) When base_url is configured in config.yaml, resolve_model_provider() now trusts the configured provider/base_url entirely and skips the slash-based OpenRouter heuristic. Fixes google/gemma-4-26b-a4b with provider:custom being silently routed to OpenRouter, resulting in 401 errors. Fixes nesquena#230 * test: mobile layout regression suite — 14 tests for every QA run (nesquena#254) Adds tests/test_mobile_layout.py with 14 static regression tests that run on every QA pass to catch mobile layout breakage before it reaches prod. Covers: breakpoints at 900px/640px, right panel slide-over CSS, mobile overlay, bottom nav, files button, profile dropdown z-index, chip overflow, workspace close, 100dvh, 44px touch targets, 16px font-size on textarea. * feat: /skills slash command lists and filters available Hermes skills (nesquena#257) Adds /skills [query] command to commands.js. Fetches from /api/skills, groups by category (alphabetically sorted), displays as a formatted assistant message. Optional query filters by name, description, or category. i18n keys added for en, de, zh, zh-Hant. 1 regression test added. Fixes nesquena#248 * feat: shared app dialogs replace native confirm()/prompt() calls (nesquena#251) Adds showConfirmDialog() and showPromptDialog() helpers to ui.js, backed by a themed #appDialogOverlay. Replaces all 11 native browser confirm/prompt call sites across panels.js, sessions.js, ui.js, workspace.js. Supports: danger mode, keyboard focus trap (Tab/Escape/Enter), focus restore, ARIA roles, mobile-responsive stacked buttons at 640px. i18n for en/de/zh/zh-Hant. 5 new tests in test_sprint33.py verify markup, CSS, helpers, and absence of native dialog calls. Extracted from PR nesquena#242. * fix: Android Chrome mobile — workspace panel close + profile dropdown (nesquena#256) Fix nesquena#247: toggleMobileFiles() now shows/hides the mobile overlay when toggling the right workspace panel. New closeMobileFiles() helper closes the panel with correct overlay state tracking. Overlay onclick calls both closeMobileSidebar() and closeMobileFiles(). Mobile-only close button (x) added to workspace panel header. Fix nesquena#246: profile dropdown uses position:fixed;top:56px;right:8px at max-width:900px, escaping the overflow-x:auto stacking context that was clipping it on Android Chrome. Fix applied during review: closeMobileSidebar() now checks if the right panel is still open before hiding the overlay, preventing the overlay from disappearing when only the sidebar is closed. Fixes nesquena#247 Fixes nesquena#246 * feat: session ⋯ action dropdown replaces per-row buttons (nesquena#252) Replaces the 5 per-row hover action buttons (pin/move/archive/duplicate/trash) with a single ⋯ trigger that opens a positioned dropdown menu. Menu has full keyboard (Escape), click-outside, scroll, and resize-reposition handling. Position:fixed prevents sidebar clipping. 5 actions: Pin/Unpin, Move to project, Archive/Unarchive, Duplicate, Delete (danger style). Each with icon and descriptive subtitle. Updated test_sprint16.py: test_sessions_js_uses_action_menu_not_per_row_buttons asserts the new trigger and menu functions exist, old per-row classes are gone. Extracted from PR nesquena#242. * docs: v0.47.0 release notes, bump version, update test counts (645) --------- Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
…loses nesquena#242) * Polish workspace panel behavior and app dialogs * Replace remaining emoji UI glyphs with Lucide icons * Redesign composer footer around model and context controls Move the model selector into the composer footer, replace the linear context pill with a compact circular badge plus tooltip, and remove the redundant topbar model pill. Design credit and inspiration: Theo / T3 Code. Reference implementation: https://github.com/pingdotgg/t3code/ * Remove obsolete activity bar Drop the old activity bar, keep turn-scoped state in the composer footer, and route remaining non-chat status messages through toasts. This leaves live tool cards and the message timeline as the primary progress UI, with the composer owning stop/cancel and brief turn status. * Move workspace and model switching into composer footer * Move profile switching into composer footer * Refactor Hermes control center UI * Redesign control center settings modal layout Widen the modal to 860px, simplify the tab list to icon+label rows, stretch the tab column's divider to full height, lock the panel to a fixed height so switching tabs no longer resizes the outer shell, and always open on the Conversation tab. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Put session item actions in a dropdown * Use Hermes mark in sidebar control button * Reset control center section on close * Drop session-item left border indicator Remove the left-border accent used for active, CLI, and project rows — each state already has a dedicated cue (gold fill, cli badge, project dot), so the border was redundant. Fully round the row, add 2px bottom spacing between rows, and strip the matching JS/CSS overrides. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Increase session search input vertical padding Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Normalise odd pixel values across UI Snap padding, gap, and border-radius values to the 2/4/6/8/10/12 grid across composer chips, sidebar panels, cron list, settings, approval buttons, dropdowns, and inline message edit — eliminating the 7/9/11px drift that was making sibling elements feel subtly misaligned. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add missing #btnMobileFiles button and .mobile-files-btn CSS (for mobile QA suite) The mobile layout regression suite (test_mobile_layout.py) requires: - #btnMobileFiles onclick=toggleMobileFiles() in topbar chips - .mobile-files-btn CSS rules for responsive show/hide at 640/900px breakpoints Also adds max-width guard to .profile-dropdown to prevent clipping at narrow viewports. * Improve composer footer mobile responsiveness and UX - Collapse composer chips to icon-only at <=400px viewports - Add model chip icon (CPU) so it remains tappable when labels are hidden - Show send button always (disabled state when empty, hidden during streaming) - Show context usage indicator on session load, not just after streaming - Add cancel status fallback timeout to prevent stale "Cancelling..." text - Update tests to match new send button and busy state behavior * Fix duplicate files button and broken workspace close on mobile Remove redundant #btnMobileFiles button that duplicated #btnWorkspacePanelToggle in the mobile topbar. Fix workspace panel close button calling undefined closeMobileFiles() — now calls closeWorkspacePanel(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix model chip icon vertical alignment in composer footer Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix workspace toggle button hidden on desktop by conflicting CSS class Remove mobile-files-btn class from #btnWorkspacePanelToggle — its display:none!important rule was overriding workspace-toggle-btn visibility on non-mobile viewports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix session actions dots button inaccessible on mobile sidebar Always show the session actions trigger on mobile (no hover state on touch devices) and restore right padding so text truncates with ellipsis before the dots icon. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix composer footer manage links not opening sidebar panel The "Manage profiles" and "Manage workspaces" links in the composer footer dropdowns called switchPanel() which only changes the active panel content but doesn't open the sidebar. Replaced with mobileSwitchPanel() which also opens the sidebar so the panel is actually visible. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Widen icon-only composer chips breakpoint from 400px to 768px Move the icon-only chip styling up into the existing max-width:768px media query so chips collapse to icon-only on tablets too, preventing composer footer overflow on mid-size screens. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix composer-left vertical scrollbar by setting overflow-y:hidden When overflow-x is set to auto, the CSS spec implicitly changes overflow-y from visible to auto, allowing a vertical scrollbar to appear from slight chip padding/border overflow. Explicitly set overflow-y:hidden to prevent this. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: resolve rebase conflicts and fix control center test assertions - Resolved 4 conflicts during rebase onto master (workspace.js, boot.js, index.html, test_sprint34.py) - Fixed test_sprint34.py: _controlSection -> _settingsSection, cc-tab -> settings-tabs (matching actual implementation) - Fixed quoting syntax error in test assertion Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update version badge in System tab to v0.49.4 * docs: update README and CHANGELOG for v0.50.0 UI refresh, bump version badge --------- Co-authored-by: Aron Prins <pwf.aron@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
* fix: custom provider with slash model name no longer rerouted to OpenRouter (nesquena#255) When base_url is configured in config.yaml, resolve_model_provider() now trusts the configured provider/base_url entirely and skips the slash-based OpenRouter heuristic. Fixes google/gemma-4-26b-a4b with provider:custom being silently routed to OpenRouter, resulting in 401 errors. Fixes nesquena#230 * test: mobile layout regression suite — 14 tests for every QA run (nesquena#254) Adds tests/test_mobile_layout.py with 14 static regression tests that run on every QA pass to catch mobile layout breakage before it reaches prod. Covers: breakpoints at 900px/640px, right panel slide-over CSS, mobile overlay, bottom nav, files button, profile dropdown z-index, chip overflow, workspace close, 100dvh, 44px touch targets, 16px font-size on textarea. * feat: /skills slash command lists and filters available Hermes skills (nesquena#257) Adds /skills [query] command to commands.js. Fetches from /api/skills, groups by category (alphabetically sorted), displays as a formatted assistant message. Optional query filters by name, description, or category. i18n keys added for en, de, zh, zh-Hant. 1 regression test added. Fixes nesquena#248 * feat: shared app dialogs replace native confirm()/prompt() calls (nesquena#251) Adds showConfirmDialog() and showPromptDialog() helpers to ui.js, backed by a themed #appDialogOverlay. Replaces all 11 native browser confirm/prompt call sites across panels.js, sessions.js, ui.js, workspace.js. Supports: danger mode, keyboard focus trap (Tab/Escape/Enter), focus restore, ARIA roles, mobile-responsive stacked buttons at 640px. i18n for en/de/zh/zh-Hant. 5 new tests in test_sprint33.py verify markup, CSS, helpers, and absence of native dialog calls. Extracted from PR nesquena#242. * fix: Android Chrome mobile — workspace panel close + profile dropdown (nesquena#256) Fix nesquena#247: toggleMobileFiles() now shows/hides the mobile overlay when toggling the right workspace panel. New closeMobileFiles() helper closes the panel with correct overlay state tracking. Overlay onclick calls both closeMobileSidebar() and closeMobileFiles(). Mobile-only close button (x) added to workspace panel header. Fix nesquena#246: profile dropdown uses position:fixed;top:56px;right:8px at max-width:900px, escaping the overflow-x:auto stacking context that was clipping it on Android Chrome. Fix applied during review: closeMobileSidebar() now checks if the right panel is still open before hiding the overlay, preventing the overlay from disappearing when only the sidebar is closed. Fixes nesquena#247 Fixes nesquena#246 * feat: session ⋯ action dropdown replaces per-row buttons (nesquena#252) Replaces the 5 per-row hover action buttons (pin/move/archive/duplicate/trash) with a single ⋯ trigger that opens a positioned dropdown menu. Menu has full keyboard (Escape), click-outside, scroll, and resize-reposition handling. Position:fixed prevents sidebar clipping. 5 actions: Pin/Unpin, Move to project, Archive/Unarchive, Duplicate, Delete (danger style). Each with icon and descriptive subtitle. Updated test_sprint16.py: test_sessions_js_uses_action_menu_not_per_row_buttons asserts the new trigger and menu functions exist, old per-row classes are gone. Extracted from PR nesquena#242. * docs: v0.47.0 release notes, bump version, update test counts (645) --------- Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
…loses nesquena#242) * Polish workspace panel behavior and app dialogs * Replace remaining emoji UI glyphs with Lucide icons * Redesign composer footer around model and context controls Move the model selector into the composer footer, replace the linear context pill with a compact circular badge plus tooltip, and remove the redundant topbar model pill. Design credit and inspiration: Theo / T3 Code. Reference implementation: https://github.com/pingdotgg/t3code/ * Remove obsolete activity bar Drop the old activity bar, keep turn-scoped state in the composer footer, and route remaining non-chat status messages through toasts. This leaves live tool cards and the message timeline as the primary progress UI, with the composer owning stop/cancel and brief turn status. * Move workspace and model switching into composer footer * Move profile switching into composer footer * Refactor Hermes control center UI * Redesign control center settings modal layout Widen the modal to 860px, simplify the tab list to icon+label rows, stretch the tab column's divider to full height, lock the panel to a fixed height so switching tabs no longer resizes the outer shell, and always open on the Conversation tab. * Put session item actions in a dropdown * Use Hermes mark in sidebar control button * Reset control center section on close * Drop session-item left border indicator Remove the left-border accent used for active, CLI, and project rows — each state already has a dedicated cue (gold fill, cli badge, project dot), so the border was redundant. Fully round the row, add 2px bottom spacing between rows, and strip the matching JS/CSS overrides. * Increase session search input vertical padding * Normalise odd pixel values across UI Snap padding, gap, and border-radius values to the 2/4/6/8/10/12 grid across composer chips, sidebar panels, cron list, settings, approval buttons, dropdowns, and inline message edit — eliminating the 7/9/11px drift that was making sibling elements feel subtly misaligned. * Add missing #btnMobileFiles button and .mobile-files-btn CSS (for mobile QA suite) The mobile layout regression suite (test_mobile_layout.py) requires: - #btnMobileFiles onclick=toggleMobileFiles() in topbar chips - .mobile-files-btn CSS rules for responsive show/hide at 640/900px breakpoints Also adds max-width guard to .profile-dropdown to prevent clipping at narrow viewports. * Improve composer footer mobile responsiveness and UX - Collapse composer chips to icon-only at <=400px viewports - Add model chip icon (CPU) so it remains tappable when labels are hidden - Show send button always (disabled state when empty, hidden during streaming) - Show context usage indicator on session load, not just after streaming - Add cancel status fallback timeout to prevent stale "Cancelling..." text - Update tests to match new send button and busy state behavior * Fix duplicate files button and broken workspace close on mobile Remove redundant #btnMobileFiles button that duplicated #btnWorkspacePanelToggle in the mobile topbar. Fix workspace panel close button calling undefined closeMobileFiles() — now calls closeWorkspacePanel(). * Fix model chip icon vertical alignment in composer footer * Fix workspace toggle button hidden on desktop by conflicting CSS class Remove mobile-files-btn class from #btnWorkspacePanelToggle — its display:none!important rule was overriding workspace-toggle-btn visibility on non-mobile viewports. * Fix session actions dots button inaccessible on mobile sidebar Always show the session actions trigger on mobile (no hover state on touch devices) and restore right padding so text truncates with ellipsis before the dots icon. * Fix composer footer manage links not opening sidebar panel The "Manage profiles" and "Manage workspaces" links in the composer footer dropdowns called switchPanel() which only changes the active panel content but doesn't open the sidebar. Replaced with mobileSwitchPanel() which also opens the sidebar so the panel is actually visible. * Widen icon-only composer chips breakpoint from 400px to 768px Move the icon-only chip styling up into the existing max-width:768px media query so chips collapse to icon-only on tablets too, preventing composer footer overflow on mid-size screens. * Fix composer-left vertical scrollbar by setting overflow-y:hidden When overflow-x is set to auto, the CSS spec implicitly changes overflow-y from visible to auto, allowing a vertical scrollbar to appear from slight chip padding/border overflow. Explicitly set overflow-y:hidden to prevent this. * fix: resolve rebase conflicts and fix control center test assertions - Resolved 4 conflicts during rebase onto master (workspace.js, boot.js, index.html, test_sprint34.py) - Fixed test_sprint34.py: _controlSection -> _settingsSection, cc-tab -> settings-tabs (matching actual implementation) - Fixed quoting syntax error in test assertion * fix: update version badge in System tab to v0.49.4 * docs: update README and CHANGELOG for v0.50.0 UI refresh, bump version badge --------- Co-authored-by: Aron Prins <pwf.aron@gmail.com> Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
Summary
This branch is a focused UI pass that reorganises the main chrome around the composer and consolidates all settings/session tools behind a single "Hermes Control Center" surface. It also replaces the scattered activity bar + native
confirm/promptcalls with a consistent status+dialog system, and does a sweeping pixel/icon cleanup across the UI.No server-side behaviour changes — everything lives in
static/plus a couple of new static-asset sanity tests.What changed
Composer becomes the control hub (inspired by Theo / T3 Code)
Hermes Control Center replaces the old Settings modal
tests/test_sprint34.py.Activity bar removed, status rerouted
setComposerStatus.setStatus.Shared app dialogs replace
confirm()/prompt()showConfirmDialog/showPromptDialoghelpers inui.js, backed by#appDialogOverlaymarkup and a themed.app-dialog-*CSS block.confirm()/prompt()callsites acrosspanels.js,sessions.js,ui.js(delete session, delete cron, delete project, clear conversation, remove workspace, new file/folder prompts, project rename, etc.) now go through the shared dialog, with proper focus trap, Esc/Enter handling, and danger styling.tests/test_sprint33.pylocks this in by grepping the static bundle for any remainingconfirm(/prompt(calls.Session list: hover actions → single dropdown
Workspace panel behaviour
Icon and emoji cleanup
Pixel normalisation pass
Tests
Docs
Test plan