RocketChat / RocketChat/Rocket.Chat

Accessibility: Interactive anchor elements lack keyboard accessibility in multiple modals

Open
#38,837 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: bug valid
Dominant language
TypeScript
Stars
46.1k
Forks
13.9k
Avg merge
3d 3h
Merged PRs (30d)
130

Description

Accessibility: Interactive anchor elements lack keyboard accessibility in multiple modals

Labels

type: bug, accessibility, contrib: valid


Description

Multiple components throughout the codebase use <Box is='a' onClick={...}> to create interactive elements without proper accessibility attributes. These pseudo-links are not keyboard accessible and violate WCAG 2.1 Level A guidelines (2.1.1 Keyboard, 4.1.2 Name/Role/Value), preventing keyboard-only users and screen reader users from interacting with critical functionality.

Scope: 5 instances identified across 4 files affecting workspace registration, ABAC administration, Matrix federation, and user status management.


Technical Details

Anchor elements (<a>) with onClick handlers but without href attributes are not keyboard-focusable by default and lack proper semantic information for assistive technologies. The current implementation creates links that:

  • Cannot be focused using the Tab key
  • Cannot be activated with Enter or Space keys
  • Are not announced as interactive elements by screen readers
  • Have no visible focus indicator for keyboard navigation
  • Violate semantic HTML principles

All Affected Files

1. RegisterWorkspaceSetupStepTwoModal.tsx (2 instances) - HIGH PRIORITY

File: apps/meteor/client/views/admin/workspace/VersionCard/modals/RegisterWorkspaceSetupModal/RegisterWorkspaceSetupStepTwoModal.tsx

Lines 109-110: "Resend" link
Lines 113-114: "change email" link

<Trans i18nKey='RegisterWorkspace_Didnt_Receive_Email'>
    Didn't receive email?{' '}
    <Box is='a' pi={4} onClick={handleResendRegistrationEmail}>
        Resend
    </Box>{' '}
    or{' '}
    <Box is='a' pi={4} onClick={handleBackFromConfirmation}>
        change email
    </Box>
</Trans>

Context: Email verification modal in workspace registration flow
User Impact: HIGH - Blocks admins from completing workspace setup via keyboard


2. WarningModal.tsx (1 instance) - MEDIUM PRIORITY

File: apps/meteor/client/views/admin/ABAC/ABACSettingTab/WarningModal.tsx

Line 38: "ABAC > Rooms" navigation link

<Box is='a' onClick={handleNavigate}>
    {' '}
    ABAC {'>'} Rooms
</Box>

Context: ABAC warning modal with navigation to Rooms tab
User Impact: MEDIUM - Prevents keyboard users from accessing ABAC room management


3. MatrixFederationSearchModalContent.tsx (1 instance) - MEDIUM PRIORITY

File: apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationSearchModalContent.tsx

Line 59: "Manage_server_list" link

<Box is='a' display='flex' flexDirection='row' mbe={16} onClick={manageServers}>
    {t('Manage_server_list')}
</Box>

Context: Matrix federation server management
User Impact: MEDIUM - Blocks keyboard access to federation server configuration


4. useStatusItems.tsx (1 instance) - LOW-MEDIUM PRIORITY

File: apps/meteor/client/navbar/NavBarSettingsToolbar/UserMenu/hooks/useStatusItems.tsx

Line 79: "Learn_more" link

<Box is='a' color='info' onClick={handleStatusDisabledModal}>
    {t('Learn_more')}
</Box>

Context: User status disabled information
User Impact: LOW-MEDIUM - Prevents keyboard users from accessing help information


Steps to Reproduce

  1. Navigate to AdministrationWorkspaceRegistration Setup
  2. Proceed to the email confirmation step (Step 2 of registration)
  3. Try to navigate the modal using only the Tab key (no mouse)
  4. Observe: The "Resend" and "change email" links cannot be focused

Alternative verification with DevTools:

// Run in browser console
document.querySelectorAll('a:not([href])[onclick], a[onclick]:not([href])').forEach((el, i) => {
    console.log(`${i+1}. "${el.textContent.trim()}" - tabIndex: ${el.tabIndex}`);
    el.style.outline = '2px solid red';
});

This will highlight all problematic anchor elements on the page.

Test with screen reader:

  1. Enable NVDA (Windows), VoiceOver (macOS), or ChromeVox
  2. Navigate through the modal with Tab/Arrow keys
  3. Observe: Screen reader does not announce "Resend" and "change email" as interactive

Expected Behavior

  • All interactive elements should be keyboard accessible
  • Tab key should focus the "Resend" and "change email" links
  • Enter or Space key should activate the links
  • Visual focus indicator should appear when focused
  • Screen readers should announce: "Resend, button" or "Resend, link"
  • Elements should follow WCAG 2.1 keyboard interaction patterns

Actual Behavior

  • Links are not focusable with Tab key
  • Keyboard users cannot access this functionality
  • Screen readers do not identify these as interactive elements
  • No visual focus indicator
  • Elements appear as plain text to keyboard users

Impact Assessment

Severity: Medium (High for workspace registration flow)
Affected User Groups:
  • Keyboard-only users (motor impairments, power users)
  • Screen reader users (blind/low-vision users)
  • Voice control users (Dragon NaturallySpeaking, etc.)
  • Switch device users (alternative input devices)
Business Impact:
  • Workspace registration becomes inaccessible to keyboard users
  • Admins cannot resend verification emails without mouse
  • Potential ADA/Section 508/WCAG compliance violations
  • Blocks accessibility certification

WCAG 2.1 Violations

This issue violates the following WCAG 2.1 Level A Success Criteria:

Criterion Level Description
2.1.1 Keyboard A All functionality must be operable through keyboard interface
4.1.2 Name, Role, Value A User interface components must expose name, role, and value to assistive technologies

Proposed Solution

Option 1: Use Button Component (Recommended)
import { Button } from '@rocket.chat/fuselage';

<Trans i18nKey='RegisterWorkspace_Didnt_Receive_Email'>
    Didn't receive email?{' '}
    <Button nude mi={4} onClick={handleResendRegistrationEmail}>
        Resend
    </Button>{' '}
    or{' '}
    <Button nude mi={4} onClick={handleBackFromConfirmation}>
        change email
    </Button>
</Trans>

Pros:

  • Semantic HTML (button element)
  • Keyboard accessible by default
  • Screen reader compatible
  • Follows Fuselage design system
  • Minimal code changes

Option 2: Use Button Element with Box
<Box 
    is='button' 
    type='button' 
    pi={4} 
    onClick={handleResendRegistrationEmail}
    style={{ 
        background: 'none', 
        border: 'none', 
        color: 'inherit', 
        textDecoration: 'underline', 
        cursor: 'pointer',
        padding: 0,
        font: 'inherit'
    }}
>
    Resend
</Box>

Pros:

  • Maintains styling flexibility
  • Semantic HTML
  • Keyboard accessible

Environment

  • Rocket.Chat Version: develop branch (8.2.0-develop)
  • Commit: Latest as of February 20, 2026
  • Browser: All modern browsers (Chrome, Firefox, Safari, Edge)
  • OS: Cross-platform issue (Windows, macOS, Linux)
  • Assistive Technology Impact: NVDA, JAWS, VoiceOver, Dragon NaturallySpeaking

References


Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the five affected instances in RegisterWorkspaceSetupStepTwoModal.tsx, WarningModal.tsx, MatrixFederationSearchModalContent.tsx, and useStatusItems.tsx. Verify each control's keyboard and screen-reader behavior in the relevant modal or menu, then confirm all five interactions are focusable, operable by keyboard, and visibly focused.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
accessibility, frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.