Accessible SVG Contracts and ARIA Implementation Requirements in Diagram-Design
Diagram-Design enforces strict accessible SVG contracts and ARIA implementation requirements by validating every exported diagram in self_check.py to ensure screen-reader compatibility through mandatory role="img" attributes, semantic title and description elements, and proper aria-labelledby relationships.
The cathrynlavery/diagram-design repository automatically validates all generated diagrams against a formal accessibility contract to guarantee inclusive user experiences. The validation logic codifies specific ARIA implementation requirements that prevent common SVG accessibility failures, ensuring every diagram exposes meaningful semantic information to assistive technologies.
SVG Accessibility Validation Rules
The validation engine resides in skills/diagram-design/scripts/self_check.py, where seven explicit rules govern SVG accessibility compliance. These checks run during the export pipeline to catch violations before diagrams reach end users.
Expose at Least One Non-Hidden SVG
Line 219 of self_check.py validates that a diagram file contains at least one SVG that is not hidden from assistive technology. The check uses if str(svg["attrs"].get("aria-hidden", "")).casefold() != "true" to ensure aria-hidden is not set to "true", guaranteeing that a diagram is actually exposed to users who rely on ARIA.
Enforce role="img" Semantics
Every accessible SVG must declare role="img" to announce itself as an image to screen readers. Line 227 appends the error "svg {number} needs role=img" when this attribute is missing, ensuring assistive technologies recognize the graphic as a meaningful image rather than generic content.
Require Title as First Child
The first child of the SVG must be a <title> element to provide a short, accessible name. Line 235 validates this structure with if svg["first"] != "title" and raises "svg {number} title must be its first child", establishing the correct document order for screen-reader announcements.
Mandate Non-Empty Title and Description
Accessible diagrams must supply both a concise label and a longer description. Line 238 enforces non-empty <title> and <desc> elements, appending "svg {number} needs non-empty title and desc" when either element is blank or missing.
Prefix Element IDs
To prevent ID collisions across diagrams and ensure predictable references, line 242 validates that IDs are diagram-prefixed and never bare. The error "svg {number} title/desc IDs must be diagram-prefixed, never bare" ensures unique identifier schemes.
Validate aria-labelledby Ordering
The aria-labelledby attribute must list the title ID followed by the description ID to establish the correct reading order. Line 244 checks this sequence and raises "svg {number} aria-labelledby must name title then desc" to guarantee screen readers announce the title before the detailed description.
Handle Motion and Interactive Elements
For animated or interactive content, lines 302–305 and 334–337 enforce specific ARIA patterns. Motion status indicators must use aria-live="polite" and aria-atomic="true" with role="status", while decorative motion items require aria-hidden="true" and focusable="false" to prevent focus traps and convey appropriate information levels.
Contract Specification and Export Pipeline
These validation rules codify the Diagram-Design contract documented in skills/diagram-design/references/output-spec.md. This specification mandates that exported diagrams must preserve role="img", aria-labelledby, and the first-child <title>/<desc> structure exactly as authored.
The export pipeline documented in skills/diagram-design/references/export.md reinforces these requirements during diagram generation. According to the source code, the contract requires that all ARIA attributes survive the transformation process from design to final SVG output, maintaining the semantic guarantees verified by self_check.py.
Implementation Examples
Valid Accessible SVG
The following markup satisfies all contract requirements:
<svg role="img"
aria-labelledby="diag1-title diag1-desc"
width="200" height="100"
viewBox="0 0 200 100">
<title id="diag1-title">Server-to-Database latency</title>
<desc id="diag1-desc">A line chart showing latency over the last hour.</desc>
<!-- Diagram content goes here -->
</svg>
Invalid SVG (Fails Validation)
This example violates multiple requirements and triggers errors in self_check.py:
<svg aria-hidden="true" width="200" height="100">
<!-- No role, no title/desc, hidden from AT → all three checks will fire -->
</svg>
Animated Element ARIA Pattern
For semantic motion indicators, implement role and live region attributes:
<g role="status"
aria-live="polite"
aria-atomic="true">
<title id="anim1-title">Progress bar</title>
<desc id="anim1-desc">Loading… 45% complete.</desc>
<!-- Animated graphics -->
</g>
Summary
- cathrynlavery/diagram-design enforces accessible SVG contracts through automated validation in
self_check.py. - Valid diagrams must expose at least one non-hidden SVG with
role="img"and a<title>element as the first child. - Element IDs must be diagram-prefixed, and
aria-labelledbymust reference the title ID followed by the description ID. - Non-empty
<title>and<desc>elements provide accessible names and descriptions for screen readers. - Motion and interactive elements require specific ARIA attributes including
aria-live,aria-atomic, andfocusablesettings to prevent accessibility barriers.
Frequently Asked Questions
What happens if an SVG has aria-hidden set to true?
Diagram-Design rejects files where all SVG elements are hidden from assistive technology. Line 219 of self_check.py specifically checks aria-hidden attributes, requiring at least one visible SVG per diagram to ensure content reaches screen-reader users.
Why must the title element be the first child of the SVG?
The first-child requirement ensures screen readers announce the accessible name immediately upon encountering the graphic. Line 235 of self_check.py enforces this document order because assistive technologies typically read the first child element as the primary label, establishing the correct semantics before processing descriptive content.
How does Diagram-Design prevent ID collisions between diagrams?
The validation logic at line 242 of self_check.py requires that all element IDs be diagram-prefixed rather than bare identifiers. This prevents namespace conflicts when multiple SVGs appear on the same page and ensures that aria-labelledby references resolve predictably across different diagram instances.
What is the difference between the title and desc elements in this context?
The <title> element provides a short, concise accessible name for the image (announced first), while the <desc> element supplies a longer, detailed description. According to the output-spec.md contract, both must be non-empty and referenced via aria-labelledby in title-then-desc order to give screen-reader users immediate context followed by comprehensive details.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →