feat: session ⋯ action dropdown replaces per-row buttons (extracted from #242) - #252
feat: session ⋯ action dropdown replaces per-row buttons (extracted from #242)#252nesquena-hermes wants to merge 1 commit into
Conversation
…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.
Full Review: PR #252 — Session action dropdownSecurity AuditClean. All user data ( Code ReviewDropdown system (
CSS changes:
Test update: One noteThe Tests573 passed, 0 failed (1 pre-existing failure from unmerged PR #243's test). VerdictApproved. Clean UX improvement, proper event lifecycle, accessible. Ready to merge. |
|
Agent review — APPROVED ✅ (merged to stage)
Browser tested: ⋯ menu opens with correct 5 items and icons, Escape closes, zero JS errors. Tests: 624 passed on review branch. Stage total: 645 passed, 0 failed. |
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>
|
Merged to master via stage branch in PR #258 (v0.47.0). |
* 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>
* 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>
Summary
Replaces the five per-row hover action buttons (pin, move, archive, duplicate, trash) in the session list with a single
⋯trigger button that opens a positioned dropdown menu. Extracted from @aronprins's PR #242 as a self-contained piece.What changed
static/sessions.jsICONSconst at top with inline SVG for pin, unpin, folder, archive, unarchive, dup, trash, more (⋯)closeSessionActionMenu()— removes the menu and cleans up anchor state_positionSessionActionMenu(anchorEl)— positions the menu in the viewport, flips above anchor if not enough space below_buildSessionAction(label, meta, icon, onSelect, extraClass)— builds a single menu option with icon + label + subtitle_openSessionActionMenu(session, anchorEl)— builds and opens the full dropdown with 5 actionsrenderSessionListFromCacheupdated: per-row buttons replaced with single⋯menuBtnstatic/style.css.session-actionsgradient overlay + per-row button styles.session-actions-trigger(26×26px, hover background),.session-action-menu(position:fixed, z-index:999, flipped shadow),.session-action-optwith icon/meta layout, danger statetests/test_sprint16.pytest_sessions_js_active_skips_project_border→test_sessions_js_uses_action_menu_not_per_row_buttons— assertssession-actions-trigger,_openSessionActionMenu,closeSessionActionMenuexist and oldact-pin/act-archiveare goneTests
624 passed, 0 failed, 0 skipped (same count as master — this PR updates an existing test, not adds new ones)
Browser tested: menu opens with correct 5 items (Pin, Move to project, Archive, Duplicate, Delete), icons and subtitles render, Escape closes cleanly, zero JS console errors.
Relationship to PR #242
Extracted from @aronprins's
feat/ui-improvements-round1. The session action menu is self-contained — it doesn't depend on the composer footer restructure, control center, or activity bar removal in the larger PR. Merging this now improves the session list UX independently.