Skip to content

[Accessibility] BtnDisabledDirective fails to block 'Space' keypress, allowing disabled buttons to be triggered #5645

@JohnnyMendesC

Description

@JohnnyMendesC

Describe the bug

The dsBtnDisabled directive (BtnDisabledDirective) is designed to visually disable a button while maintaining its presence in the DOM for screen readers (using aria-disabled="true" instead of the native HTML disabled attribute). The directive correctly stops mouse clicks, but it fails to block the Space key due to an incorrect key value check in the HostListener.

Because of this, any button relying purely on [dsBtnDisabled] (without the native HTML disabled attribute or a Typescript safeguard) can still be triggered by keyboard-only users pressing the Space bar, which could result in unexpected backend requests or errors.

Note: In many existing components across the project (like forms), this bug is currently "silenced" because the component's TypeScript method has its own internal validation check (e.g., if (form.invalid) return;). However, if a button relies solely on the [dsBtnDisabled] directive to block interactions (as seen in PR #5395), the Space bar bypasses the directive and successfully triggers the component's action.

To Reproduce

Steps to reproduce the behavior (using PR #5395 as the scenario):

  1. Navigate to the "Edit Item" -> "Upload" section of an item and reduce it to a single bitstream. The delete button will become visually disabled via [dsBtnDisabled].
Image Image
  1. Using the keyboard, press Tab until the focus is on the visually disabled delete button and press the Space bar.
Image
  1. Behavior: The action is triggered. It attempts to delete the last bitstream, resulting in a 422 Unprocessable Entity error that breaks the UI.
Image

Note: The test spec (disabled-directive.spec.ts) currently passes because it mocks the event with { key: 'Space' }, which masks the real browser behavior.

Expected behavior

When a button uses [dsBtnDisabled], pressing the Space bar should be intercepted and blocked (event.preventDefault() and event.stopImmediatePropagation()), exactly as it works for mouse clicks and the Enter key.

Technical Details & Proposed Fix

In src/app/shared/btn-disabled.directive.ts, the keydown listener checks for the literal string "Space":

if (this.isDisabled && (event.key === 'Enter' || event.key === 'Space')) {

However, standard web browsers return a single space character (" ") for the KeyboardEvent.key property when the space bar is pressed, not the word "Space".

The fix is simply updating the condition to:
if (this.isDisabled && (event.key === 'Enter' || event.key === ' ')) {
And updating the mock event in disabled-directive.spec.ts to { key: ' ' }.

Related work

I discovered this bug while doing accessibility tests during the review of PR #5395.
I plan to submit a Pull Request to fix this directive and its related tests shortly.

Metadata

Metadata

Assignees

Labels

Type

Projects

Status

🏗 In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions