WCAG Compliance
WCAG 2.1/2.2 AA compliance guide
Built-in — No separate implementation needed
All accessibility features described on this page are already implemented in the Unveily SDK native components. Web developers do not need to write any native code separately. Both Android and iOS are supported equally.
Overview
The Unveily SDK's native UI components are designed to meet WCAG 2.1/2.2 AA standards. Users who need accessibility (visual impairment, motor impairment, hearing impairment, etc.) can use the app equally.
| Standard | Item | Applied Components | Android | iOS |
|---|---|---|---|---|
| WCAG 1.1.1 | Non-text content (screen reader labels) | Panel, menu, tab, drawer | ✓ | ✓ |
| WCAG 1.4.3 | Contrast ratio (4.5:1 or higher) | Panel background, menu icons | ✓ | ✓ |
| WCAG 1.4.4 | Text resize (up to 200%) | Accessibility panel settings | ✓ | ✓ |
| WCAG 2.1.1 | Keyboard access | All interactive elements | ✓ | ✓ |
| WCAG 2.4.3 | Focus order | AccessibilityPanel, SideDrawer, TopDownMenu | ✓ | ✓ |
| WCAG 2.5.5 | Minimum touch target (48dp / 44pt) | Tabs, drawer rows, menu items | ✓ | ✓ |
| WCAG 2.5.8 | Minimum target size (24dp, WCAG 2.2) | Badge, icon buttons | ✓ | ✓ |
Bridge readiness
The JavaScript examples on this page use window.unveilyBridge (lowercase). If you call a namespace such as accessibilityPanel at mount time in an SPA (React, Vue, etc.), wait for the unveilyGlueReady event before calling. Calls triggered by user actions (e.g. a button click) do not need this.
Focus Trap (WCAG 2.4.3)
When a panel, drawer, or menu opens, focus cycles only within it.
Android: Tab → next element, Shift+Tab → previous element, Tab from the last element → back to first.
// Tab / Shift+Tab cycling — handled automatically by the SDK
setOnKeyListener { _, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_TAB && event.action == KeyEvent.ACTION_DOWN) {
val focusables = getFocusableChildren()
val nextIndex = if (event.isShiftPressed)
(currentIndex - 1 + focusables.size) % focusables.size
else
(currentIndex + 1) % focusables.size
focusables[nextIndex].requestFocus()
true
} else false
}iOS: When the panel opens, UIAccessibility.post(notification: .screenChanged, argument: containerView) is called so VoiceOver immediately moves focus inside the panel.
// VoiceOver automatic notification on panel display — handled automatically by the SDK
UIAccessibility.post(notification: .screenChanged, argument: containerView)Screen Reader Labels (WCAG 1.1.1)
All UI elements automatically have labels that screen readers (Android TalkBack / iOS VoiceOver) can read.
Menu Items — Disabled State Announcement
// Active item: "Camera"
// Disabled item: "Camera, disabled" — not distinguishable by color alone
itemView.contentDescription = if (enabled) label
else "$label, ${getString(R.string.acc_state_disabled)}"// Applied automatically via NSLocalizedString
button.accessibilityLabel = NSLocalizedString("acc_state_disabled", comment: "")
button.accessibilityTraits = enabled ? .button : [.button, .notEnabled]Badge Notification Count Announcement
// TalkBack: "3 notifications"
badge.contentDescription = getString(R.string.acc_badge_count, count)// VoiceOver: "3 notifications"
badge.accessibilityLabel = String(format: NSLocalizedString("acc_badge_count", comment: ""), count)Text Resize (WCAG 1.4.4)
When the user sets the font size in the accessibility panel, the WebView text size is also adjusted.
The accessibility panel offers three steps: normal / large / extraLarge. WCAG 1.4.4 requires that content remains usable at up to 200% zoom; in addition to this panel setting, the WebView honors the user's system text-size setting, so content stays usable at 200% zoom.
| Setting | WebView textZoom |
|---|---|
| Normal | 100% |
| Large | 130% |
| Extra Large | 160% |
You can read the current setting from JavaScript. getSettings takes a callback function name as a string; there is no synchronous form:
window.unveilyBridge.accessibilityPanel.getSettings("onAccessibilitySettingsLoaded");
window.onAccessibilitySettingsLoaded = function (settings) {
console.log(settings.fontSize); // "normal" | "large" | "extraLarge"
};Minimum Touch Targets (WCAG 2.5.5 / 2.5.8)
All interactive elements guarantee a minimum touch size. iOS uses 44pt and Android uses 48dp (physically equivalent).
| Component | Android | iOS |
|---|---|---|
| Accessibility panel item | 48dp × 72dp | 44pt × 66pt |
| Bottom tab | 48dp × 48dp | 44pt × 44pt |
| Drawer row | 48dp × 56dp | 44pt × 52pt |
| Badge | 24dp × 24dp (WCAG 2.2) | 24pt × 24pt (WCAG 2.2) |
High Contrast Mode (WCAG 1.4.3)
Activating high contrast mode in the accessibility panel dynamically changes the background style.
iOS: Background color switches from systemBackground → black, text color from label → white, ensuring a 4.5:1 contrast ratio.
Android: Panel background opacity is increased and blur effects are removed.
window.unveilyBridge.accessibilityPanel.getSettings("onAccessibilitySettingsLoaded");
window.onAccessibilitySettingsLoaded = function (settings) {
if (settings.highContrast) {
// Recommended: also apply a high-contrast style to web content
document.body.classList.add("high-contrast");
}
};Multilingual Accessibility Strings
TalkBack/VoiceOver labels automatically change to match the app language. The SDK supports 3 languages: Korean (ko), English (en), and Japanese (ja).
| String Key | 한국어 | English | 日本語 |
|---|---|---|---|
acc_high_contrast | 고대비 | High Contrast | ハイコントラスト |
acc_font_size | 글꼴 크기 | Font Size | 文字サイズ |
acc_tts | 읽어주기 | Read Aloud | 読み上げ |
acc_easy_read | 쉬운 읽기 | Easy Read | かんたん表示 |
acc_haptic | 진동 피드백 | Vibration | 振動フィードバック |
acc_tab_pin | 탭 바 고정 | Pin Tab Bar | タブ固定 |
acc_left_handed | 왼손 모드 | Left-Hand Mode | 左利きモード |
acc_one_handed | 한손 모드 | One-Hand Mode | 片手モード |
acc_state_disabled | 비활성화됨 | Disabled | 無効 |
acc_state_selected | 선택됨 | Selected | 選択済み |
acc_badge_count | 알림 %ld건 | %ld notifications | %ld件の通知 |
TTS voice languages are separate
The table above lists UI (screen reader label) languages. TTS speech synthesis separately also supports zh-CN (Simplified Chinese) — that is a voice output language, not a UI language.
Motor Impairment Support
Left-Handed Mode
Switches the drawer from the right side of the screen to the left.
window.unveilyBridge.accessibilityPanel.open();The user sets it via the "Left-Hand Mode" toggle in the panel.
One-Handed Mode
Compresses content into the bottom area of the screen for single-handed use.
Always Show Tab Bar
Pins an auto-hiding tab bar to always-visible state.
window.unveilyBridge.accessibilityPanel.open();The user sets it via the "Pin Tab Bar" toggle in the panel.
Easy Read
Simplifies the layout so users with cognitive disabilities can easily navigate.
Web Content Accessibility
Accessibility for web content within the WebView is the responsibility of the web developer.
Apply standard web accessibility techniques such as aria-* attributes, semantic HTML, and focus management.
Use TTS Bridge
By calling TTS directly from web content, you can implement a read-aloud feature without Android TalkBack / iOS VoiceOver. For more details, refer to the Accessibility Bridge API.