-
Notifications
You must be signed in to change notification settings - Fork 0
[A11Y] [Medium] Interactive divs should use semantic elements #9
Copy link
Copy link
Open
Labels
accessibilityWeb accessibility improvements (WCAG compliance)Web accessibility improvements (WCAG compliance)severity-mediumMedium severity issueMedium severity issuewcag-aWCAG Level A complianceWCAG Level A compliance
Description
Accessibility Issue: Interactive Divs Should Use Semantic Elements
WCAG Level: A
Severity: Medium
Category: Keyboard Navigation / Semantic HTML
Issue Description
Several components use <div> elements with click handlers instead of proper semantic elements like <button>. These elements may not be keyboard accessible and lack proper ARIA roles.
User Impact
- Affected Users: Keyboard-only users, screen reader users
- Severity: Users cannot activate certain interactive elements with keyboard
Violations Found
File: components/semiconductor/structure-library.tsx
Lines: 118-141
<div
key={material.id}
className={`group rounded-lg border bg-zinc-900/50 p-3.5 transition-all cursor-pointer hover:border-zinc-600 ${...}`}
onClick={() => onSelect(structureToFile(material), material)}
>
{/* Card content */}
</div>Issue: Interactive card using <div> with onClick - not keyboard accessible
File: components/calculate/file-upload-section.tsx
Lines: 42-59
<div
onDrop={handleDrop}
onDragOver={(e) => e.preventDefault()}
className="group relative cursor-pointer rounded-lg border-2 border-dashed ..."
>
<input
type="file"
...
className="absolute inset-0 cursor-pointer opacity-0"
/>
...
</div>Issue: While the hidden input is accessible, the visual drop zone interaction pattern could be clearer
File: components/semiconductor/defect-generator.tsx
Lines: 133-151
<tr
key={i}
onClick={() => setSelectedAtom(i)}
className={`cursor-pointer border-t border-zinc-800/60 transition-colors hover:bg-zinc-800/40 ...`}
>Issue: Table rows with click handlers - should be selectable via keyboard
Recommended Fix
For clickable cards:
<!-- Option 1: Use button inside card -->
<div className="group rounded-lg border bg-zinc-900/50 p-3.5">
<button
onClick={() => onSelect(structureToFile(material), material)}
className="w-full text-left focus:outline-none focus:ring-2 focus:ring-matrix-green"
aria-pressed={isSelected}
>
{/* Card content */}
</button>
</div>
<!-- Option 2: Make entire div a button -->
<button
className="group rounded-lg border bg-zinc-900/50 p-3.5 text-left w-full focus:outline-none focus:ring-2 focus:ring-matrix-green"
onClick={() => onSelect(structureToFile(material), material)}
aria-pressed={isSelected}
>
{/* Card content */}
</button>For selectable table rows:
<tr
key={i}
onClick={() => setSelectedAtom(i)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
setSelectedAtom(i);
}
}}
tabIndex={0}
role="button"
aria-pressed={selectedAtom === i}
className="cursor-pointer ... focus:outline-none focus:ring-2 focus:ring-inset focus:ring-matrix-green"
>Changes Made:
- Use
<button>instead of<div>for clickable elements - If
<div>must be used, addrole="button",tabIndex={0}, and keyboard handlers - Add
aria-pressedfor toggle-like interactions - Ensure focus styles are visible
Additional Instances
- Category filter pills in
components/semiconductor/structure-library.tsx(these are already buttons - good!) - Expandable sections in
components/calculate/parameter-panel.tsx
Testing Instructions
- Tab through all interactive elements
- Verify all clickable items receive focus
- Press Enter/Space on focused elements
- Verify action is triggered
Resources
Acceptance Criteria
- All interactive elements are keyboard accessible
- Focus indicator visible on all elements
- Enter/Space activates clickable elements
- Proper ARIA roles where semantic elements not used
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
accessibilityWeb accessibility improvements (WCAG compliance)Web accessibility improvements (WCAG compliance)severity-mediumMedium severity issueMedium severity issuewcag-aWCAG Level A complianceWCAG Level A compliance