Skip to content

Keep Tab out of image captions - #1224

Open
jeremy wants to merge 1 commit into
mainfrom
caption-tab-focus
Open

Keep Tab out of image captions#1224
jeremy wants to merge 1 commit into
mainfrom
caption-tab-focus

Conversation

@jeremy

@jeremy jeremy commented Aug 6, 2026

Copy link
Copy Markdown
Member

Tabbing through a message drops the cursor into image captions. Reported by a customer in early July; the fix has been sitting inside #1053 since then, behind a review conversation about a different part of that PR.

The bug

The caption is a real <textarea> in the document, so native sequential focus navigation walks straight into it. Verified on main with a probe before touching anything — caret in ordinary text, nothing selected, captionTabIndex: 0, one Tab, and document.activeElement is the caption textarea.

The fix

tabIndex: -1 takes the textarea out of the tab order. That one line is the whole fix for the reported behaviour.

On its own it would trade one accessibility bug for another — a caption no keyboard user could reach at all. So KEY_TAB_COMMAND at COMMAND_PRIORITY_HIGH restores a deliberate path: with an attachment selected, Tab moves into that attachment's caption. Escape hands focus back to the editor and reselects the attachment, so Tab can step in again. Shift+Tab is untouched and still steps backwards out of the editor.

The caption also gains an accessible name (ariaLabel). It is now reachable only on purpose, so the label is what tells a screen-reader user where they have landed.

Why this is separable from #1053

Every external symbol it needs is already on main: $isActionTextAttachmentNode, $createNodeSelectionWith, this.editor, and the existing NodeSelection. Nothing here touches attachment_toolbar.js or fake_selection.js — the two files the open review threads on #1053 are actually about.

Two deliberate trims against the #1053 version:

  • No ariaHidden toggling. That belongs to the aria-hidden caption mirror (.attachment__caption-text), which is not in this PR; without the mirror the toggle is dead code.
  • $singleSelectedNode inlined rather than exported from lexical_helper.js, so this PR adds no shared surface that Improve attachment accessibility #1053 would then conflict with.

#1053 stays open for the toolbar work.

One check worth flagging

The behaviour I could not settle by reading was whether a figure click leaves the contenteditable focused on main, since #1053 also adds a fake-selection span that parks the DOM range inside the figure. Without that span, does KEY_TAB_COMMAND fire at all?

It does. After a figure click on main: activeElement is the contenteditable, window.getSelection().rangeCount is 0 (no DOM range at all — the NodeSelection state), and a Tab keydown still arrives on the contenteditable. The fake-selection span is not load-bearing for this.

Tests

Three, in attachment_caption_focus.test.js. Two are ported from #1053; the first is new#1053's pair does not actually cover the reported complaint, because neither asserts that Tab from a text caret stays out of the caption.

Each was checked for non-vacuity by reverting one piece at a time, and each revert fails exactly one test:

revert fails
drop tabIndex: -1 Tab past an attachment does not fall into its caption
keep tabIndex, drop KEY_TAB_COMMAND Tab from a selected attachment focuses the caption textarea
drop the Escape branch Escape from caption restores attachment selection and editor focus

Worth noting the middle row: with tabIndex at 0 the Tab-into-caption test passes without the command, because native focus order reaches the textarea anyway. It only tests the command once the textarea is out of the tab order.

9/9 green across Chromium, Firefox and WebKit. Full attachment suite: 103 passed. Four tests reported flaky, all upload-timing; main flakes in the same files with a different subset each run, so they are pre-existing and not from this change.

Tabbing through a message drops the cursor into image captions. The caption is
a real <textarea> in the document, so native sequential focus navigation walks
into it: with the caret in ordinary text and nothing selected, one Tab lands in
the caption of the next image rather than moving past it.

tabIndex -1 takes the textarea out of the tab order, which is the whole fix for
the reported behaviour. On its own that would trade one accessibility bug for
another -- a caption no keyboard user can reach at all -- so KEY_TAB_COMMAND at
COMMAND_PRIORITY_HIGH restores a deliberate path: with an attachment selected,
Tab moves into that attachment caption. Escape hands focus back to the editor
and reselects the attachment, so Tab can step in again. Shift+Tab is untouched
and still steps backwards out of the editor.

The caption also gains an accessible name. It is now reachable only on purpose,
so the label is what tells a screen-reader user where they have landed.
Copilot AI balanced review requested due to automatic review settings August 6, 2026 23:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants