Playground icon-only buttons have no accessible names, and editor tabs cannot be closed from the keyboard
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
- Domain
- accessibility, frontend, testing
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
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
- Open the playground with VoiceOver or NVDA running and Tab through the header and the editor toolbar.
- 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
- Ships a Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from DouglasNeuroInformatics/OpenDataCapture
-
Area: Playground Bug Difficulty: Low Good First Issue Priority: Low
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
DouglasNeuroInformatics/OpenDataCapture#1805 ·
Maintainers usually reply within 1 day
-
Area: Instruments Bug Difficulty: Low Priority: Low
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
DouglasNeuroInformatics/OpenDataCapture#1801 ·
Maintainers usually reply within 1 day
-
Area: Instruments Bug Difficulty: Low Good First Issue Priority: Low
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
DouglasNeuroInformatics/OpenDataCapture#1800 ·
Maintainers usually reply within 1 day
-
Area: Instruments Bug Difficulty: Low Good First Issue Priority: Low
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
DouglasNeuroInformatics/OpenDataCapture#1799 ·
Maintainers usually reply within 1 day
-
Area: Instruments Bug Difficulty: Low Performance Priority: Medium
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
DouglasNeuroInformatics/OpenDataCapture#1795 ·
Maintainers usually reply within 1 day
All issues in DouglasNeuroInformatics/OpenDataCapture
Similar issues
-
A hung CI job runs for 6 hours before it is cancelledPossibly taken @Olanetsoft claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Olanetsoft/agent-lookout#110 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
thedotmack/claude-mem#4757 ·
Maintainers usually reply within 1 day
-
🐛 bug 🗺️ MCP OAuth
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
LibreChat-AI/LibreChat#17077 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 75/100