Tab List: Add tab semantics and arrow key navigation - #532
Open
AlexOpasnost wants to merge 2 commits into
Open
Conversation
👷 Deploy request for telegram-tt-previews pending review.Visit the deploys page to approve it
|
|
hope merged. |
`FormattedDateModal` disables two of its tab lists with `pointer-events: none`, which blocks the mouse but not the keyboard. Now that tabs are focusable, add an `isDisabled` prop that drops them from the tab sequence and exposes `aria-disabled`.
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.
Problem
Chat folder tabs (All, Personal, Groups and so on) are plain
<div>s with a click handler. They have no tab semantics, and nothing inside the tab list is focusable, so keyboard and screen reader users cannot reach or switch folders at all.Fix
All of it is in
ui/TabList.The container gets
role="tablist". Each tab getsrole="tab"andaria-selected. Tabindex is roving, so the whole list is a single tab stop. Left and Right arrows move focus and activate the tab, wrapping at both ends, and they go through the existingonSwitchTabprop, so there is no second selection path. A:focus-visibleoutline was added because these elements were never focusable before.The active indicator renders a mirrored copy of every tab. Those copies get no role, no tabindex and no
aria-selected, so they stay out of the accessibility tree and out of the tab order.Arrow navigation starts from the focused element rather than from the
activeTabprop. The prop lags one render behind, so a held arrow key would otherwise stall on a single tab.RTL needs no arrow flipping.
TabListnever setsdir, so DOM order matches visual order in every locale.Mouse, touch and swipe are untouched.
Checks
npm run check:tsandnpm run check:csspass.Verified in
dev:mockedwith real keyboard input. Roles are correct, there is exactly onearia-selectedand onetabIndex=0, the accessibility tree lists each folder once, arrows wrap both ways, Up and Down are not intercepted, focus survives re-render, no console errors.Checked with NVDA on Windows. A folder tab is announced as its name, then
tab, thenselected, together with its position in the set. Each folder is announced once, so the mirrored copies stay out of the accessibility tree. Arrow navigation announces the newly selected folder.Known limits
Forward Tab does not reach the tabs. The search field opens the search panel on focus and that collapses the folder bar.
Shift+Tabreaches them. This is pre-existing and separate from this change.SquareTabList(search tabs) and the vertical folders sidebar have the same gap. I left them alone to keep this scoped.Closes #106