Skip to content

FE: Add aria-hidden to decorative SVG icons (#1099)#1120

Merged
Chris0Jeky merged 4 commits into
mainfrom
fix/1099-decorative-svg-aria-hidden
May 29, 2026
Merged

FE: Add aria-hidden to decorative SVG icons (#1099)#1120
Chris0Jeky merged 4 commits into
mainfrom
fix/1099-decorative-svg-aria-hidden

Conversation

@Chris0Jeky
Copy link
Copy Markdown
Owner

Resolves #1099.

Summary

Audited every inline <svg> in src/components and src/views, then added aria-hidden="true" to decorative icons that lacked both aria-hidden and a role. Applied per-SVG judgment (not a bulk edit). SVGs already handled (existing aria-hidden, role="img", dynamic v-bind a11y, or an aria-hidden wrapper parent) were left untouched.

Decorative SVGs hidden (16 total)

  • board/BoardCanvas.vue — empty-state icon next to "No columns yet" text
  • board/BoardSettingsModal.vue — close icon (see labelled controls below)
  • board/BoardToolbar.vue — 5 icons: back (button has aria-label), filter / keyboard-help / settings (buttons have title), labels / starter-packs (button has title + visible text)
  • board/CardItem.vue — 4 icons: drag handle + move-menu (buttons have aria-label), blocked badge (next to "Blocked" text), due-date (next to date text)
  • board/CardModalHeader.vue — close icon (see labelled controls below)
  • board/ColumnEditModal.vue — close icon (see labelled controls below)
  • board/ColumnLane.vue — drag handle (aria-label) + edit (title) icons
  • board/FilterPanel.vue — filter heading icon (next to "Filter Cards"), close icon (button has aria-label) — the original PR Add aria-labels to filter clear buttons in FilterPanel #1098 finding
  • board/LabelManagerModal.vue — close icon (see below), edit + delete icons (buttons have title), "Create New Label" icon (next to text)
  • board/StarterPackCatalogModal.vue — close icon (see labelled controls below)
  • KeyboardShortcutsHelp.vue — close icon (button has aria-label)
  • common/SessionTimeoutWarning.vue — dismiss/close icon (button has aria-label)
  • common/ToastContainer.vue — close icon (button has aria-label)
  • views/BoardsListView.vue — empty-state icon next to "No boards" text

Icon-only controls given a parent aria-label (5)

These close buttons had NO accessible name and the SVG was their sole content. Hiding the SVG alone would have left the control unlabelled, so I added an aria-label to the parent button and aria-hidden="true" to the icon:

  • board/BoardSettingsModal.vuearia-label="Close board settings"
  • board/CardModalHeader.vuearia-label="Close card editor"
  • board/ColumnEditModal.vuearia-label="Close column editor"
  • board/LabelManagerModal.vuearia-label="Close label manager"
  • board/StarterPackCatalogModal.vuearia-label="Close starter packs"

Intentionally left untouched

  • common/SessionTimeoutWarning.vue:27 and common/ToastContainer.vue:19/31/43/55 — icons already inside an aria-hidden="true" wrapper <div> (parent handles it)
  • ui/TdSelect.vue:46 — icon inside an aria-hidden="true" wrapper <span>
  • ui/TdSpinner.vue, paper/PaperConfidenceDial.vue, views/.../TodayCadence.vue — already have aria-hidden / role="img" + aria-label (multiline attrs)
  • paper/PaperIcon.vue — dynamically binds aria-hidden or role="img"+aria-label via v-bind
  • LoginView.vue, ProfileSettingsView.vue, inbox panels, TdTag/TdToast/TdInlineAlert — already carry aria-hidden

Verification

  • npm run typecheck — clean
  • npx eslint <14 changed files> — clean (vuejs-accessibility rules enforced)
  • npx vitest --run for all 14 related specs — 199 passed

Label icon-only close buttons in BoardSettingsModal, CardModalHeader, ColumnEditModal, LabelManagerModal, StarterPackCatalogModal that lacked an accessible name.
Copilot AI review requested due to automatic review settings May 29, 2026 20:24
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves accessibility across several Vue components by adding aria-hidden="true" to decorative SVGs and introducing explicit aria-label attributes to close buttons. However, several buttons that contain these hidden SVGs rely solely on title attributes for screen readers, which is not a reliable method for providing accessible names. It is recommended to add explicit aria-label attributes to these buttons (such as the filter, keyboard shortcuts, board settings, edit column, and label action buttons) to ensure proper assistive technology support.

title="Filter Cards (Press f)"
>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the SVG is now marked as aria-hidden="true", this button will have no accessible text content for screen readers when filteredCardCount >= totalCardCount (since the filter count span is conditionally rendered). While the button has a title attribute, title is not a reliable accessible name across all assistive technologies and devices (especially touch screens). It is highly recommended to add an explicit aria-label="Filter Cards" to the parent <button> element, similar to how the close buttons were updated in this PR.

title="Keyboard Shortcuts (Press ?)"
>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the SVG is now marked as aria-hidden="true", this button has no accessible text content for screen readers. While the button has a title attribute, title is not a reliable accessible name across all assistive technologies and devices. It is highly recommended to add an explicit aria-label="Keyboard Shortcuts" to the parent <button> element.

title="Board Settings"
>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the SVG is now marked as aria-hidden="true", this button has no accessible text content for screen readers. While the button has a title attribute, title is not a reliable accessible name across all assistive technologies and devices. It is highly recommended to add an explicit aria-label="Board Settings" to the parent <button> element.

title="Edit Column"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the SVG is now marked as aria-hidden="true", this button has no accessible text content for screen readers. While the button has a title attribute, title is not a reliable accessible name across all assistive technologies and devices. It is highly recommended to add an explicit aria-label="Edit Column" to the parent <button> element.

title="Edit"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the SVG is now marked as aria-hidden="true", this button has no accessible text content for screen readers. While the button has a title attribute, title is not a reliable accessible name across all assistive technologies and devices. It is highly recommended to add an explicit aria-label="Edit label" to the parent <button> element.

title="Delete"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the SVG is now marked as aria-hidden="true", this button has no accessible text content for screen readers. While the button has a title attribute, title is not a reliable accessible name across all assistive technologies and devices. It is highly recommended to add an explicit aria-label="Delete label" to the parent <button> element.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@Chris0Jeky
Copy link
Copy Markdown
Owner Author

Adversarial reviews (2 independent) + Fix Evidence — PR #1120

Review 1 (self): confirmed the diff is accessibility-only; 16 decorative icons hidden, 5 close buttons given accurate aria-labels; typecheck/lint clean, 199 specs pass.

Review 2 (independent): verified each hidden icon is decorative (blocked/due-date/drag/nav/empty-state icons all have sibling text or a parent label — correctly hidden) and the 5 close-button labels are accurate and needed. It found 5 real regressions: icon-only buttons whose only content was the now-hidden SVG and that had no aria-label (only an unreliable title), leaving them with no accessible name (WCAG 4.1.2):

  • ColumnLane edit-column button (C-1)
  • BoardToolbar filter / keyboard-shortcuts / board-settings buttons (C-2 ×3)
  • LabelManagerModal per-label edit / delete buttons (I-1 ×2)

Fixes (commit add aria-label to icon-only buttons whose sole SVG was hidden)

  • ColumnLane edit button → aria-label="Edit Column"
  • BoardToolbar → aria-label="Filter Cards" / "Keyboard Shortcuts" / "Board Settings"
  • LabelManagerModal edit/delete → :aria-label="\" and Delete label … (also identifies which label — addresses the reviewer's secondary point)

Verification: vue-tsc -b clean; eslint clean on the 3 files; BoardToolbar/ColumnLane/LabelManagerModal specs 54/54 pass. All findings (CRITICAL + IMPORTANT) addressed.

Note: the failing API Integration (backend) check is unrelated to this frontend-only diff (flaky/infra) — re-running.

@Chris0Jeky
Copy link
Copy Markdown
Owner Author

CI note — E2E Smoke flake (investigated, re-running)

The E2E Smoke check failed on 1 of 152 tests: multi-board.spec.ts line 197 expect(restoredBoard).toBeVisible({ timeout: 10_000 }) timed out after clicking Restore Board. Investigated rather than assumed flaky:

  • The failing assertion is in the board archive→restore flow — a path this PR never touches (changes are decorative-SVG aria-hidden + aria-label on filter/keyboard/settings/edit/delete/close buttons).
  • The one selector my change could affect — Board Settings — is selected by button[title="Board Settings"] (lines 159/178); I kept the title and only added aria-label, so that locator still matches (verified).
  • The CI server log shows a transient DB connection error (error … using the connection to database 'main'), and E2E Smoke has flaked intermittently across this session.

Re-running the failed E2E job. No code change warranted.

@Chris0Jeky Chris0Jeky merged commit 52ac488 into main May 29, 2026
43 of 44 checks passed
@github-project-automation github-project-automation Bot moved this from Pending to Done in Taskdeck Execution May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Add aria-hidden to decorative SVG icons across frontend components

2 participants