Claude Cursor GitHub Copilot Skill

html-semantics-accessibility-review

Review HTML markup and rendered DOM structure for correct native-element usage, valid heading/landmark hierarchy, and WAI-ARIA APG-conformant custom-widget patterns; produce a WCAG 2.2-grounded verdict with APG pattern citations for every custom interactive control, flagging anyt

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download vincentchuwaichow-vanguard-frontier-agentic-skills_frontend_html-semantics-accessibility-review-febe32a.zip · 10 KB
Part of vincentchuwaichow/vanguard-frontier-agentic — 293 skills

Install

skills CLI npx skills add https://github.com/VincentChuWaiChow/vanguard-frontier-agentic/tree/master/skills/frontend/html-semantics-accessibility-review
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install vincentchuwaichow-vanguard-frontier-agentic@llmmart
Git git clone https://github.com/VincentChuWaiChow/vanguard-frontier-agentic.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole vincentchuwaichow/vanguard-frontier-agentic collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

HTML Semantics & Accessibility Review

Purpose

Automated a11y linters (axe, Lighthouse) catch roughly 30-50% of WCAG issues by design — they cannot verify whether a custom widget's keyboard interaction matches its intended pattern, whether ARIA correctly reflects (or wrongly overrides) native semantics, or whether a heading/landmark outline actually helps a screen-reader user navigate. This skill performs the manual, spec-grounded review that closes that gap: matching every custom interactive element against a specific WAI-ARIA APG pattern, verifying heading/landmark structure, and catching redundant or conflicting ARIA before it ships.

When to use

Use this skill when the user asks to:

  • review a pull request or component for HTML semantics or accessibility correctness,
  • verify a custom widget (modal, dropdown, tabs, combobox, accordion, etc.) against WAI-ARIA APG patterns,
  • audit heading level and landmark structure on a page or component tree,
  • check whether ARIA roles/states/properties are correctly applied or redundant/conflicting with native semantics,
  • assess WCAG 2.2 conformance risk for markup changes ahead of a compliance audit.

Context7 Documentation Protocol

Element semantics, implicit ARIA-role mappings, and attribute-support tables change as the HTML and ARIA specs evolve — never assert them from memory.

  1. Call ToolSearch with query "context7" (or "select:mcp__Context7__resolve-library-id,mcp__Context7__query-docs") to load the Context7 tools if they are not already loaded in this session.
  2. Call mcp__Context7__resolve-library-id for the relevant documentation set — for this skill that is almost always MDN (/mdn/content, or /websites/developer_mozilla_en-us if the former lacks coverage for the query). Resolve the WAI-ARIA APG or WCAG spec source too if the review needs primary-spec wording rather than MDN's paraphrase.
  3. Call mcp__Context7__query-docs for the specific element, role, or attribute in question — e.g. "implicit ARIA role for <nav>", "APG combobox keyboard pattern", "tabindex focus-order behavior" — before ruling on it. Do this per review, not once from memory of a prior session.
  4. Prefer the official spec/MDN wording over this skill's own paraphrase when the two could be read to disagree; cite the resolved doc URL in the finding.
  5. If Context7 is unavailable or returns no relevant match, fall back to the URLs in official_docs / references/apg-pattern-index.md, and explicitly mark the claim documentation-based (Context7 unavailable) rather than presenting it as freshly verified.
  6. Never invent an ARIA role, state, property, or implicit-semantics mapping that no queried source confirms.

Lean operating rules

  • First rule of ARIA: no ARIA is better than bad ARIA. Prefer a native element (<button>, <dialog>, <details>, <nav>) over a JS-reimplemented equivalent with ARIA bolted on, unless the platform genuinely has no equivalent.
  • Never accept 'axe/Lighthouse passed' as sufficient evidence for a custom interactive widget — manually match it against a specific APG pattern URL, including its full keyboard model (not just Tab/Enter — Escape, Home, End, Arrow keys per the pattern).
  • Treat heading-level skips (h1→h3) and missing/duplicate landmarks as blocking findings, not style notes — they break screen-reader page-navigation shortcuts.
  • Never approve positive tabindex values; require tabindex="0"/"-1" plus correct DOM order instead.
  • Flag aria-hidden="true" on any ancestor of a focusable/interactive descendant — this creates an unreachable-but-focusable or reachable-but-hidden trap.
  • Query current MDN/WAI-ARIA APG docs (see Context7 Documentation Protocol) for the specific element/role in question before ruling; element semantics and ARIA support tables change with spec updates — never assert support/behavior from memory.
  • Anything requiring live screen-reader verification (actual NVDA/JAWS/VoiceOver behavior) gets flagged as a residual risk, not asserted as verified from static review alone.
  • Label every claim as live evidence, spec-cited, documentation-based, or inference so the reviewer knows what's actually been verified vs. reasoned about.

References

Load these only when needed:

  • WCAG success-criterion mapping — use when a finding needs to be tied to a specific WCAG 2.2 success criterion for a compliance-audit deliverable.
  • APG pattern quick-index — use when identifying which APG pattern matches a given custom widget (modal, combobox, tabs, tree, menu, disclosure, etc.) before doing the deep keyboard-model comparison.
  • Heading and landmark structure rules — use when auditing page-level or component-tree-level outline structure, including nested-landmark and multiple-landmark-of-same-type edge cases.

Response minimum

Return, at minimum:

  • the element/component in scope and its semantic verdict (native-element compliant / needs ARIA / needs restructure),
  • for any custom interactive widget: the specific APG pattern URL cited, or an explicit flag that none matches and a native element should be used instead,
  • the heading/landmark outline diff (before/after) when structure changed,
  • every ARIA attribute added or removed, with its WAI-ARIA 1.2 role/state justification,
  • residual risk notes for anything requiring live assistive-technology verification beyond this static review.
Files (vanguard-frontier-agentic)
  • references
    • apg-pattern-index.md 4.9 KB
      # APG Pattern Quick-Index
      
      Use this reference when a component under review is a custom (JS-driven) interactive widget and you need to identify which WAI-ARIA Authoring Practices Guide (APG) pattern applies before comparing its actual keyboard/role/state implementation against the canonical model.
      
      ## What people get wrong
      
      The common bad assumption is:
      
      > "I added `role="button"` and a click handler, so it's accessible."
      
      Wrong. A role only tells assistive technology what the element *is*; it does nothing for keyboard operability, focus management, or state exposure. Every non-trivial custom widget corresponds to exactly one (sometimes zero) APG pattern, and that pattern defines a full contract: role, required/optional states and properties, and a specific keyboard interaction model — not just "Enter activates it."
      
      > Version note: WAI-ARIA and the APG evolve. Confirm the pattern's current keyboard model and required ARIA attributes via Context7 (`/mdn/content`) or the live `https://www.w3.org/WAI/ARIA/apg/patterns/` page before ruling — do not cite this file's summaries as the final word.
      
      ## Non-negotiable design rule: match first, judge second
      
      Before writing any finding about a custom widget, identify its APG pattern by name. If no pattern fits, that itself is a finding: either the widget should not exist as a custom control (use a native element), or it needs a `role="group"`/`role="region"` treatment with no interactive-widget semantics at all. Never invent ad-hoc ARIA for a shape that doesn't match a documented pattern.
      
      ## Common widget → pattern map (starting point, not exhaustive)
      
      | Widget seen in markup | Likely APG pattern | Minimum keyboard model to verify |
      |---|---|---|
      | Modal / overlay dialog | Dialog (Modal) | Focus moves into dialog on open; `Tab`/`Shift+Tab` trapped inside; `Escape` closes; focus returns to trigger on close |
      | Non-modal panel toggle | Disclosure (Show/Hide) | `Enter`/`Space` toggles; `aria-expanded` reflects state; no focus trap |
      | Dropdown menu (app-style, not `<select>`) | Menu / Menu Button | `Enter`/`Space`/`ArrowDown` opens; `ArrowUp`/`ArrowDown` moves; `Escape` closes and returns focus; `Home`/`End` jump to first/last |
      | Custom text input with suggestions | Combobox | `ArrowDown` opens/moves listbox; `Escape` closes without selecting; `Enter` selects active option; `aria-activedescendant` or roving `tabindex` tracks active option |
      | Tab strip | Tabs | Arrow keys move between tabs (auto- or manual-activation, pick one and document which); `Tab` key exits to panel; only active tab is in the sequential tab order |
      | Accordion | Accordion (built from Disclosure) | Each header toggles its own panel independently; heading semantics preserved (see heading-landmark-rules.md) |
      | Tree view (file explorer style) | Tree View | `ArrowUp`/`ArrowDown` moves; `ArrowRight`/`ArrowLeft` expands/collapses or moves to child/parent; `*` expands all siblings (optional) |
      | Custom slider | Slider | `ArrowLeft`/`ArrowRight` (or `Up`/`Down`) adjusts by step; `Home`/`End` jump to min/max; `aria-valuenow`/`aria-valuemin`/`aria-valuemax` kept in sync |
      | Toast / live status message | Alert or Status (live region, not a focusable widget) | No keyboard model — it must not steal focus; verify `role="alert"` (assertive, interrupting) vs `role="status"` (polite) is the deliberate choice, not a default |
      
      ## Verification targets
      
      For each matched pattern, confirm in the markup/code:
      
      - the root and child elements carry the pattern's required roles (native-implicit or explicit `role=`),
      - every required `aria-*` state/property from the pattern is present and kept in sync with actual UI state (not just set once at mount),
      - the full keyboard model is implemented, not a subset — a widget with only mouse/click handlers and no `keydown` logic fails regardless of correct roles,
      - focus is visible (no `outline: none` without a replacement focus style) and moves predictably on open/close/select.
      
      ## High-risk assumptions to kill
      
      - "It has the right `role`, so it's done" — role without keyboard model and state sync is theater.
      - "Semantic-sounding class name (`.dropdown-menu`) means it follows the Menu pattern" — check the actual DOM/role/keydown handlers, not the class name.
      - "We tested with the mouse and it felt fine" — APG conformance is a keyboard-first and AT-first contract; mouse-only QA proves nothing about it.
      - "It matched a pattern last time we reviewed it" — widgets drift as code changes; re-verify against the current implementation every review, not from memory of a prior review.
      
      ## When to push back
      
      Push back if the user asks to:
      
      - add ARIA roles/states to make a widget "look accessible" without implementing the pattern's keyboard model,
      - ship a custom widget where a native element (`<select>`, `<details>`, `<dialog>`) would satisfy the requirement with less code and less risk,
      - treat "no pattern fits perfectly" as license to skip APG entirely rather than picking the closest pattern or reconsidering the widget design.
      
    • heading-landmark-rules.md 4.7 KB
      # Heading and Landmark Structure Rules
      
      Use this reference when auditing the document outline of a page or component tree — heading hierarchy, landmark regions, and how components compose into a whole page's navigation structure.
      
      ## What people get wrong
      
      The common bad assumption is:
      
      > "Headings are for visual size; I'll pick whichever `<h*>` looks right at this font size, and CSS will fix the rest."
      
      Wrong. Screen-reader users navigate primarily by heading level and landmark region — jumping "next heading," "next level-2 heading," or "next landmark" without reading surrounding text. A heading chosen for visual weight instead of document structure breaks that navigation model even when the page looks fine visually.
      
      ## Non-negotiable design rules
      
      ### 1. Heading levels must not skip
      
      `<h1>` → `<h3>` with no `<h2>` between them is a structural break, not a style inconsistency. It reads to a screen-reader user as "I jumped past something — did I miss content?" Every component that renders a heading must accept its heading level as a prop/parameter from its parent context rather than hardcoding a level, so composed pages stay contiguous.
      
      ### 2. Exactly one `<h1>` per page (not per component)
      
      A component library that hardcodes `<h1>` internally breaks the instant it's composed twice on one page, or nested inside a page that already has its own `<h1>`. Components should default to accepting a level and render the semantically-correct `<h1>`–`<h6>` element for that level (not just visually restyle a `<div>`).
      
      ### 3. Landmarks must be unique-per-page or explicitly labeled
      
      A page may have only one unlabeled `<main>`, one unlabeled `<banner>` (`<header>` at the top level, not nested in `<article>`/`<section>`), and one unlabeled `<contentinfo>` (`<footer>` at the top level). Multiple instances of the same landmark type (e.g., two `<nav>` regions — primary nav and breadcrumb nav) MUST each carry a distinct accessible name via `aria-label` or `aria-labelledby`, or AT users hear "navigation, navigation" with no way to distinguish them.
      
      ### 4. Prefer semantic elements over `role=` on `<div>`
      
      `<nav>`, `<main>`, `<header>`, `<footer>`, `<aside>`, `<section>` (with an accessible name) carry implicit landmark roles. Adding `role="navigation"` to a `<div>` works but is strictly worse than using `<nav>` — it adds a maintenance burden (the role can drift out of sync with a renamed/refactored element) for no benefit. Flag `role=` landmark attributes on generic elements as a downgrade unless there's a documented reason (e.g., legacy browser support matrix) — see MDN ARIA landmark-role guidance via the Context7 Documentation Protocol in SKILL.md for the "semantic HTML first" rule.
      
      ### 5. `<section>` and `<aside>` need an accessible name to count as landmarks
      
      A bare `<section>` with no `aria-label`/`aria-labelledby`/heading-derived name does not expose as a landmark to most assistive technology — it is a generic grouping only. Do not report "landmark added" unless the accessible-name requirement is also met.
      
      ## Minimal safe audit flow
      
      1. Extract the full heading tree (level + text) for the page or component in isolation.
      2. Extract the full landmark tree (type + accessible name, or "unlabeled" if none).
      3. Diff both trees against the pre-change version when reviewing a delta; against W3C rules from scratch when reviewing a new page.
      4. Flag: any level skip, any second unlabeled instance of a unique-landmark type, any component that hardcodes a heading level instead of accepting one from its parent.
      5. For component-tree-only reviews (no full-page context available), state explicitly that heading-level correctness cannot be fully verified without knowing the mount context, and flag it as a residual risk rather than asserting compliance.
      
      ## Verification targets
      
      - Render (or read) the full page and extract the accessibility tree / heading outline via a real DOM inspection when live evidence is available; note this as `live evidence`.
      - When only source is available (no live render), derive the outline from JSX/template structure and label the finding `inference` — a dynamically-computed heading level (e.g., `level={depth + 1}`) cannot be fully verified statically without knowing all call sites.
      
      ## When to push back
      
      Push back if the user says:
      
      - "just use `<div class="h2">`, we'll style it to look right" — that produces zero navigable structure for AT users regardless of visual styling,
      - "we don't need `aria-label` on the second nav, screen-reader users will figure it out from context" — they cannot; landmark lists present regions out of visual context,
      - "heading levels don't matter as long as visually it looks like a hierarchy" — visual hierarchy and semantic hierarchy are independent axes; both must be correct.
      
    • wcag-criterion-mapping.md 4.5 KB
      # WCAG 2.2 Success-Criterion Mapping
      
      Use this reference when a finding from this skill needs to be tied to a specific WCAG 2.2 success criterion (SC) for a compliance-audit deliverable — e.g. when the output feeds an ADA / Section 508 / EN 301 549 conformance report and "looks wrong" is not an acceptable citation.
      
      ## Grounding rule
      
      This file gives a starting map from common findings to likely SC numbers so review output cites *something* concrete instead of vague prose. It does not replace reading the actual SC "Understanding" doc for edge cases — verify exact wording and Level (A/AA/AAA) against `https://www.w3.org/TR/WCAG22/` or via the Context7 Documentation Protocol before finalizing a compliance-facing citation, since SC numbering and scope can be easy to misremember (e.g., confusing 4.1.2 Name/Role/Value with 1.3.1 Info and Relationships).
      
      ## Finding → likely success criterion
      
      | Finding category | Likely SC (Level) | Why |
      |---|---|---|
      | Heading level skip / missing heading structure | 1.3.1 Info and Relationships (A) | Structure conveyed visually must also be conveyed programmatically |
      | Duplicate unlabeled landmark of the same type | 1.3.1 Info and Relationships (A), 2.4.1 Bypass Blocks (A) | Landmarks are the mechanism for bypassing repeated content; ambiguous landmarks break that mechanism |
      | Custom widget missing/incorrect role | 4.1.2 Name, Role, Value (A) | AT must be able to programmatically determine the role of every UI component |
      | Custom widget state (`aria-expanded`, `aria-checked`, etc.) not kept in sync with actual UI state | 4.1.2 Name, Role, Value (A) | Same SC — "Value" includes states that change |
      | Custom widget missing full keyboard operability (e.g. no `Escape`, no arrow-key navigation per its APG pattern) | 2.1.1 Keyboard (A) | All functionality must be operable through a keyboard interface |
      | Positive `tabindex` values / illogical focus order | 2.4.3 Focus Order (A) | Focus order must preserve meaning and operability |
      | `outline: none` / removed focus indicator with no replacement | 2.4.7 Focus Visible (AA) | Keyboard focus indicator must be visible |
      | `aria-hidden="true"` trapping a focusable descendant | 4.1.2 Name, Role, Value (A), 2.1.1 Keyboard (A) | Element is reachable by keyboard but hidden from AT (or vice versa) — a dual failure |
      | Toast/alert stealing focus or interrupting unexpectedly | 4.1.3 Status Messages (AA) | Status messages must be programmatically determinable without receiving focus |
      | Native element replaced with unlabeled `<div>`/`<span>` + click handler (fake button/link) | 4.1.2 Name, Role, Value (A), 2.1.1 Keyboard (A) | No role exposed, no keyboard access by default |
      | Missing/incorrect accessible name on interactive control (icon-only button, ambiguous link text) | 4.1.2 Name, Role, Value (A), 2.4.4 Link Purpose (In Context) (A) | Control lacks a determinable/discriminable accessible name |
      
      ## Non-negotiable rule for compliance-facing output
      
      Never present an SC citation as authoritative without the Level (A/AA/AAA) attached — an auditor reading "1.3.1" without a level cannot assess conformance-target scope (most orgs target AA). If uncertain of the exact SC number for a novel finding, say so explicitly (`inference — needs SC verification`) rather than guessing a plausible-sounding number; a wrong citation in a compliance deliverable is worse than an honest gap.
      
      ## Verification targets
      
      - Cross-check any SC number cited in this table against the live WCAG 2.2 "Understanding" page for that SC before it goes into a compliance-audit-facing deliverable (not required for a routine PR review comment, where this table's mapping is sufficient).
      - For AAA-level findings, flag explicitly that AAA is rarely a required conformance target — do not imply a blocking failure at AAA carries the same severity as an A/AA failure unless the user has stated AAA is their target.
      
      ## When to push back
      
      Push back if the user asks to:
      
      - label every accessibility finding as a single generic "WCAG violation" for a compliance deliverable without SC-level granularity — auditors and legal teams need the specific criterion and level,
      - downgrade a Level A finding to "nice to have" — Level A is the floor of any recognized conformance claim (WCAG A/AA/AAA, Section 508, EN 301 549 all build on Level A as mandatory),
      - treat this skill's static-review findings as a substitute for a full conformance audit — this skill narrows and grounds findings but does not replace testing with real assistive technology across the criteria this file does not cover (e.g., color contrast, captions, timing).
      
  • metadata.json 1.5 KB
    {
      "id": "html-semantics-accessibility-review",
      "name": "HTML Semantics & Accessibility Review",
      "type": "skill",
      "provider": "frontend",
      "harnesses": [
        "claude-code",
        "cursor",
        "codex",
        "gemini",
        "kiro",
        "other"
      ],
      "summary": "Reviews markup for correct native-element usage, valid heading/landmark structure, and WAI-ARIA APG-conformant custom-widget patterns, producing a WCAG-grounded verdict with APG citations for every custom interactive element and flags for anything needing live assistive-technology verification.",
      "source_type": "original",
      "official_docs": [
        "https://html.spec.whatwg.org/multipage/",
        "https://www.w3.org/WAI/ARIA/apg/",
        "https://www.w3.org/TR/wai-aria-1.2/",
        "https://www.w3.org/TR/WCAG22/",
        "https://developer.mozilla.org/en-US/docs/Web/HTML",
        "https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA"
      ],
      "security_notes": "Do not hardcode or request user PII, real screen-reader session logs, or authenticated-app URLs in review examples. Flag markup that binds unsanitized user content directly into the DOM (innerHTML/outerHTML/document.write) as an XSS-adjacent finding even though the primary fix is JS-side. Treat WCAG conformance findings as compliance-relevant (ADA/Section 508/EN 301 549 exposure) and label them as such rather than 'style nitpicks'.",
      "last_verified": "2026-07-02",
      "path": "skills/frontend/html-semantics-accessibility-review",
      "author": "github: VincentChuWaiChow",
      "version": "0.1.0"
    }
    
  • SKILL.md 6 KB
    ---
    name: html-semantics-accessibility-review
    description: Review HTML markup and rendered DOM structure for correct native-element usage, valid heading/landmark hierarchy, and WAI-ARIA APG-conformant custom-widget patterns; produce a WCAG 2.2-grounded verdict with APG pattern citations for every custom interactive control, flagging anything that needs live screen-reader verification beyond static review.
    allowed-tools: Read Grep Glob Bash(git diff:*) WebFetch
    metadata:
      author: "github: VincentChuWaiChow"
      version: "0.1.0"
      updated: "2026-07-02"
      category: compliance
    ---
    
    # HTML Semantics & Accessibility Review
    
    ## Purpose
    
    Automated a11y linters (axe, Lighthouse) catch roughly 30-50% of WCAG issues by design — they cannot verify whether a custom widget's keyboard interaction matches its intended pattern, whether ARIA correctly reflects (or wrongly overrides) native semantics, or whether a heading/landmark outline actually helps a screen-reader user navigate. This skill performs the manual, spec-grounded review that closes that gap: matching every custom interactive element against a specific WAI-ARIA APG pattern, verifying heading/landmark structure, and catching redundant or conflicting ARIA before it ships.
    
    ## When to use
    
    Use this skill when the user asks to:
    
    - review a pull request or component for HTML semantics or accessibility correctness,
    - verify a custom widget (modal, dropdown, tabs, combobox, accordion, etc.) against WAI-ARIA APG patterns,
    - audit heading level and landmark structure on a page or component tree,
    - check whether ARIA roles/states/properties are correctly applied or redundant/conflicting with native semantics,
    - assess WCAG 2.2 conformance risk for markup changes ahead of a compliance audit.
    
    ## Context7 Documentation Protocol
    
    Element semantics, implicit ARIA-role mappings, and attribute-support tables change as the HTML and ARIA specs evolve — never assert them from memory.
    
    1. Call `ToolSearch` with query `"context7"` (or `"select:mcp__Context7__resolve-library-id,mcp__Context7__query-docs"`) to load the Context7 tools if they are not already loaded in this session.
    2. Call `mcp__Context7__resolve-library-id` for the relevant documentation set — for this skill that is almost always MDN (`/mdn/content`, or `/websites/developer_mozilla_en-us` if the former lacks coverage for the query). Resolve the WAI-ARIA APG or WCAG spec source too if the review needs primary-spec wording rather than MDN's paraphrase.
    3. Call `mcp__Context7__query-docs` for the specific element, role, or attribute in question — e.g. "implicit ARIA role for `<nav>`", "APG combobox keyboard pattern", "tabindex focus-order behavior" — before ruling on it. Do this per review, not once from memory of a prior session.
    4. Prefer the official spec/MDN wording over this skill's own paraphrase when the two could be read to disagree; cite the resolved doc URL in the finding.
    5. If Context7 is unavailable or returns no relevant match, fall back to the URLs in `official_docs` / `references/apg-pattern-index.md`, and explicitly mark the claim `documentation-based (Context7 unavailable)` rather than presenting it as freshly verified.
    6. Never invent an ARIA role, state, property, or implicit-semantics mapping that no queried source confirms.
    
    ## Lean operating rules
    
    - First rule of ARIA: no ARIA is better than bad ARIA. Prefer a native element (`<button>`, `<dialog>`, `<details>`, `<nav>`) over a JS-reimplemented equivalent with ARIA bolted on, unless the platform genuinely has no equivalent.
    - Never accept 'axe/Lighthouse passed' as sufficient evidence for a custom interactive widget — manually match it against a specific APG pattern URL, including its full keyboard model (not just Tab/Enter — Escape, Home, End, Arrow keys per the pattern).
    - Treat heading-level skips (h1→h3) and missing/duplicate landmarks as blocking findings, not style notes — they break screen-reader page-navigation shortcuts.
    - Never approve positive `tabindex` values; require `tabindex="0"`/`"-1"` plus correct DOM order instead.
    - Flag `aria-hidden="true"` on any ancestor of a focusable/interactive descendant — this creates an unreachable-but-focusable or reachable-but-hidden trap.
    - Query current MDN/WAI-ARIA APG docs (see Context7 Documentation Protocol) for the specific element/role in question before ruling; element semantics and ARIA support tables change with spec updates — never assert support/behavior from memory.
    - Anything requiring live screen-reader verification (actual NVDA/JAWS/VoiceOver behavior) gets flagged as a residual risk, not asserted as verified from static review alone.
    - Label every claim as `live evidence`, `spec-cited`, `documentation-based`, or `inference` so the reviewer knows what's actually been verified vs. reasoned about.
    
    ## References
    
    Load these only when needed:
    
    - [WCAG success-criterion mapping](references/wcag-criterion-mapping.md) — use when a finding needs to be tied to a specific WCAG 2.2 success criterion for a compliance-audit deliverable.
    - [APG pattern quick-index](references/apg-pattern-index.md) — use when identifying which APG pattern matches a given custom widget (modal, combobox, tabs, tree, menu, disclosure, etc.) before doing the deep keyboard-model comparison.
    - [Heading and landmark structure rules](references/heading-landmark-rules.md) — use when auditing page-level or component-tree-level outline structure, including nested-landmark and multiple-landmark-of-same-type edge cases.
    
    ## Response minimum
    
    Return, at minimum:
    
    - the element/component in scope and its semantic verdict (native-element compliant / needs ARIA / needs restructure),
    - for any custom interactive widget: the specific APG pattern URL cited, or an explicit flag that none matches and a native element should be used instead,
    - the heading/landmark outline diff (before/after) when structure changed,
    - every ARIA attribute added or removed, with its WAI-ARIA 1.2 role/state justification,
    - residual risk notes for anything requiring live assistive-technology verification beyond this static review.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related