$npx -y skills add ibelick/ui-skills --skill fixing-accessibilityAudit and fix HTML accessibility issues including ARIA labels, keyboard navigation, focus management, color contrast, and form errors. Use when adding interactive controls, forms, dialogs, or reviewing WCAG compliance.
| 1 | # fixing-accessibility |
| 2 | |
| 3 | Fix accessibility issues. |
| 4 | |
| 5 | ## how to use |
| 6 | |
| 7 | - `/fixing-accessibility` |
| 8 | Apply these constraints to any UI work in this conversation. |
| 9 | |
| 10 | - `/fixing-accessibility <file>` |
| 11 | Review the file against all rules below and report: |
| 12 | - violations (quote the exact line or snippet) |
| 13 | - why it matters (one short sentence) |
| 14 | - a concrete fix (code-level suggestion) |
| 15 | |
| 16 | Do not rewrite large parts of the UI. Prefer minimal, targeted fixes. |
| 17 | |
| 18 | ## when to apply |
| 19 | |
| 20 | Reference these guidelines when: |
| 21 | - adding or changing buttons, links, inputs, menus, dialogs, tabs, dropdowns |
| 22 | - building forms, validation, error states, helper text |
| 23 | - implementing keyboard shortcuts or custom interactions |
| 24 | - working on focus states, focus trapping, or modal behavior |
| 25 | - rendering icon-only controls |
| 26 | - adding hover-only interactions or hidden content |
| 27 | |
| 28 | ## rule categories by priority |
| 29 | |
| 30 | | priority | category | impact | |
| 31 | |----------|----------|--------| |
| 32 | | 1 | accessible names | critical | |
| 33 | | 2 | keyboard access | critical | |
| 34 | | 3 | focus and dialogs | critical | |
| 35 | | 4 | semantics | high | |
| 36 | | 5 | forms and errors | high | |
| 37 | | 6 | announcements | medium-high | |
| 38 | | 7 | contrast and states | medium | |
| 39 | | 8 | media and motion | low-medium | |
| 40 | | 9 | tool boundaries | critical | |
| 41 | |
| 42 | ## quick reference |
| 43 | |
| 44 | ### 1. accessible names (critical) |
| 45 | |
| 46 | - every interactive control must have an accessible name |
| 47 | - icon-only buttons must have aria-label or aria-labelledby |
| 48 | - every input, select, and textarea must be labeled |
| 49 | - links must have meaningful text (no “click here”) |
| 50 | - decorative icons must be aria-hidden |
| 51 | |
| 52 | ### 2. keyboard access (critical) |
| 53 | |
| 54 | - do not use div or span as buttons without full keyboard support |
| 55 | - all interactive elements must be reachable by Tab |
| 56 | - focus must be visible for keyboard users |
| 57 | - do not use tabindex greater than 0 |
| 58 | - Escape must close dialogs or overlays when applicable |
| 59 | |
| 60 | ### 3. focus and dialogs (critical) |
| 61 | |
| 62 | - modals must trap focus while open |
| 63 | - restore focus to the trigger on close |
| 64 | - set initial focus inside dialogs |
| 65 | - opening a dialog should not scroll the page unexpectedly |
| 66 | |
| 67 | ### 4. semantics (high) |
| 68 | |
| 69 | - prefer native elements (button, a, input) over role-based hacks |
| 70 | - if a role is used, required aria attributes must be present |
| 71 | - lists must use ul or ol with li |
| 72 | - do not skip heading levels |
| 73 | - tables must use th for headers when applicable |
| 74 | |
| 75 | ### 5. forms and errors (high) |
| 76 | |
| 77 | - errors must be linked to fields using aria-describedby |
| 78 | - required fields must be announced |
| 79 | - invalid fields must set aria-invalid |
| 80 | - helper text must be associated with inputs |
| 81 | - disabled submit actions must explain why |
| 82 | |
| 83 | ### 6. announcements (medium-high) |
| 84 | |
| 85 | - critical form errors should use aria-live |
| 86 | - loading states should use aria-busy or status text |
| 87 | - toasts must not be the only way to convey critical information |
| 88 | - expandable controls must use aria-expanded and aria-controls |
| 89 | |
| 90 | ### 7. contrast and states (medium) |
| 91 | |
| 92 | - ensure sufficient contrast for text and icons |
| 93 | - hover-only interactions must have keyboard equivalents |
| 94 | - disabled states must not rely on color alone |
| 95 | - do not remove focus outlines without a visible replacement |
| 96 | |
| 97 | ### 8. media and motion (low-medium) |
| 98 | |
| 99 | - images must have correct alt text (meaningful or empty) |
| 100 | - videos with speech should provide captions when relevant |
| 101 | - respect prefers-reduced-motion for non-essential motion |
| 102 | - avoid autoplaying media with sound |
| 103 | |
| 104 | ### 9. tool boundaries (critical) |
| 105 | |
| 106 | - prefer minimal changes, do not refactor unrelated code |
| 107 | - do not add aria when native semantics already solve the problem |
| 108 | - do not migrate UI libraries unless requested |
| 109 | |
| 110 | ## common fixes |
| 111 | |
| 112 | ```html |
| 113 | <!-- icon-only button: add aria-label --> |
| 114 | <!-- before --> <button><svg>...</svg></button> |
| 115 | <!-- after --> <button aria-label="Close"><svg aria-hidden="true">...</svg></button> |
| 116 | |
| 117 | <!-- div as button: use native element --> |
| 118 | <!-- before --> <div onclick="save()">Save</div> |
| 119 | <!-- after --> <button onclick="save()">Save</button> |
| 120 | |
| 121 | <!-- form error: link with aria-describedby --> |
| 122 | <!-- before --> <input id="email" /> <span>Invalid email</span> |
| 123 | <!-- after --> <input id="email" aria-describedby="email-err" aria-invalid="true" /> <span id="email-err">Invalid email</span> |
| 124 | ``` |
| 125 | |
| 126 | ## review guidance |
| 127 | |
| 128 | - fix critical issues first (names, keyboard, focus, tool boundaries) |
| 129 | - prefer native HTML before adding aria |
| 130 | - quote the exact snippet, state the failure, propose a small fix |
| 131 | - for complex widgets (menu, dialog, combobox), prefer established accessible primitives over custom behavior |