Skip to content

fix(a11y): WCAG 2.1 accessibility improvements across Icon component and demo#4

Open
yacosta738 wants to merge 32 commits into
twodft:mainfrom
dallay:fix/accessibility-wcag-improvements
Open

fix(a11y): WCAG 2.1 accessibility improvements across Icon component and demo#4
yacosta738 wants to merge 32 commits into
twodft:mainfrom
dallay:fix/accessibility-wcag-improvements

Conversation

@yacosta738
Copy link
Copy Markdown

Summary

This PR fixes several WCAG 2.1 accessibility violations found in the Icon component and the demo pages. Changes are grouped into three focused commits for easier review.


Issues Fixed

packages/core/components/Icon.astro — Critical

Issue WCAG Criterion Fix
_id variable used in template but computed as _id<symbol> and <use> referenced an undefined id Bug Renamed _idid, _normalizedBodynormalizedBody
Decorative SVGs announced by screen readers without a name 1.1.1 (A) Added aria-hidden="true" when no title prop is provided
Meaningful icons had no accessible role 4.1.2 (A) Added role="img" when title prop is provided
SVGs focusable in IE/Edge and some Chromium builds 2.1.1 (A) Added focusable="false" unconditionally

demo/src/layouts/base.astro — Serious

Issue WCAG Criterion Fix
No <main> landmark — AT users couldn't navigate to main content 1.3.6, 2.4.1 (A) Wrapped <slot /> in <main id="main-content" tabindex="-1">
No skip link — keyboard users must tab through all repeated content 2.4.1 (A) Added visible-on-focus skip link targeting #main-content
No <meta name="description"> Added page description

demo/src/pages/index.astro and map.astro — Moderate

Issue WCAG Criterion Fix
Standalone icons used without title — invisible to AT 1.1.1 (A) Added title prop to each meaningful icon
_icon variable shadowed — runtime reference would fail Bug Renamed _iconicon
Star icons rendered as flat list — group meaning lost 1.1.1, 1.3.1 (A) Wrapped in <figure aria-label="Rating: 4 out of 5 stars"> + visually-hidden <figcaption>
No explicit imports Added explicit import statements for Base and Icon

How to Verify

Keyboard

  • Tab through both pages — focus should never be trapped or lost
  • Activate the skip link (Tab once then Enter) — focus moves to <main>

Screen reader (VoiceOver / NVDA)

  • Decorative icons must not be announced
  • Icons with title must be announced as "<title text>, image"
  • Star rating group must read "Rating: 4 out of 5 stars" (or equivalent)

Automated

# From repo root
npx @axe-core/cli http://localhost:4321 --exit
npx pa11y http://localhost:4321 --reporter cli

WCAG References


Accessibility review:

  • Semantics/roles/names: ✅ Fixed — role="img" + title for meaningful icons; aria-hidden for decorative
  • Keyboard & focus: ✅ Fixed — skip link + <main> landmark; focusable="false" on SVGs
  • Announcements (async/route): N/A for this PR
  • Contrast/visual focus: ✅ No regressions — skip link has sufficient contrast on focus
  • Forms/errors/help: N/A for this PR
  • WCAG 2.2 (target size, dragging, focus obscured, auth): N/A for this PR

yacosta738 and others added 30 commits May 15, 2026 15:53
- Add release-please-config.json for packages/core (@dallay/astro-icon)
- Add .release-please-manifest.json with current version 1.2.4
- Add release-please.yml workflow: auto PR on push to main, publish to npm on release
- Convert release.yml to manual fallback with explicit confirmation guard
- Remove .changeset directory and @changesets/* dependencies
- Remove changeset version script from root package.json
- devalue >= 5.8.1 (DoS via sparse array)
- fast-uri >= 3.1.2 (host confusion + path traversal)
- minimatch >= 10.2.3 (ReDoS, 3 CVEs)
- path-to-regexp >= 6.3.0 (backtracking ReDoS)
- undici@<6 >= 5.29.0 (DoS, smuggling, CRLF)
- ajv >= 8.18.0 (ReDoS via $data)
- smol-toml >= 1.6.1 (DoS via nested TOML)
…ponents--@dallay/astro-icon

chore: release @dallay/astro-icon 1.3.0
- Replace prettier with @biomejs/biome ^2.4.15
- Add biome.json with formatter, linter, and files.includes config (Biome v2)
- Update package.json scripts: lint, lint:fix, format
- Rewrite CI lint job: drop wearerequired/lint-action, use native biome + git auto-fix steps
Run biome check --write and --unsafe to auto-correct formatting and safe lint issues
Added a security policy document outlining supported versions and vulnerability reporting.

Signed-off-by: Yuniel Acosta Pérez <33158051+yacosta738@users.noreply.github.com>
…dates (#4)

Bumps the npm_and_yarn group with 2 updates in the / directory: [postcss](https://github.com/postcss/postcss) and [yaml](https://github.com/eemeli/yaml).


Updates `postcss` from 8.5.8 to 8.5.14
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](postcss/postcss@8.5.8...8.5.14)

Updates `yaml` from 2.7.1 to 2.9.0
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](eemeli/yaml@v2.7.1...v2.9.0)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.14
  dependency-type: indirect
- dependency-name: yaml
  dependency-version: 2.9.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Add .vercel to packages/www/.gitignore to prevent Vercel deployment artifacts from being committed. Keeps repository clean of environment-specific deployment metadata.
Co-authored-by: dallay-bot[bot] <172063952+dallay-bot[bot]@users.noreply.github.com>
- Rename _id to id so symbol/use references resolve correctly (bug fix)
- Rename _normalizedBody to normalizedBody to match template usage (bug fix)
- Add focusable='false' to prevent SVGs from being keyboard-focusable
  in IE/Edge and some Chromium builds (WCAG 2.1.1)
- Decorative icons (no title prop) receive aria-hidden='true' so
  assistive technologies skip them (WCAG 1.1.1)
- Meaningful icons (with title prop) receive role='img' so screen
  readers expose the title as the accessible name (WCAG 4.1.2)
- Associate desc element with a stable id for future aria-describedby
  wiring (WCAG 1.1.1)
…se layout

- Wrap slot in <main id='main-content'> to provide a navigation
  landmark that keyboard and AT users can target (WCAG 1.3.6, 2.4.1)
- Add skip link that becomes visible on focus so keyboard users can
  bypass repeated header content (WCAG 2.4.1 - Level A)
- Add meta description for better AT context and SEO
- Skip link uses tabindex='-1' on <main> to allow programmatic focus
  without disrupting natural tab order
…cs in demo pages

- Add explicit imports for Base layout and Icon component to replace
  implicit globals; makes component contracts clear and auditable
- Fix variable name: _icon -> icon so the runtime reference resolves
- Add title prop to standalone icons so they are exposed as role='img'
  with an accessible name to screen readers (WCAG 1.1.1)
- Wrap star icons in <figure aria-label='Rating: 4 out of 5 stars'>
  with a visually-hidden <figcaption> so the group meaning is
  communicated to AT users (WCAG 1.1.1, 1.3.1)
- Add .visually-hidden utility class following the standard SR-only
  clip pattern
actions/checkout on pull_request events checks out the merge commit,
leaving the runner in detached HEAD state. A plain 'git push' then
fails with exit 128 because there is no active branch to push to.

Fix: use 'git push origin HEAD:${HEAD_REF}' when github.head_ref is
set (PR context), falling back to plain 'git push' on direct pushes
to main where HEAD is always attached.
- Add biome-ignore on normalizedBody variable (used in Astro template,
  outside Biome JS scope) to prevent false unused-variable warning
- Apply biome import order: sort imports alphabetically in demo pages
- Apply biome ternary formatting in Icon.astro (cosmetic only)
- Use --force-with-lease on push to guard against concurrent pushes
  while still protecting against accidental overwrite of others' work
- Icon.astro: add aria-describedby to normalizedProps when desc is
  provided and icon is meaningful, binding <svg> to its <desc id>
  (WCAG 1.1.1 / 4.1.2)
- map.astro: remove per-star title props so each icon is decorative;
  the <figure aria-label> and <figcaption> carry the collective meaning
  and screen readers no longer announce each star separately
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.

1 participant