Accessibility¶
Hedron aims for an accessible HTML baseline, not automatic WCAG / legal / VPAT certification. Authors remain responsible for labels, focus, and interaction patterns.
0.19 ships accessibility engineering APIs (hedron_core.a11y), Explorer review,
progressive-enhancement forms, landmarks, and automated Playwright/axe evidence.
Human screen-reader evaluation is Planned on 0.21 (sessions outstanding; not Supported).
Narrative: What's new in 0.19 · API: A11Y.
What Hedron provides¶
- Semantic built-ins (landmarks, forms, tables, dialogs) that emit ordinary HTML
- Versioned standards profile and machine-readable
AccessibilityContractcatalog - Explorer accessibility workspace (
/hedron-explorer/a11ywithhedron[dev]) - Progressive-enhancement POST (no-JS full page / redirect alongside HTMX)
- Allowlisted
Page(scripts=[SafeUrl…])for same-origin PE scripts AccessibilityScenario, axe → SARIF helpers, and automated three-engine AT matrix- Stable identities for targets and tests without encoding secrets
- Documented component contracts in the Components catalog
- Optional browser helpers via
hedron[browser]for Playwright evidence
hedron_core.a11y (0.19)¶
Import from hedron_core.a11y (re-exported where noted). Full contract:
A11Y API.
| Surface | Role |
|---|---|
ACCESSIBILITY_PROFILE / AccessibilityProfile |
Pinned WCAG 2.2 A/AA + WAI-ARIA 1.2 baseline (PROFILE-019) |
ClaimBoundary |
Explicit non-goals (no auto WCAG / legal / certification / VPAT) |
AccessibilityContract / catalog |
Leaf or package obligations — never implies app conformance |
AccessibilityScenario |
Structured evidence steps; empty scans are not “accessible” |
EvidenceInventory / Waiver / AccessibilityStatement |
Governance (GOVERN-019); statements need human approved_by |
| Surface helpers | Structure validation, media tracks, cognitive prefs, target spacing |
from hedron_core.a11y import ACCESSIBILITY_PROFILE, AccessibilityContractCatalog, seed_reviewed_contracts
assert ACCESSIBILITY_PROFILE.claim_boundaries.forbids_auto_wcag_conformance
catalog = AccessibilityContractCatalog()
seed_reviewed_contracts(catalog)
Claim boundaries¶
Hedron refuses automatic conformance, legal compliance, certification, and VPAT/ACR
claims (refuse_auto_conformance_claim). Component contracts record obligations and
limitations; composition can still leave unmet criteria. Empty axe scans never summarize
as accessible.
Explorer /a11y workspace¶
With explorer="development" or "secured" and hedron[dev], open
/hedron-explorer/a11y for:
- Standards profile summary
- Component contract table (registry stubs + curated reviewed contracts)
- Review-mode checklist (contrast, target spacing, zoom/reflow, reduced motion, …)
- ATAG authoring notes beside component inspect metadata
See Explorer API.
Progressive enhancement, landmarks, and Page(scripts=)¶
| Gate | What to do |
|---|---|
PE-019 |
Critical forms/mutations succeed without HX-Request — full Page or redirect. HTMX is optional enhancement. |
LANDMARK-019 |
Use Header / Main / Nav / Aside / Footer / Section with allowlisted safe attrs. |
SCRIPT-019 |
Attach same-origin PE scripts via Page(scripts=[SafeUrl.parse(..., purpose=UrlPurpose.ASSET)]) — no free-form <script> in the tree. |
Details: Forms and actions · Page · Landmarks.
Try it (simulated)¶
HTMX fragment vs full-page confirmation path (PE-019). Docs simulation.
HTMX path swaps #pe-result. Full-page path replaces the whole stage.
Minimal runnable app.py that reproduces this demo (real Hedron, not the docs simulator):
import os
from fastapi import Request
from fastapi.responses import RedirectResponse
from hedron import Form, Hedron, InteractionResult, Page, Stack, SubmitButton, Text, html
from hedron.security import csrf_token_for_request
app = Hedron(
title="PE paths",
security="standard",
explorer="off",
session_secret=os.environ.get("HEDRON_SESSION_SECRET", "dev-only"),
)
result = app.region("pe-result", description="HTMX result")
def _csrf(request: Request) -> str:
return csrf_token_for_request(request, request.app.state.hedron_security)
@app.page("/")
def home(request: Request) -> Page:
token = _csrf(request)
return Page(
Stack(
Text("Invite note"),
html.div(id=result.id),
Form(
html.input(type="hidden", name="csrf_token", value=token),
html.label("Note", html.input(name="note", value="Ship PE-019")),
SubmitButton("Submit with HTMX"),
**{
"hx-post": "/save",
"hx-target": result.selector,
"hx-swap": "outerHTML",
},
),
Form(
html.input(type="hidden", name="csrf_token", value=token),
html.label("Note", html.input(name="note", value="Ship PE-019")),
SubmitButton("Submit full page"),
action="/save",
method="post",
),
),
title="PE",
)
@app.action("/save", method="POST")
async def save(request: Request):
form = await request.form()
note = str(form.get("note") or "")
if request.headers.get("HX-Request"):
return InteractionResult(
content=html.div(
html.strong("Fragment path"),
html.span(note),
id=result.id,
),
region_id=result.id,
)
return RedirectResponse(f"/done?note={note}", status_code=303)
@app.page("/done")
def done(request: Request) -> Page:
return Page(Text(f"Full-page confirmation: {request.query_params.get('note', '')}"), title="Done")
AT matrix (AT-019) vs human AT¶
0.19 Verified: automated three-engine Playwright matrix (Chromium, Firefox, WebKit)
covering keyboard, zoom/reflow, reduced motion, forced colors, plus pinned axe/ACT
provenance after representative dynamic states (hedron[browser]).
0.21 Published engineering / sessions Planned (D-052): compensated human screen-reader /
disabled-participant evaluation. Protocol, gate IDs, and redacted ledger schema live under
human-at acceptance.
PROTOCOL-021 is Verified; SR/PARTICIPANT remain Planned. Do not market automated evidence as
human AT sign-off, and do not market human AT as Supported until session gates are Verified.
Author checklist¶
- Every interactive control has an accessible name (
Label,aria-label, or visible text). - Forms associate labels with inputs (
FormField/Label+ matchingname). - Dialogs and expanders restore focus; do not trap keyboard users without an exit.
- Status and errors use polite live regions where appropriate (
role="status", alerts). - Do not rely on color alone for state; pair with text or icons that have names.
- Prefer no-JS POST success for critical mutations; enhance with HTMX where useful.
- Test critical flows with keyboard-only navigation; plan a screen-reader pass (0.21 owns compensated AT evidence — protocol Verified; sessions Planned / not Supported).
What Hedron does not claim¶
- Automatic WCAG conformance or legal certification
- That every third-party chart/grid Web Component is accessible out of the box
- That third-party or Experimental interactive chart hosts meet the same bar as core built-ins
- That Playwright/axe results replace human AT evaluation
Research and RFCs¶
Maintainer RFCs (GitHub; excluded from Read the Docs builds):
- RFC-0023 (umbrella)
- RFC-0051 AccessibilityContract
- RFC-0052 Explorer / AccessibilityScenario
- RFC-0053 PE / landmarks / Page scripts
- RFC-0054 ATAG authoring
- RFC-0055 Governance / AT matrix
Adopters should treat this guide as the day-one checklist.
See also¶
A11Y API · What's new in 0.19 · Security · Testing · Components