feat: multichat grid view polish (a11y, unread, tab UX, mobile)#15
Merged
Conversation
…s dot - expanded row maxHeight: min(100dvh - 16px, 100vw + 88px) so landscape / wide-mobile no longer overflows the viewport (was unconditional 100vw + 88px). - offline status dot uses --text-muted token instead of bg-gray-500 to respect light/dark theme.
- Export MAX_CELLS_PER_TAB from chat-tabs-api so GridPage and SessionPicker share one source of truth (was duplicated literal 12 across files). - SessionPicker modal gets role=dialog, aria-modal, aria-labelledby on title. - Modal max-height switches to 80dvh (was 80vh) so iOS soft-keyboard does not crush the picker. - Overflow banner gets role=status for AT announcement.
Tab bar: - role=tablist on container, role=tab + aria-selected on each chip. - Arrow Left/Right cycle focus, Home/End jump, F2 starts rename, Enter/Space activate. Roving tabindex (active chip is 0, others -1). - focus-visible ring for keyboard users. - Softened border-b to /60 per design rules (was solid). Grid body: - role=tabpanel on desktop grid container, aria-labelledby active tab. - role=grid + aria-label on cells container with visible/total count. - role=gridcell + aria-selected on each cell wrapper. Layout picker: - aria-haspopup=listbox, aria-expanded, aria-label. - Escape closes and returns focus to trigger. - Listbox role on menu, option role + aria-selected on items. Cell header: - Drop misleading 'open in single-chat' button (was navigating to # / and dropping session context). Leave a TODO for when single-chat route accepts a sessionId param. - Remove button gets aria-label with session name.
…n, scroll-snap - Tab delete confirmation now lists the number of session bindings being removed and warns when deleting the only remaining tab. - Last-tab guard: when the final tab is deleted, immediately create a fresh empty tab and route to it instead of leaving the user in an empty-state route with no active tab. - Tab bar: scroll-snap proximity + smooth scroll for overflow rows so the bar scrolls cleanly when there are many tabs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a row expands, scroll its header to the top of the scroll container so the input field below stays visible above the iOS soft keyboard. Uses scroll-mt-2 so the header isn't flush against the container edge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Per-session unread counter. Increments only on server-emitted assistant 'message' events (not text_delta) for visible cells that are not the currently-active cell. Cleared when the cell is activated. - Soft indigo badge on the cell header (sr-only label included). No badge on the active cell — that's where the user already is. - Page-level role="status" aria-live="polite" announcer reports the TOTAL unread count across cells, never the message content. Quiet by design: one summary per change, no per-cell announcement. Resolves the P2 a11y gap: incoming messages on background cells were silent for screen-reader users. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documents the round-2 polish work: - ARIA tablist/grid/listbox + roving tabindex + keyboard map - Tab bar scroll-snap behavior - Tab delete confirm text + last-tab protection - Per-cell unread counter + polite aria-live announcer policy Co-Authored-By: Claude Opus 4.7 (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
Polish pass on top of the grid-view foundation (PR #2) — accessibility, keyboard nav, unread tracking, tab delete UX, and mobile accordion improvements. Cherry-picked clean from
feat/multichat-grid-viewto exclude unrelated Phase 04/05 work stacked on that branch.aria-liveannouncer for inactive cellsdvhupper bound, design-token status dot, scrolls expanded row into viewMAX_CELLS_PER_TABsingle constant,SessionPickera11ydocs/grid-view.md)Ship inventory:
.planning/phases/03-multichat-grid-view/SHIP-COMMITS.mdTest plan
role=statusannouncement100vhkeyboard collapseGenerated with Claude Code
@