Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Component Accessibility Checklist

This matrix is the accessibility contract for Beverly’s interactive surfaces. It is intentionally explicit about partial coverage and manual validation.

Status meanings:

  • Yes: implemented in Beverly’s semantic/focus/keyboard systems.
  • Partial: the core semantics exist, but a documented state or platform behavior still needs component-specific verification.
  • Gap: not currently wired by the component.
  • Manual: requires VoiceOver, NVDA, JAWS, Orca, or real-window testing.
  • N/A: not part of this component’s contract; for example, a notification is not a bound input field. Application-owned relationships still use SemanticRelationships rather than guessed associations.
ComponentRoleNameValue/stateKeyboardFocusDisabledError/validationRelationshipsDynamic announcements
BeverlyButtonYes: ButtonYes: text/custom text childYes: disabledPartial: activation routing exists; shortcut coverage needs manual verificationYes: tab index/focus ringYesN/A: not a fieldApp-owned relationshipsManual: live-region adapter available
LinkYes: LinkYes: Link::textYes: destination URL projectedPartial: shared activationPartial: platform verificationYes: dynamic stateN/A: not a fieldApp-owned relationshipsManual: live-region adapter available
CheckboxYes: CheckboxYes: config labelYes: checked/indeterminate/disabledYesPartial: platform verificationYesYes: bound error/invalid projectionYes: bound error/description targetsManual
ToggleYes: SwitchYes: config labelYes: checked/disabledYesPartial: platform verificationYesYes: bound error/invalid projectionYes: bound error/description targetsManual
RadioGroupYes: RadioGroup/RadioYes: group labelYes: selected valuePartial: roving behavior needs platform verificationPartial: platform verificationYes: group disabled guardsYes: bound error projectionYes: group ownership and errorsManual
Select<T>Yes: ComboBox/ListBoxYes: persistent .label(...)Yes: value/expandedPartial: platform verificationPartial: platform verificationYesYes: binding errors on triggerYes: controls/controlled-by/active descendantManual
SliderYes: SliderYes: accessible labelYes: numeric range/valueYes: arrows/home/endPartial: platform verificationYesYes: bound error/invalid projectionYes: bound error/description targetsManual
TextInputYes: TextInput/SearchBoxYes: explicit label/floating labelYes: value/required/invalid/readonlyYes: text editing keysPartial: platform verificationYesYes: binding errors project automaticallyYes: error/description targetsManual: assertive validation region
TextareaYes: TextInput multilineYes: explicit labelYes: value/required/readonlyYes: text editing keysPartial: platform verificationYes: config and edit guardsYes: binding errors project automaticallyYes: error/description targetsManual: assertive validation region
DropdownYes: ComboBox/ListBox/optionsYes: persistent trigger nameYes: open/selected valuePartial: arrows/Enter/Escape need platform verificationPartial: platform verificationYes: config and input guardsYes: binding errors on triggerYes: controls/controlled-by/active descendantManual
TabsYes: TabList/Tab/TabPanelYes: tab labelsYes: selected/activePartial: roving navigation needs platform verificationPartial: platform verificationYes: disabled config/guardsN/A: not a fieldYes: tab controls panel; panel labelled/controlled by tabManual
ModalYes: DialogYes: dialog titleYes: modal/open stateYes: Escape/focus scopeYes: focus restorationN/A: disable child controls or close dialogN/A: errors belong to fields inside dialogApp-owned descriptions; child field errors supportedManual
FileInputYes: Button triggerYes: persistent FileInput::labelYes: selected filenamesPartial: native picker requires platform verificationPartial: platform verificationYes: picker/drop guardsYes: bound error/invalid projectionYes: bound error/description targetsManual
Search / SearchBoxYes: named editable input; Search suggestions listboxYes: editor labelYes: query/expanded/active suggestionPartial: completion keys need platform verificationYes: editor focus bridged; platform test pendingYes: Search editor disabled stateYes: errors reach editorYes: Search listbox controls/active descendantManual
PaginationYes: List root/Button itemsYes: page/action labelsYes: current page/disabled buttonsPartial: shared activationYes: tab indicesYesN/A: not a fieldApp-owned relationshipsManual
TableYes: Table/Row/Cell/ColumnHeaderYes: contextual column/cell labels; caller supplies table idYes: single-row selected stateYes: arrows/Home/End/Enter/SpaceYes: cell/header tab stops and focus requests; platform test pendingYes: explicit disabled semantic ancestors gate interactionsN/A: display data, not bound fieldsYes: semantic table/row/cell hierarchyManual
ButtonGroupPartial: Button items; caller supplies group nameYes: item labelsYes: selected/disabledPartial: shared activationYes: tab indicesYesN/A: not a fieldApp-owned relationshipsManual
PlayButtonYes: ButtonYes: configured labelYes: pressed/playingPartial: shared activationPartial: platform verificationYesN/A: not a fieldApp-owned relationshipsManual
NavButton / Sidebar navigationYes: links/Menu controlsYes: page labels/MenuApp-owned: active page statePartial: shared activationYes: tab indicesYes: explicit disabled semanticsN/A: not a fieldApp-owned routing relationshipsManual
Alert / ToastYes: Alert/StatusYes: message/title and dismiss nameYes: dismissible/timerYes: dismiss controls have tab stops and shared activationPartial: platform verificationN/A: notification; dismiss control can use disabled semanticsN/A: not a fieldApp-owned relationshipsYes: live-region projection; Manual: actual reader delivery

Implemented Gap Closures

  • Bound controls automatically project invalid state and an error-message child. Existing descriptions and error relationships are preserved and restored on validation recovery. Composite controls route errors to the editable trigger.
  • .error(|errors| ...) renders visible error content below supported form controls, including typed Selects, Forms, and submit buttons. Content refreshes only when nonempty errors change, is removed on recovery, and requests focus restoration when a focused error action disappears. Manual/global errors use BindingErrorState; bound-field errors remain setter-owned.
  • AccessibilityAnnouncement messages create polite/assertive AccessKit live regions, including repeated messages, and expire after one second.
  • Disabled semantics gate accessibility/automation activation and pointer interaction; generated interaction markers are removed on re-enabling without removing application-owned markers. Explicit disabled panels affect descendants.
  • Textarea supports .disabled(...), .read_only(...), and .required(...); protected editors reject text insertion, deletion, cut, and paste.
  • Dropdown and Select expose named listboxes, expanded state, selected values, hidden closed options, and trigger/listbox relationships.
  • Table has directional cell/header navigation and persistent single-row selection. Search installs focus/completion routing and suggestion semantics.
  • Alerts and Toasts expose named, tabbable dismiss buttons. Error/warning Alerts project assertive live regions; informational notices project polite regions.

Evidence includes validation_projects_errors_and_restores_existing_relationships, validation_on_composite_container_reaches_its_focusable_trigger, announcements_project_each_message_including_repeated_text, disabled_semantics_block_automation_and_remove_only_owned_markers, textarea_constraints_project_to_accesskit_and_prevent_edits, dropdown_semantics_link_trigger_menu_and_active_option, table_keyboard_navigates_and_selects_exactly_one_row, search_editor_focus_and_suggestions_expose_a_listbox_and_dismiss, and disabled_radio_group_rejects_activation_and_removes_tab_stops.

This is implementation coverage, not a screen-reader conformance claim.

Required component review

When adding or changing an interactive component, update its row and answer each question below with a source reference or a test name:

Semantics

  • What semantic role is projected?
  • Where does the accessible name come from?
  • What value and state fields are projected?
  • Which keyboard actions are supported?
  • How does focus enter, move through, and leave the component?
  • How is disabled behavior enforced for pointer, keyboard, and automation input?
  • How are invalid state and validation messages represented?
  • Which label, description, error, controls, owns, or active-descendant relationships are emitted?
  • How are important dynamic changes announced?

Verification

  • Add a headless semantic projection test where possible.
  • Add a keyboard/focus system test for composite controls.
  • Add a real-window smoke check for focus and pointer routing.
  • Test at least one screen reader manually before calling platform behavior complete.

The repository’s headless tests verify semantic projection and deterministic file-drop target ordering. They do not verify native focus behavior, pointer routing in a real window, or what a platform screen reader announces. Those rows remain Partial or Manual until the real-window and assistive technology checks above are completed on supported operating systems.