Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Playground icon-only buttons have no accessible names, and editor tabs cannot be closed from the keyboard

Open
#1,763 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
playwright, react, typescript

Research direction

Start with the named playground components: Header/ActionButton/ActionButton.tsx, Editor/EditorButton.tsx, CloneButton.tsx, ShareButton.tsx, ActionsDropdown.tsx, and Editor/EditorTab.tsx. Then run or inspect the E2E tests in testing/src/specs/playground.spec.ts and the page object in testing/src/pages/playground/index.page.ts. Done means icon buttons have accessible names, the tab close control is keyboard-accessible, and the described role-based checks pass.

Written by the indexing model from the issue text.

Description

Area: Playground Bug Difficulty: Low Priority: Medium

The playground's icon-only buttons have no accessible names, and editor tabs cannot be closed from the keyboard. These buttons render nothing but a lucide icon: Save, Create New Instrument, Share, Download Archive, Upload Archive, Refresh and the actions menu in the header, and View Files, Add File and Upload Files in the editor toolbar. lucide marks its icons aria-hidden="true". The visible label lives only in a Radix tooltip, which sets aria-describedby on the trigger while the tooltip is open; that is a description, not a name. Screen readers announce each of them as "button". Each editor tab is a single <button>, and its close "X" is a plain <div> detected by click target. The X cannot be focused and has no label, and Enter or Space on the tab only selects it, so a keyboard user has no way to close a tab. (The theme and language toggles in the same header are libui components; #1722 covers those.)

Where

apps/playground/src/components/Header/ActionButton/ActionButton.tsx:15-24 (the same pattern is in Editor/EditorButton.tsx:13-21, CloneButton.tsx:40-42, ShareButton.tsx:49-51 and ActionsDropdown.tsx:31-33):

<Tooltip.Trigger
  className="h-9 w-9"
  disabled={disabled}
  size="icon"
  type="button"
  variant="outline"
  onClick={onClick}
>
  {icon}
</Tooltip.Trigger>

apps/playground/src/components/Editor/EditorTab.tsx:25-37:

onClick={(event) => {
  const isClose = xRef.current?.contains(event.target as HTMLElement);
  if (isClose) {
    closeFile(filename);
  } else {
    selectFile(filename);
  }
}}
>
  <span className="leading-non truncate">{filename}</span>
  <div className="rounded-md p-0.5 hover:bg-slate-200 dark:hover:bg-slate-600" ref={xRef}>
    <XIcon style={{ height: '14px', width: '14px' }} />
  </div>

Reproduce

  1. Open the playground with VoiceOver or NVDA running and Tab through the header and the editor toolbar.
  2. Tab to an editor tab and try to close it with the keyboard.

Actual: each icon button is announced as "button" with no name, and no key closes the tab.
Expected: each button is announced by its tooltip text ("Save", "Share", …), and each tab has a focusable close button announced as "Close index.ts".

Tests

E2E in testing/src/specs/playground.spec.ts: assert that page.getByRole('button', { name: 'Save' }) and the other header and toolbar buttons resolve, and that focusing a tab's close button and pressing Enter removes the tab. These role-based locators also give testing/src/pages/playground/index.page.ts a stable way to reach the header actions. There is no pure logic to unit-test.

Suggested fix

Pass the translated tooltip text as aria-label from ActionButton and EditorButton, and add the same to the Create New Instrument and Share triggers and the actions-menu trigger. In EditorTab, render the close control as a sibling <button type="button"> with a translated aria-label (for example Close {filename}), instead of a <div> nested in the tab button.

Dominant language
TypeScript
Stars
119
Forks
19
Avg merge
1d 2h
Merged PRs (30d)
56

Getting set up

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.

More from DouglasNeuroInformatics/OpenDataCapture

All issues in DouglasNeuroInformatics/OpenDataCapture

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.