executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
semantic-html-aria-accessibility-treeBuilds accessible HTML structures using semantic elements (button, nav, main, section, form, fieldset, label) and ARIA 1.2 with clear understanding of accessibility tree, implicit roles, first rule of ARIA, and landmark navigation.
Independent GitHub snapshot · Automated classification · Original documentation governs
Builds accessible HTML structures using semantic elements and ARIA 1.2, with clear mental model of the accessibility tree, implicit vs explicit roles, and when to use ARIA. Covers HTML5 semantic elements (button, nav, main, section, article, form, fieldset, label), ARIA roles/properties/states, accessibility tree visualization, "first rule of ARIA" (use native HTML), and accessibility tree inspection tools. Load when designing DOM structure, building accessible forms, creating landmark navigation, or understanding how content is exposed to assistive technology.
<button>, <a>, <nav>, <main>, <article>, <form>, <fieldset>, <label><button> = role="button", <nav> = role="navigation"role="button" on <div> if <button> exists<header>, <nav>, <main>, <aside>, <footer><label htmlFor="input-id"> with <input id="input-id">aria-label only for missing text (icon buttons, decorative labels)Use this skill when:
Avoid this skill for:
| Element | Implicit Role | Usage | Screen Reader Announces |
|---|---|---|---|
<header> | banner | Page header (once per page) | "banner" |
<nav> | navigation | Navigation section | "navigation" |
<main> | main | Main content (once per page) | "main" |
<article> | article | Self-contained content | "article" |
<section> | region | Generic grouping (use aria-label for context) | "region" |
<aside> | complementary | Sidebar, related content | "complementary" |
<footer> | contentinfo | Page footer (once per page) | "contentinfo" |
| Element | Usage | Semantic Meaning |
|---|---|---|
<h1> - <h6> | Headings | Document outline hierarchy |
<p> | Paragraphs | Natural text grouping |
<blockquote> | Extended quotes | Attribution context |
<ul>, <ol>, <li> | Lists | Enumerated/ordered information |
<dl>, <dt>, <dd> | Definition lists | Terms and definitions |
<address> | Contact information | Author/organization address |
| Element | Implicit Role | Keyboard Support | Usage |
|---|---|---|---|
<button> | button | Enter, Space, Tab | Buttons, form submission |
<a href> | link | Tab, Enter | Navigation links |
<input>, <textarea>, <select> | varies | Tab, input-specific | Form controls |
<label> | label | No, associates with input | Form field labels |
<fieldset> | group | No, groups inputs | Form grouping |
| Element | Usage | Accessibility Requirement |
|---|---|---|
<img> | Images | alt text (required) |
<figure> | Illustration/diagram | <figcaption> for context |
<video> | Video content | captions, transcript, audio description |
<audio> | Audio content | transcript, captions |
The accessibility tree is a simplified representation of the DOM structure that assistive technologies (screen readers, voice control) use to understand page content.
DOM Tree Accessibility Tree
───────────── ──────────────────
<header> "banner" (role)
<nav> ├─ "navigation" (role)
<ul> │ ├─ "Home" (button)
<li><button>Home</button> │ ├─ "Products" (link)
<li><a>Products</a> │ └─ "Contact" (link)
</nav> │
</header> │
<main> ├─ "main" (role)
<h1>Welcome</h1> │ ├─ "Welcome" (heading level 1)
<p>...</p> │ └─ "..." (paragraph)
<button aria-label="Search"> │ └─ "Search" (button)
<svg aria-hidden="true"> │ [decorative, not in tree]
...
</svg>
</button>
</main>
<footer> └─ "contentinfo" (role)
... └─ "..." (text content)
</footer>
Screen reader reads:
Key insights:
aria-hidden="true") are excludedEvery item in the accessibility tree has up to three properties:
| Property | Example | How Determined |
|---|---|---|
| Name | "Search", "Submit", "Home" | Text content, aria-label, title, alt |
| Role | "button", "link", "heading" | HTML element or aria-role |
| State | "pressed", "expanded", "disabled" | aria-pressed, aria-expanded, disabled |
Screen readers announce: "{State} {Name} {Role}"
Examples:
<button disabled>Save</button> → "Disabled Save button"<a href="/home">Home</a> → "Home, link"<h1>Welcome</h1> → "Welcome, heading level 1"Always use native HTML elements first. Only use ARIA when native HTML lacks the required semantics.
<button> responds to Enter/Space without code<!-- ❌ BAD: ARIA button without keyboard support -->
<div role="button" tabindex="0" @click="handleClick">
Click me
</div>
<!-- Missing: Enter/Space support, focus management, semantic meaning -->
<!-- ✅ GOOD: Native button -->
<button @click="handleClick">
Click me
</button>
<!-- Includes: Enter/Space, focus management, inherent semantics -->
Use ARIA only when:
HTML element doesn't exist for your use case
Native element needs role enhancement
<input type="checkbox"> → <input type="checkbox" aria-switch> (not recommended, but valid)Heading or labeling missing
<div aria-label="Search Results"> for dynamically generated regionState communication
<button aria-pressed="true">Toggle</button> for toggle buttons<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Title (appears in browser tab, <title> not visible on page)</title>
</head>
<body>
<!-- ✅ GOOD: Semantic structure with landmarks -->
<!-- Page header (appears once) -->
<header role="banner">
<h1>Site Name</h1>
<p>Site tagline</p>
</header>
<!-- Main navigation -->
<nav aria-label="Main navigation">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
<!-- Main content (appears once) -->
<main id="main-content">
<h1>Page Heading</h1>
<!-- Article content -->
<article>
<h2>Article Title</h2>
<p>Article content...</p>
</article>
<!-- Additional articles in section -->
<section aria-label="Related articles">
<h2>Related</h2>
<article>
<h3>Related Article 1</h3>
</article>
<article>
<h3>Related Article 2</h3>
</article>
</section>
</main>
<!-- Sidebar (supplementary content) -->
<aside aria-label="Sidebar">
<h2>Featured</h2>
<p>Featured content...</p>
</aside>
<!-- Page footer (appears once) -->
<footer>
<p>© 2024 Company Name</p>
</footer>
<!-- Skip to main content link (keyboard users benefit) -->
<a href="#main-content" class="skip-link">Skip to main content</a>
</body>
</html>
<!-- ✅ GOOD: Properly structured form -->
<form id="contact-form">
<fieldset>
<legend>Contact Information</legend>
<!-- Properly labeled text input -->
<div class="form-group">
<label for="name">Name</label>
<input id="name" type="text" name="name" required>
</div>
<!-- Email input with helper text -->
<div class="form-group">
<label for="email">Email Address</label>
<input
id="email"
type="email"
name="email"
required
aria-describedby="email-help"
>
<p id="email-help" class="help-text">
We'll never share your email
</p>
</div>
<!-- Password with validation -->
<div class="form-group">
<label for="password">Password</label>
<input
id="password"
type="password"
name="password"
required
aria-invalid="false"
aria-describedby="password-requirements"
>
<ul id="password-requirements" class="requirements">
<li>At least 8 characters</li>
<li>One uppercase letter</li>
<li>One number</li>
</ul>
</div>
<!-- Checkbox -->
<div class="form-group">
<input
id="terms"
type="checkbox"
name="terms"
required
>
<label for="terms">
I agree to the <a href="/terms">terms of service</a>
</label>
</div>
<!-- Submit button -->
<button type="submit">Create Account</button>
</fieldset>
</form>
<!-- ❌ BAD: Inaccessible form -->
<form>
<!-- Missing label -->
<input type="text" placeholder="Name">
<!-- Label not associated -->
<label>Email</label>
<input type="email">
<!-- No fieldset/legend for grouping -->
<input type="checkbox">
I agree to terms
<!-- Missing semantic button -->
<div role="button" onclick="submitForm()">Submit</div>
</form>
<!-- ✅ GOOD: Semantic navigation -->
<nav aria-label="Main navigation">
<ul>
<li><a href="/">Home</a></li>
<li>
<a href="/products">Products</a>
<!-- Submenu -->
<ul>
<li><a href="/products/electronics">Electronics</a></li>
<li><a href="/products/clothing">Clothing</a></li>
</ul>
</li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
<!-- ❌ BAD: Non-semantic navigation -->
<div class="navigation">
<div class="nav-item"><a href="/">Home</a></div>
<div class="nav-item"><a href="/products">Products</a></div>
<div class="nav-item"><a href="/about">About</a></div>
</div>
<!-- Roles define what an element does -->
<!-- Navigation role (use <nav> instead) -->
<div role="navigation">Links here</div>
<!-- Tablist with roving tabindex -->
<div role="tablist">
<button role="tab" aria-selected="true" tabindex="0">Tab 1</button>
<button role="tab" aria-selected="false" tabindex="-1">Tab 2</button>
</div>
<!-- Alert role (for status messages) -->
<div role="alert">Error: Password too short</div>
<!-- Status role (for updates) -->
<div role="status" aria-live="polite">Loading...</div>
<!-- aria-label: Provide name when text unavailable -->
<button aria-label="Close dialog">×</button>
<!-- aria-labelledby: Connect to existing text -->
<h2 id="dialog-title">Delete Item</h2>
<div role="dialog" aria-labelledby="dialog-title">
...
</div>
<!-- aria-describedby: Provide description -->
<input
type="password"
aria-describedby="pwd-requirements"
>
<p id="pwd-requirements">8+ characters, 1 number, 1 uppercase</p>
<!-- aria-required: Indicate required field -->
<input type="email" aria-required="true">
<!-- aria-invalid: Indicate invalid state -->
<input type="email" aria-invalid="true">
<!-- aria-expanded: Indicate collapsed/expanded state -->
<button aria-expanded="false" aria-controls="menu">
Menu
</button>
<ul id="menu" hidden>...</ul>
<!-- aria-selected: Indicate selected tab/option -->
<button role="tab" aria-selected="true">Tab 1</button>
<button role="tab" aria-selected="false">Tab 2</button>
<!-- aria-pressed: Indicate toggled button state -->
<button aria-pressed="false" @click="toggle()">
Toggle
</button>
<!-- aria-disabled: Prevent interaction (supplementary to disabled) -->
<button aria-disabled="true">Disabled</button>
Verify accessibility tree matches:
<label htmlFor="id"><img alt="description">aria-label only when visible text unavailable (icon buttons, regions)role="button" on <div> when <button> exists<div> and <span> for interactive elements (use button, a, input)aria-hidden="true")aria-label as substitute for proper HTML structure<label> elements without aria-labelFor any page or component, verify:
<label> or aria-labelaria-hidden="true"