Skip to content

Accessibility model

Accessibility in BeeUI is a behavior contract at the component level plus a deliberate hand-off to the platform — it is not a certification, and it never covers the composition decisions you make on top.

Prerequisites: read Cross-platform model first — the platform hand-offs described here (text scaling, direction) follow the same shared-contract/per-platform-evidence split.

“Is this library accessible?” is unanswerable as asked. A component can expose a perfect role, label and state and still land in a screen with three <h1>-equivalent headings, an unlabelled icon button and a modal that returns focus to nowhere. Conversely, a great deal of accessibility is not the library’s to implement at all: text scaling belongs to the OS, and layout direction belongs to the host application.

Splitting the question into three parts — what BeeUI owns, what the platform owns, what you own — makes it answerable, and makes it testable.

┌── you own ────────────────────────────────────────────────────────────┐
│ heading/reading order · modal boundaries in your flows │
│ labels for your icon-only actions · error copy · focus after routing │
│ setting the app's direction · your own animations │
└───────────────────────────────┬───────────────────────────────────────┘
┌── BeeUI owns ─────────────────▼───────────────────────────────────────┐
│ roles · labels/descriptions/state wiring · focus order within a │
│ component · overlay dismissal + focus restoration per contract │
│ live-region announcements where the contract requires them │
│ reading the ambient direction · not blocking font scaling │
└───────────────────────────────┬───────────────────────────────────────┘
┌── the platform owns ──────────▼───────────────────────────────────────┐
│ Dynamic Type / OS text size · browser zoom · reduced-motion signal │
│ RTL authority (I18nManager.isRTL, document dir) · the screen reader │
└───────────────────────────────────────────────────────────────────────┘
  1. Use the semantic control, do not wrap it. Putting a second pressable surface around a BeeUI trigger duplicates the role and breaks keyboard and screen-reader behavior. Put your content inside the trigger.
  2. Keep label, control and error associated. Field establishes that association for you; splitting a label away from its control breaks it silently. See Forms model.
  3. Text scaling is the platform’s, and BeeUI does not fight it. No BeeUI component disables font scaling on native, and Web typography resolves through rem-based custom properties rather than pixel literals — so OS text size and real browser zoom both work by construction. Your fixed heights are what break it.
  4. Direction is read, never forced. BeeUI resolves an explicit direction prop first, then the platform’s own authority, then falls back to left-to-right. Setting the application’s direction stays yours.
  5. Motion may clarify state; it may never carry it. Under a reduced-motion preference, decorative animation reduces while state, focus, loading and success/error feedback stay available. Replacing an animation with an invisible state change is a regression, not a fix.
  6. Touch targets are a floor, not a style. The minimum interactive target holds at every width and in every density mode.
  7. Evidence classes do not substitute for each other. This is the same rule as the cross-platform model, and it matters most here.
Evidence Proves Does not prove
Deterministic component tests The documented roles, labels, states and focus contracts Any live assistive-technology behavior
Automated axe-core scans in a pinned Chromium No automatable violation in the scanned, interacted-with state Full WCAG conformance, or any non-Chromium engine
Native compilation The code builds for iOS and Android Nothing about VoiceOver or TalkBack
Simulator / device runs of recorded flows Native assistive-technology behavior for the cases actually executed Anything outside those cases

BeeUI never presents an automated scan as certification, and never presents a compile as screen-reader proof. Read a claim as scoped to the class behind it.

  • Your composition is where most real failures live. Heading and reading order, modal boundaries across a multi-step flow, focus after a route change and the wording of error announcements are all yours — each primitive can be correct while the screen is not.
  • Label every icon-only action. IconButton will expose what you give it and nothing more.
  • Do not hard-code heights around text. Large text, long localized strings and RTL all change intrinsic size; a fixed row height is an exception that needs a reason.
  • Test with the keyboard, not the pointer. Real Tab, Shift+Tab and Escape find problems clicks never will.
  • Budget device time for assistive technology. It is a class-4 question, and it cannot be closed in a browser.

“BeeUI is accessible, so my app is accessible.”

Component-level correctness is necessary and nowhere near sufficient. The anti-pattern that follows this belief is shipping on a green automated scan: axe-core catches automatable rule violations in one engine, in one rendered state, and a screen can pass it while being unusable with a screen reader.

The second misconception is the opposite reflex — adding accessibilityRole and accessibilityLabel on top of BeeUI components “to be safe”. That usually overrides a correct contract with a less correct one. Check the component reference first; add semantics only for content BeeUI cannot see.