🚧 Glyx is pre-release software. APIs may change before v1.0. Get started →
Documentation
Guides
Accessibility & IME

Accessibility & IME

Glyx draws its entire UI to a GPU canvas, so unlike a DOM-based framework there's no free accessibility tree for the OS to enumerate. Glyx builds one explicitly via AccessKit (opens in a new tab) and wires IME composition into TextInput, so screen readers and CJK input both work.

Both are live-tested — accessibility against Windows Narrator, confirmed working across the full role set below.

Accessibility

Every committed layout pass walks the node tree into an accesskit::TreeUpdate, pushed to the OS accessibility API (Windows UIA, macOS NSAccessibility, AT-SPI on Linux) via accesskit_winit. This is compiled in behind the a11y Cargo feature — check __glyx_hasA11y() from JS if your app needs to detect whether a build has it.

Props

PropTypeDescription
rolestringExplicit AccessKit role — see the table below. Overrides the inferred default.
ariaLabelstringAccessible name announced by the screen reader.
<Pressable role="button" ariaLabel="Close dialog" onPress={onClose}>
  <Icon name="x" />
</Pressable>

Role mapping

role valueAccessKit role
'button'Button
'textbox'TextInput
'checkbox'CheckBox
'radio'RadioButton
'switch'Switch
'link'Link
'image'Image
'heading'Heading
'list'List
'listitem'ListItem
'combobox'ComboBox
'slider'Slider
'none' / 'presentation'GenericContainer (filtered from the platform tree, same as ARIA none)

Without an explicit role, Glyx infers one: <Text>Label, <Image>Image, any node with a visible caret → TextInput, any pressable node → Button, everything else → GenericContainer.

Actions

Wired: Focus, Click, Increment/Decrement (e.g. Slider), and SetValue for numeric values.

⚠️

Known gaps: Expand/Collapse, ScrollIntoView, and text-selection actions aren't wired yet. There's also no keyboard Tab-key focus cycling implementation — focus can be set programmatically and screen readers can navigate their own virtual cursor, but there's no built-in Tab/Shift+Tab traversal across focusable nodes yet.

IME / CJK text input

TextInput handles IME composition end-to-end — not just receiving the OS events, but actually rendering the preedit string inline and committing it into the field's value.

  • Composition (preedit) text renders inline in the field as you type, before you've committed a character.
  • On commit, the composed text is inserted into the real value at the caret — a proper two-phase insertion, not a naive append.
  • The OS candidate window is positioned automatically against the caret.

This covers Chinese, Japanese, Korean, and any other script that needs a composition window — no extra setup required beyond using <TextInput>.

What's genuinely still missing

  • Tab-key focus cycling (keyboard-only navigation between focusable nodes).
  • Expand/Collapse, ScrollIntoView, and text-selection AccessKit actions.
  • An ariaLabel-adjacent "hint" prop (e.g. a longer description alongside the accessible name) — not implemented.
  • Right-to-left TextInput cursor/selection directionality, and bidirectional text mixing within a single field.

See the remaining accessibility gaps roadmap page for more detail on the first two.