Skip to content

Fix accessibility: replace div#startStopBtn with <button> in classic design#782

Merged
sstidl merged 2 commits intomasterfrom
copilot/fix-button-accessibility-issue
Apr 13, 2026
Merged

Fix accessibility: replace div#startStopBtn with <button> in classic design#782
sstidl merged 2 commits intomasterfrom
copilot/fix-button-accessibility-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 12, 2026

The start/abort control was a <div onclick="">, making it unreachable via keyboard (Tab) and invisible to screen readers.

Changes

  • HTML: Replaced <div id="startStopBtn" onclick="startStop()"> with <button id="startStopBtn" onclick="startStop()"> across index-classic.html and all affected example pages:

    • example-singleServer-{pretty,modern,progressBar,customSettings,gauges}.html
    • example-multipleServers-{full,pretty}.html
  • CSS: Added padding: 0; font: inherit; to each #startStopBtn rule to neutralize default browser button styles and preserve existing appearance.

<!-- Before -->
<div id="startStopBtn" onclick="startStop()"></div>

<!-- After -->
<button id="startStopBtn" onclick="startStop()"></button>

Copilot AI changed the title [WIP] Fix button accessibility issue by changing div to button Fix accessibility: replace div#startStopBtn with <button> in classic design Apr 12, 2026
Copilot AI requested a review from sstidl April 12, 2026 21:23
@sstidl sstidl marked this pull request as ready for review April 13, 2026 05:39
@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Fix accessibility: replace div#startStopBtn with button element

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Replace non-semantic <div> with <button> element for keyboard accessibility
• Add CSS reset properties to preserve visual appearance
• Update all example pages and main index file consistently
Diagram
flowchart LR
  A["div#startStopBtn<br/>onclick handler"] -->|"Replace with<br/>semantic element"| B["button#startStopBtn<br/>onclick handler"]
  B -->|"Add CSS reset"| C["padding: 0<br/>font: inherit"]
  C -->|"Maintains visual<br/>appearance"| D["Keyboard accessible<br/>Screen reader visible"]
Loading

Grey Divider

File Changes

1. index-classic.html 🐞 Bug fix +3/-1

Convert div to button with CSS reset

• Replaced <div id="startStopBtn"> with <button id="startStopBtn"> element
• Added padding: 0 and font: inherit CSS properties to #startStopBtn rule
• Preserves existing visual styling while enabling keyboard navigation

index-classic.html


2. examples/example-multipleServers-full.html 🐞 Bug fix +3/-1

Convert div to button with CSS reset

• Replaced <div id="startStopBtn"> with <button id="startStopBtn"> element
• Added padding: 0 and font: inherit CSS properties to #startStopBtn rule
• Maintains consistent styling across multiple server example

examples/example-multipleServers-full.html


3. examples/example-multipleServers-pretty.html 🐞 Bug fix +3/-1

Convert div to button with CSS reset

• Replaced <div id="startStopBtn"> with <button id="startStopBtn"> element
• Added padding: 0 and font: inherit CSS properties to #startStopBtn rule
• Ensures accessibility in pretty layout variant

examples/example-multipleServers-pretty.html


View more (5)
4. examples/example-singleServer-customSettings.html 🐞 Bug fix +3/-1

Convert div to button with CSS reset

• Replaced <div id="startStopBtn"> with <button id="startStopBtn"> element
• Added padding: 0 and font: inherit CSS properties to #startStopBtn rule
• Improves keyboard accessibility in custom settings example

examples/example-singleServer-customSettings.html


5. examples/example-singleServer-gauges.html 🐞 Bug fix +3/-1

Convert div to button with CSS reset

• Replaced <div id="startStopBtn"> with <button id="startStopBtn"> element
• Added padding: 0 and font: inherit CSS properties to #startStopBtn rule
• Enables keyboard navigation in gauges example

examples/example-singleServer-gauges.html


6. examples/example-singleServer-modern.html 🐞 Bug fix +3/-1

Convert div to button with CSS reset

• Replaced <div id="startStopBtn"> with <button id="startStopBtn"> element
• Added padding: 0 and font: inherit CSS properties to #startStopBtn rule
• Maintains modern design appearance with improved accessibility

examples/example-singleServer-modern.html


7. examples/example-singleServer-pretty.html 🐞 Bug fix +3/-1

Convert div to button with CSS reset

• Replaced <div id="startStopBtn"> with <button id="startStopBtn"> element
• Added padding: 0 and font: inherit CSS properties to #startStopBtn rule
• Ensures consistent accessibility across single server examples

examples/example-singleServer-pretty.html


8. examples/example-singleServer-progressBar.html 🐞 Bug fix +3/-1

Convert div to button with CSS reset

• Replaced <div id="startStopBtn"> with <button id="startStopBtn"> element
• Added padding: 0 and font: inherit CSS properties to #startStopBtn rule
• Improves keyboard accessibility in progress bar example

examples/example-singleServer-progressBar.html


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

qodo-free-for-open-source-projects bot commented Apr 13, 2026

Code Review by Qodo

🐞 Bugs (1)   📘 Rule violations (0)   📎 Requirement gaps (0)   🖥 UI issues (0)   🎨 UX Issues (0)
🐞\ ≡ Correctness (1)

Grey Divider


Action required

1. Button lacks accessible name 🐞
Description
The new <button id="startStopBtn"> elements are empty and rely on CSS #startStopBtn:before /
.running:before to render “Start/Abort”, which does not provide an accessible name to assistive
technologies. Screen readers will announce an unnamed button, and the control’s state (Start vs
Abort) is not exposed via an accessible label across index-classic.html and all updated example
pages.
Code

index-classic.html[495]

+		<button id="startStopBtn" onclick="startStop()"></button><br />
Evidence
index-classic.html renders the control as an empty <button> and shows the label via CSS
:before content, while startStop() only toggles the running class and never sets a text label
or ARIA attributes. The same empty-button + CSS-generated label pattern exists in the modified
example pages as well, so the accessible name is missing everywhere this PR changed the element
type.

index-classic.html[494-496]
index-classic.html[277-283]
index-classic.html[132-167]
examples/example-singleServer-pretty.html[159-160]
examples/example-singleServer-pretty.html[87-92]
Best Practice: W3C AccName (Accessible Name and Description Computation)

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`#startStopBtn` is now a real `<button>`, but it has no accessible name because the visible “Start/Abort” text is injected via CSS `:before`. Screen readers will announce an unnamed button and won’t know whether it starts or aborts the test.

## Issue Context
Across `index-classic.html` and the example pages, the label is currently implemented via:
- `#startStopBtn:before { content: "Start" }`
- `#startStopBtn.running:before { content: "Abort" }`

JavaScript toggles the `running` class but never updates any accessible label/state.

## Fix approach
Prefer one of these:
1) **Recommended:** Put real text in the button and update it from JS (and remove/ignore the CSS `:before` content), OR
2) Keep the CSS visual label but add and maintain **`aria-label`** (and optionally `aria-pressed`) in JS whenever `running` is toggled.

### Minimal change (works with existing CSS)
- In HTML, initialize:
 - `aria-label="Start"` (and optionally `aria-pressed="false"`)
- In JS, whenever setting `className = "running"`:
 - set `aria-label` to `"Abort"` (and `aria-pressed="true"`)
- Whenever clearing `className` (abort/end):
 - set `aria-label` to `"Start"` (and `aria-pressed="false"`)

## Fix Focus Areas
- index-classic.html[132-167]
- index-classic.html[277-283]
- index-classic.html[494-496]
- examples/example-multipleServers-full.html[123-160]
- examples/example-multipleServers-full.html[407-408]
- examples/example-multipleServers-pretty.html[33-87]
- examples/example-multipleServers-pretty.html[210-210]
- examples/example-singleServer-customSettings.html[19-39]
- examples/example-singleServer-customSettings.html[156-156]
- examples/example-singleServer-gauges.html[55-76]
- examples/example-singleServer-gauges.html[228-228]
- examples/example-singleServer-modern.html[17-65]
- examples/example-singleServer-modern.html[193-193]
- examples/example-singleServer-pretty.html[20-36]
- examples/example-singleServer-pretty.html[159-160]
- examples/example-singleServer-progressBar.html[11-38]
- examples/example-singleServer-progressBar.html[178-178]ক্রান্ত

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@sstidl sstidl merged commit da29334 into master Apr 13, 2026
1 check passed
@sstidl sstidl deleted the copilot/fix-button-accessibility-issue branch April 13, 2026 05:40
</div>
<div id="testWrapper" class="hidden">
<div id="startStopBtn" onclick="startStop()"></div><br />
<button id="startStopBtn" onclick="startStop()"></button><br />
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.

Action required

1. Button lacks accessible name 🐞 Bug ≡ Correctness

The new <button id="startStopBtn"> elements are empty and rely on CSS #startStopBtn:before /
.running:before to render “Start/Abort”, which does not provide an accessible name to assistive
technologies. Screen readers will announce an unnamed button, and the control’s state (Start vs
Abort) is not exposed via an accessible label across index-classic.html and all updated example
pages.
Agent Prompt
## Issue description
`#startStopBtn` is now a real `<button>`, but it has no accessible name because the visible “Start/Abort” text is injected via CSS `:before`. Screen readers will announce an unnamed button and won’t know whether it starts or aborts the test.

## Issue Context
Across `index-classic.html` and the example pages, the label is currently implemented via:
- `#startStopBtn:before { content: "Start" }`
- `#startStopBtn.running:before { content: "Abort" }`

JavaScript toggles the `running` class but never updates any accessible label/state.

## Fix approach
Prefer one of these:
1) **Recommended:** Put real text in the button and update it from JS (and remove/ignore the CSS `:before` content), OR
2) Keep the CSS visual label but add and maintain **`aria-label`** (and optionally `aria-pressed`) in JS whenever `running` is toggled.

### Minimal change (works with existing CSS)
- In HTML, initialize:
  - `aria-label="Start"` (and optionally `aria-pressed="false"`)
- In JS, whenever setting `className = "running"`:
  - set `aria-label` to `"Abort"` (and `aria-pressed="true"`)
- Whenever clearing `className` (abort/end):
  - set `aria-label` to `"Start"` (and `aria-pressed="false"`)

## Fix Focus Areas
- index-classic.html[132-167]
- index-classic.html[277-283]
- index-classic.html[494-496]
- examples/example-multipleServers-full.html[123-160]
- examples/example-multipleServers-full.html[407-408]
- examples/example-multipleServers-pretty.html[33-87]
- examples/example-multipleServers-pretty.html[210-210]
- examples/example-singleServer-customSettings.html[19-39]
- examples/example-singleServer-customSettings.html[156-156]
- examples/example-singleServer-gauges.html[55-76]
- examples/example-singleServer-gauges.html[228-228]
- examples/example-singleServer-modern.html[17-65]
- examples/example-singleServer-modern.html[193-193]
- examples/example-singleServer-pretty.html[20-36]
- examples/example-singleServer-pretty.html[159-160]
- examples/example-singleServer-progressBar.html[11-38]
- examples/example-singleServer-progressBar.html[178-178]ক্রান্ত

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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.

Accessibility: the "start/abort" button should actually be a button and not a div

2 participants