fix: accessibility pass — keyboard reachability and dialog semantics - #285
Open
NovakPAai wants to merge 1 commit into
Open
fix: accessibility pass — keyboard reachability and dialog semantics#285NovakPAai wants to merge 1 commit into
NovakPAai wants to merge 1 commit into
Conversation
Closes the gaps found in a UX audit across Overview, Projects, Sessions, and Workspace: real keyboard focus and screen-reader semantics were inconsistent — some controls had them, most didn't. - Overview: .ov-card gets a visible :focus-visible outline (it was already a real <button>, just missing the ring). - Calendar: day cells are now real <button>s (were unfocusable divs) with aria-pressed reflecting selection; the popup is a proper role="dialog" aria-modal with Escape-to-close and focus returned to the date button on close (toggleCalendar/closeCalendar/onCalendarPopupKeydown). - Add Project modal: addProjectSwitchTab() now updates aria-selected and roving tabindex when switching tabs (previously only toggled the visual .active class, so a screen reader kept announcing the first tab as selected forever); added Left/Right/Home/End arrow-key navigation matching the existing Projects/History tablist pattern. - Session cards (.card / .list-row / .qa-item): were plain divs with an onclick and nested buttons — unreachable by Tab entirely. Added tabindex, a descriptive aria-label, :focus-visible styling, and a shared onCardKeydown handler (Enter/Space triggers the card's own click, guarded so it doesn't also fire for a nested button/checkbox's own key handling). - Detail panel: role="dialog" aria-modal, wired into the existing _installModalFocusTrap/_uninstallModalFocusTrap helper (same one Add Project / Projects Settings use) for Tab-trapping and focus-return on close. Hardened _uninstallModalFocusTrap to skip focus-return when the captured element has since been detached from the DOM (a background poll/re-render can replace it while the modal is open) rather than silently stranding focus on the modal's own now-hidden close button. - Workspace: aria-label on the pane close button, tab close button, and the three launch/layout <select> menus that only had a title before. Split-pane resize handles (.ws-resizer) are now real ARIA separators — tabindex, role="separator", aria-orientation, and arrow-key resize (mirrors the pointer-drag math without triggering a full handle rebuild mid-interaction, which would destroy and unfocus the handle the user is actively adjusting).
vakovalskii
added a commit
that referenced
this pull request
Aug 2, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up on a UX audit run across Overview, Projects, Sessions, and Workspace: keyboard/screen-reader support was inconsistent throughout — some controls had real focus/ARIA semantics, most didn't. This closes the accessibility gaps found (see conversation history for the full audit).
.ov-cardgets a visible:focus-visibleoutline (it was already a real<button>, just missing the ring — every other button class in the app has one).<button>s (were unfocusable<div>s) witharia-pressedreflecting selection; the popup is a properrole="dialog" aria-modalwith Escape-to-close and focus returned to the date button on close.addProjectSwitchTab()now updatesaria-selected/rovingtabindexwhen switching tabs — it previously only toggled the visual.activeclass, so a screen reader kept announcing the first tab as selected forever. Added Left/Right/Home/End arrow-key navigation matching the existing Projects/History tablist pattern one function away..card/.list-row/.qa-item): were plain<div>s with anonclickand nested buttons — entirely unreachable by Tab, only mouse or the undiscoverable j/k shortcuts worked. Addedtabindex, a descriptivearia-label,:focus-visiblestyling, and a sharedonCardKeydownhandler (Enter/Space triggers the card's own click, guarded so it doesn't also double-fire for a nested button/checkbox's own key handling).role="dialog" aria-modal, wired into the existing_installModalFocusTrap/_uninstallModalFocusTraphelper (same one Add Project / Projects Settings already use) for Tab-trapping and focus-return on close. Also hardened_uninstallModalFocusTrapto skip focus-return when the captured element has since been detached from the DOM (a background poll/re-render can replace it while a modal is open) instead of silently stranding focus on the modal's own now-hidden close button.aria-labelon the pane close button, tab close button, and the three launch/layout<select>menus that only had atitlebefore. Split-pane resize handles (.ws-resizer) are now real ARIA separators —tabindex,role="separator",aria-orientation, and arrow-key resize (mirrors the pointer-drag math without triggering a full handle rebuild mid-interaction, which would destroy and unfocus the handle the user is actively adjusting).Test plan
node --test "test/**/*.test.js"— 257 passed, 1 skipped (win32-only)aria-selected/tabindexon click and via arrow-key navigation🤖 Generated with Claude Code