Accessibility

← Documentation
STRVCT

Automatic, framework-level ARIA support, keyboard navigation, and preference adaptation derived from slot metadata annotations and view classes.

Overview

STRVCT provides built-in accessibility support that works automatically for every application built on the framework. Because the UI is derived from model nodes through a small set of shared view classes, accessibility metadata is emitted at the framework level—developers don't need to manually add ARIA attributes to individual components.

In a conventional web framework, accessibility is a per-component concern: every button, list, and form field requires manual ARIA attributes, and maintenance costs scale linearly ($O(N)$) with screen count. In STRVCT, the same $\sim$15 view classes render every application's UI, so fixing accessibility in those shared primitives fixes it across every screen in every application.

Slot Metadata Annotations Declared once in initPrototypeSlots() slot.description() slot.isReadOnly() slot.isRequired() slot.minimum() / slot.maximum() Framework ARIA Emitted Emitted by ~15 shared view classes aria-description="Current hit points" aria-readonly="true" aria-required="true" aria-valuemin="0" · aria-valuemax="999" One declaration drives field validation, AI JSON tool schemas, and screen reader ARIA attributes.

Slot Metadata to ARIA Mapping

SvFieldTile implements syncAriaFromSlotMetadata() to map slot metadata directly to ARIA attributes:

Slot AnnotationARIA AttributeDescription
description()aria-descriptionDetailed field description announced on demand
isReadOnly()aria-readonly="true"Indicates whether value is editable
isRequired()aria-required="true"Indicates required form field
slotType()role="..."Informs control role (checkbox, button, listbox)
minimum() / maximum()aria-valuemin / aria-valuemaxValue range bounds for numeric fields

Example Slot Declaration:

{
    const slot = this.newSlot("hitPoints", 10);
    slot.setSlotType("Number");
    slot.setIsRequired(true);
    slot.setAnnotation("minimum", 0);
    slot.setAnnotation("maximum", 999);
    slot.setDescription("Current character hit points");
}

Produces a field tile emitting aria-required="true", aria-valuemin="0", aria-valuemax="999", and aria-description="Current character hit points" without custom accessibility code.

View Class ARIA Roles & Landmarks

STRVCT View ClassARIA RolePurpose & Landmark Usage
SvStackViewnavigationTop-level navigation landmark container
SvNavViewregionNamed column region (aria-label from node title)
SvTilesViewlistContainer for navigable tile items
SvTilelinkIndividual navigation item in a list
SvFieldTilegroupKey-value field with label and control
SvBooleanFieldTilecheckboxToggle field emitting aria-checked
SvActionFieldTilebuttonClickable action emitting aria-disabled
SvOptionsNodeTilelistboxContainer for selectable options
SvOptionNodeTileoptionIndividual option emitting aria-selected
SvBreadCrumbsTilenavigationBreadcrumb trail (aria-label="Breadcrumb")

Node-Level ARIA Overrides (`SvTitledNode`)

Domain models can override default ARIA properties by implementing protocol hooks on SvTitledNode:

Protocol MethodDefaultPurpose
nodeAriaLabel()title()Label announced by screen readers
nodeAriaRole()null (view default)Custom role override
nodeAriaIsReadOnly()null (slot editability)Read-only state override
nodeAriaIsRequired()null (slot required)Required state override
nodeAriaLive()nullReturns "polite" or "assertive" for dynamic live regions

Focus Management & Keyboard Navigation

  • Tile Focusability: Tiles use tabindex="-1", making them focusable programmatically without cluttering the global browser Tab order.
  • Focus Follows Selection: When a tile is selected, SvTilesView sets aria-current="true" and moves DOM focus to the tile.
  • Keyboard Navigation: Arrow keys navigate tiles in columns; Enter opens subnode details; Escape moves focus up to the parent column.
  • Focus Indicators: Styled using :focus-visible (2px solid cornflower blue outline). High-contrast mode (prefers-contrast: more) increases outlines to 3px solid white.

Visual Accessibility & Motion Preferences

  • Reduced Motion (prefers-reduced-motion: reduce): Animations and transitions are reduced to 0.01ms, scroll behavior switches to auto (instant), and iteration counts lock to 1.
  • High Contrast (prefers-contrast: more): Focus outlines increase to 3px solid white with tighter offsets.

WCAG 2.2 Compliance Matrix

WCAG CriterionImplementation Mechanism
1.3.1 Info & RelationshipsARIA roles and landmarks convey structure
1.3.2 Meaningful SequenceDOM order matches visual flexbox order
2.1.1 KeyboardFull keyboard support (Arrows, Enter, Escape)
2.3.3 Animation from Interactionsprefers-reduced-motion media query override
2.4.1 Bypass BlocksLandmark roles enable screen reader region jumping
2.4.6 Headings & Labelsaria-label derived from node title()
2.4.7 Focus VisibleDistinct :focus-visible outlines
4.1.2 Name, Role, ValueAutomated ARIA roles, labels, and states across all tiles

Files Modifying Accessibility

FileResponsibilities
_css.css:focus-visible styling, prefers-reduced-motion, prefers-contrast
SvTilesView.jsrole="list", aria-label, opt-in aria-live
SvTile.jsrole="link", tabindex="-1", aria-label, aria-description, aria-current
SvFieldTile.jsrole="group", aria-label, aria-readonly, syncAriaFromSlotMetadata()
SvBooleanFieldTile.jsrole="checkbox", aria-checked
SvActionFieldTile.jsrole="button", aria-label, aria-disabled
SvOptionsNodeTile.jsrole="listbox"
SvOptionNodeTile.jsrole="option", aria-selected
SvChatMessageTile.jsaria-live="polite"
SvStackView.jsrole="navigation"
SvNavView.jsrole="region", aria-label
SvBreadCrumbsTile.jsrole="navigation", aria-label="Breadcrumb", aria-current="location"
  • Nodes: Core SvNode domain abstraction.
  • Slots: Complete guide to slot metadata and declarations.