Skip to content

Remove the positive tabindex from the chat composer input #270

Description

@HMarzban

Problem

The composer input sets tabIndex={1} on its wrapper and tabIndex={2} on EditorContent (apps/webapp/src/components/chatroom/components/MessageComposer/components/Input/Input.tsx:27, :31). A search of apps/webapp/src on 14ab7f9c1 finds no other positive tab index.

A positive tab index puts an element ahead of every normal element in the page tab order. When a composer is on screen, the first Tab press from the top of the page goes to it, ahead of the pad header. EditorContent passes the prop to its wrapper div. So the composer input gives two focus stops with no role and no name, before the editable text area.

This fails WCAG 2.2 success criterion 2.4.3, Focus Order. Both values arrived in 83cb3afa9 (refactor: emoji picker v0.5, 2025-07-24). The commit message gives no reason.

One Cypress spec depends on the second value. data-testid="composer-input" sits on the same element as tabIndex={2} (Input.tsx:30-31). apps/webapp/cypress/e2e/chatroom/send-and-retry.cy.ts types into that test id. Cypress refuses .type() on an element that is neither focusable nor editable.

Steps to reproduce

  1. On desktop, open a pad as a channel member, or signed out. Open a heading chat, and copy its Share link. The link carries ?chatroom=.
  2. Open that link in a new tab. Wait until the composer shows. Without clicking the page, press Tab once.
  3. See focus land on the composer input wrapper, not on the first control of the page.
  4. Press Tab again. See focus move to a second wrapper. The text area still has no caret.

Acceptance criteria

  • No element in apps/webapp/src has a positive tabIndex.
  • The composer input is one focus stop: the editable text area.
  • Tab order up to the editable text area follows the visual order: the insert menu button, then the editable text area.
  • The send-and-retry spec still types into the composer. Its .type() calls target the editable element inside the composer-input test id.

Agent Brief

Category: bug
Summary: Remove the two positive tab indexes, so the composer input is one focus stop in document order.

Current behavior:
The composer input wrapper and the EditorContent wrapper take focus first in the page, as two unnamed focus stops before the editable text area.

Desired behavior:
Inside the composer input, only the editable text area is focusable. It is reached in normal document order.

Key interfaces:

  • The composer Input component.
  • EditorContent from @tiptap/react — it forwards extra props to its wrapper div.
  • The composer-input test id — a Cypress spec types into it, so the spec must target a focusable or editable element.

Out of scope

Notes

Run the send-and-retry spec with NEXT_PUBLIC_E2E=true on the webapp dev server. Without it, the /c/test-channel page renders nothing, and each test times out. At 14ab7f9c1, the second and third tests also fail on a data-status check, which #263 fixes. All three tests type into the composer first, so the .type() criterion can still be checked.

The evidence is a code trace and a repo search on 14ab7f9c1. The steps above were not run in a browser.

Activity

  1. added a commit that references this issue on Sep 22, 2026
    1091f99
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ChatRelated to chat featuresUIbugSomething isn't workinggood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions