From mateonunez-skills
Reviews UI changes for WCAG 2.1 AA accessibility: keyboard navigation, focus visibility, semantic HTML, ARIA-live regions, reduced motion.
npx claudepluginhub mateonunez/skillsThis skill uses the workspace's default tool permissions.
> The site works for everyone or it doesn't work.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Processes PDFs: extracts text/tables/images, merges/splits/rotates pages, adds watermarks, creates/fills forms, encrypts/decrypts, OCRs scans. Activates on PDF mentions or output requests.
Share bugs, ideas, or general feedback.
The site works for everyone or it doesn't work.
Accessibility regressions ship by default unless someone is looking. After a UI change, run this checklist before declaring it done. The bar is WCAG 2.1 AA — the same bar mateonunez.co is built to.
This is a review skill, not a teaching skill. It assumes you know what aria-live does; it tells you when to look for it.
You just edited:
onClick, onKeyDown, or focus managementtabindex or aria-*Tab in source order.Enter and Space activate buttons; Enter follows links.Escape closes modals, drawers, menus, popovers.Tab can always escape.:focus-visible outline is visible against the background. No outline: none without a replacement.<button>, not <div onClick>. Links are <a href>, not <div onClick>.<h1> per page. Heading levels don't skip (h2 → h4 is wrong).<label for> or wrapping <label>).alt (empty alt="" for decorative; descriptive for content).<ul>/<ol>/<li>, not <div> siblings.aria-label on a button that already has visible text — duplicates the announcement.aria-live="polite" on async status regions (search results count, save indicators).aria-expanded, aria-controls on disclosure widgets.role="dialog" + aria-modal="true" + aria-labelledby on modals.role that contradicts the element (e.g. role="button" on an <a href>).prefers-reduced-motion. Critical motion is gated.aria-live or role="status").<div onClick> — not focusable, not keyboard-activatable, not announced as a button. Use <button>.<a> with href="#" for buttons — use <button>. Reserve <a> for navigation.tabindex > 0 — breaks source-order focus. Almost always wrong.aria-hidden="true" on a focusable element — invisible to AT but reachable by keyboard. Use inert instead, or remove from tab order.<label>.alt="image of a cat" — screen readers already announce "image". Just alt="a cat sleeping".Don't bundle the fixes into an unrelated PR. Note them, prioritise (keyboard > semantics > ARIA polish), and either fix in a separate commit or surface to me as a follow-up. A11y debt is real debt — track it.
If it doesn't hold up for a keyboard-only or screen-reader user, it doesn't make the cut.