Skip to content

Keep keyboard focus inside the open popup chat #335

Closed

Description

@anurag629

When the popup chat is open, Tab and Shift+Tab can leave the panel and land on the host page behind it. The panel is a dialog (role="dialog", Escape closes it, focus returns to the launcher), so focus should cycle inside it until it's closed (WCAG 2.4.3, focus order).

What to do

  • In popup mode, while the panel is open, Tab from the last focusable element goes to the first, and Shift+Tab from the first goes to the last.
  • Work out the focusable elements when Tab is pressed, not once at open. The pre-chat form, retry and regenerate buttons come and go.
  • Inline mode is part of the page, so leave it alone.
  • Add aria-modal="true" to the popup panel next to role="dialog".

Where to look

  • packages/widget/src/dom/panel.ts: the constructor sets role="dialog" and handles Escape in a keydown listener. The trap can go in the same listener.
  • The panel lives in a shadow root, so the focused element is shadowRoot.activeElement, not document.activeElement (see containsFocus()).
  • packages/widget/tests/dom/panel.test.ts

Acceptance criteria

  • Tab and Shift+Tab wrap inside the open popup, including while the pre-chat form is shown
  • Inline mode and a closed popup are unaffected
  • aria-modal="true" on the popup panel
  • Unit tests for both directions and for inline mode
  • Changeset for @chatcops/widget (patch)
  • pnpm test:coverage, pnpm lint and pnpm size pass

The chat panel (dist/chatcops.panel.js) has a 14 kB gzip budget and about 800 B of it is left, shared by several open issues. Keep the change small, and check pnpm size before you open the PR.

Activity

  1. added
    enhancementNew feature or request
    widgetAffects @chatcops/widget package
    hacktoberfestGood pick for Hacktoberfest contributors
    accessibilityKeyboard, screen reader and a11y fixes
    on Oct 26, 2026
  2. piyusshhjangid commented on Oct 26, 2026

    @piyusshhjangid
    Contributor

    hi @anurag629 i would like to this one on also

  3. anurag629 commented on Oct 26, 2026

    @anurag629
    MemberAuthor

    Assigned to you, @piyusshhjangid, as your second one alongside Hindi in #55.

  4. piyusshhjangid commented on Oct 26, 2026

    @piyusshhjangid
    Contributor

    Hi @anurag629, a7b2051 is already included in dev, and PR #353 has no remaining diff. Could you close #335 as resolved and confirm the contribution is recorded?

  5. anurag629 commented on Oct 26, 2026

    @anurag629
    MemberAuthor

    @piyusshhjangid, I'm afraid it isn't in dev yet. packages/widget/src/dom/panel.ts on codercops/chatcops dev still has no aria-modal and no Tab handling: the last change to that file is #173. My guess is your own fork's dev has it. The force-push reset your branch to dev, which dropped both commits, not just the second, so #353 ended up empty and GitHub closed it.

    a7b2051 still exists in your clone, so this brings it back:

    git fetch upstream
    git checkout -B codex/335-popup-focus-trap upstream/dev
    git cherry-pick a7b2051
    git push -f origin codex/335-popup-focus-trap

    Then open a new PR with Closes #335 (a closed PR whose branch was force-pushed can't always be reopened). Your review there was already done apart from the extra commit, so I'll get to it quickly. #335 stays open and assigned to you until then.

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

Metadata

Metadata

Labels

accessibilityKeyboard, screen reader and a11y fixesenhancementNew feature or requesthacktoberfestGood pick for Hacktoberfest contributorswidgetAffects @chatcops/widget package

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions