diff --git a/muxplex/frontend/app.js b/muxplex/frontend/app.js index 05a9b2d..2bd1cd1 100644 --- a/muxplex/frontend/app.js +++ b/muxplex/frontend/app.js @@ -1738,8 +1738,8 @@ function _openMobileKillConfirm(sessionName, remoteId) { html += '
'; html += ''; html += '
Kill ' + escapeHtml(sessionName) + '?
'; - html += ''; - html += ''; + html += ''; + html += ''; html += '
'; sheet.innerHTML = html; diff --git a/muxplex/frontend/style.css b/muxplex/frontend/style.css index 9afc50e..bacab42 100644 --- a/muxplex/frontend/style.css +++ b/muxplex/frontend/style.css @@ -1156,33 +1156,6 @@ body { -.sidebar-delete { - background: none; - border: none; - color: var(--text-dim); - font-size: 13px; - cursor: pointer; - padding: 1px 5px; - border-radius: 3px; - opacity: 0; - transition: opacity 150ms ease; - pointer-events: none; - flex-shrink: 0; - line-height: 1; -} - -.sidebar-item:hover .sidebar-delete, -.sidebar-item:focus-within .sidebar-delete { - opacity: 1; - pointer-events: auto; -} - -.sidebar-delete:hover { - color: #ef4444; - background: rgba(239, 68, 68, 0.1); - opacity: 1; -} - /* ============================================================ Header actions + settings buttons ============================================================ */ @@ -2432,6 +2405,14 @@ body { margin: 10px auto 6px; } +.flyout-sheet__title { + padding: 8px 16px 12px; + font-size: 15px; + font-weight: 600; + color: var(--text); + text-align: center; +} + .flyout-sheet__item { display: flex; align-items: center; diff --git a/muxplex/tests/test_frontend_css.py b/muxplex/tests/test_frontend_css.py index 8032b9e..76acf9c 100644 --- a/muxplex/tests/test_frontend_css.py +++ b/muxplex/tests/test_frontend_css.py @@ -2274,3 +2274,38 @@ def test_tile_delete_css_removed() -> None: ".tile-delete CSS rules must be removed from style.css — " "the button was removed from buildTileHTML; orphaned CSS is dead code" ) + + +# ── Fix A: .flyout-sheet__title CSS (Phase 3 COE re-verification) ───────────── + + +def test_flyout_sheet_title_css_exists() -> None: + """.flyout-sheet__title must have a CSS rule in the flyout-sheet section. + + Fix A: The kill-confirm sheet renders a title div with class + `flyout-sheet__title` but the CSS rule was missing, leaving the title + as raw unstyled text. + """ + css = read_css() + assert ".flyout-sheet__title" in css, ( + ".flyout-sheet__title CSS rule must exist in style.css — " + "the kill-confirm sheet renders a title div with this class" + ) + + +# ── Fix C: .sidebar-delete orphaned CSS removed (Phase 3 COE re-verification) ── + + +def test_no_sidebar_delete_css() -> None: + """.sidebar-delete CSS rules must be removed from style.css (orphaned dead code). + + Fix C: The .sidebar-delete button was removed from buildSidebarHTML() in a + previous task. The 3 CSS rule blocks (.sidebar-delete, + .sidebar-item:hover .sidebar-delete, .sidebar-delete:hover) are now dead + code and must be cleaned up. + """ + css = read_css() + assert ".sidebar-delete" not in css, ( + ".sidebar-delete CSS rules must be removed from style.css — " + "the button was removed from buildSidebarHTML(); orphaned CSS is dead code" + ) diff --git a/muxplex/tests/test_frontend_js.py b/muxplex/tests/test_frontend_js.py index e6d489a..fffb4bd 100644 --- a/muxplex/tests/test_frontend_js.py +++ b/muxplex/tests/test_frontend_js.py @@ -4181,3 +4181,33 @@ def test_flyout_menu_map_is_const() -> None: assert "var FLYOUT_MENU_MAP" not in _JS, ( "FLYOUT_MENU_MAP must not use 'var' — change to 'const'" ) + + +# ── Fix B: ARIA role correction in kill confirm sheet (Phase 3 COE re-verification) ── + + +def test_kill_confirm_buttons_use_role_button() -> None: + """Kill and Cancel buttons inside the alertdialog must use role='button', not 'menuitem'. + + Fix B: _openMobileKillConfirm() renders buttons inside a role='alertdialog' + panel. The ARIA spec requires buttons inside an alertdialog to carry + role='button' (not role='menuitem', which only belongs inside role='menu'). + """ + # Negative check: role="menuitem" must NOT appear on the confirm-kill button + assert 'data-action="confirm-kill" role="menuitem"' not in _JS, ( + "Kill button inside alertdialog must not use role='menuitem' — " + "use role='button' instead (menuitem is only valid inside role='menu')" + ) + # Negative check: role="menuitem" must NOT appear on the cancel button + assert 'data-action="cancel" role="menuitem"' not in _JS, ( + "Cancel button inside alertdialog must not use role='menuitem' — " + "use role='button' instead (menuitem is only valid inside role='menu')" + ) + # Positive check: role="button" must appear on the confirm-kill button + assert 'data-action="confirm-kill" role="button"' in _JS, ( + "Kill button inside alertdialog must use role='button'" + ) + # Positive check: role="button" must appear on the cancel button + assert 'data-action="cancel" role="button"' in _JS, ( + "Cancel button inside alertdialog must use role='button'" + )