Accessibility Panel
The optional accessibility panel gives your end users a familiar in-app control surface — the same kind of controls they expect from modern web accessibility widgets, but native to your mobile app. It respects the device’s real accessibility state, so it augments system settings rather than fighting them.
The panel is available on React Native, iOS, Android and Flutter, with the same feature set on every platform. The implementation is platform-native — UIKit on iOS, classic Views on Android, pure React components on RN, pure Flutter widgets on Flutter — so there’s no shared runtime or WebView overhead.
Available Features
Opens the OS accessibility settings for system-wide text size control.
Text SizeExposes a contrast preference your components can read and react to.
High ContrastHonours the system reduce-motion preference and exposes it to your components.
Reduce MotionBlack overlay for screen-reader users who prefer an eyes-off experience.
Screen CurtainDraggable horizontal highlight strip with dimmed regions above and below.
Reading GuideSetup
Step 1: Wrap Your App in the Provider
A11yProvider / AccessibilityProvider is the context root for panel state and device
accessibility detection.
React Native
import { AccessibilityProvider } from '@welcomingweb/react-native-sdk';
export default function App() {
return (
<AccessibilityProvider>
{/* rest of your app */}
</AccessibilityProvider>
);
}Step 2: Drop the Panel Component
React Native
Place <AccessibilityPanel /> as the last child inside your NavigationContainer, after all
navigators, so it layers above the navigation stack.
import {
AccessibilityProvider,
AccessibilityPanel,
createNavigationObserver
} from '@welcomingweb/react-native-sdk';
export default function App() {
return (
<AccessibilityProvider>
<NavigationContainer onStateChange={createNavigationObserver()}>
<Tab.Navigator>{/* screens */}</Tab.Navigator>
<AccessibilityPanel
position="bottom-right"
theme={{ primaryColor: '#3D2ED6' }}
/>
</NavigationContainer>
</AccessibilityProvider>
);
}The panel uses absolute positioning with zIndex 9998–9999. If you can’t see it after adding it, check that it sits after all navigators, not inside a screen component.
Step 3: (Optional) Apply Settings in Your Components
The panel exposes its preferences through hooks or controllers. Read them in your components to honour the user’s choices.
React Native
import { useAccessibilityToolkit } from '@welcomingweb/react-native-sdk';
export function MyCard({ title, body }) {
const { effectiveSettings, getTextStyle, getTouchTargetStyle } =
useAccessibilityToolkit();
if (effectiveSettings.reduceMotion) {
// skip entrance animation
}
return (
<TouchableOpacity style={[styles.card, getTouchTargetStyle()]}>
<Text style={getTextStyle({ fontSize: 20, fontWeight: '600' })}>{title}</Text>
<Text style={getTextStyle({ fontSize: 14 })}>{body}</Text>
</TouchableOpacity>
);
}Panel Props
Every platform accepts the same panel props. Naming varies slightly per language idiom.
| Prop | Type | Default | Description |
|---|---|---|---|
position | enum | bottom-right | FAB position. One of bottom-right, bottom-left, top-right, top-left. |
features | string array | all | Feature IDs to show. Omit to show all. |
theme | object | {} | Override colors: primaryColor, accentColor, backgroundColor, textColor, fabSize. |
onSettingsChange | function | null | Callback when settings change. |
Available feature IDs: textSize, highContrast, reduceMotion, screenCurtain,
readingGuide, screenReader.
Feature Details
Text Size
Opens the OS accessibility settings so the user’s choice persists across every app. The panel
itself does not override text size in your app — respect the system font scale by reading
effectiveSettings.fontScale in your components.
| Platform | Implementation |
|---|---|
| React Native | Linking.openSettings (iOS) / Linking.sendIntent (Android) |
| iOS | UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!) |
| Android | Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS) with fallback to app details |
| Flutter | app_settings package, deep-links to accessibility settings on both platforms |
High Contrast
Toggling high contrast sets settings.highContrast to true. Your components read this and apply
a contrast theme from effectiveSettings.highContrastTheme.
The SDK also respects the system’s high-contrast preference (e.g. Smart Invert on iOS,
Increase contrast on Android) — effectiveSettings.highContrast is the merge of user toggle
OR system preference.
Reduce Motion
The SDK reads the device’s system reduce-motion preference and merges it with the in-panel
toggle. Read effectiveSettings.reduceMotion and skip or shorten animations where relevant:
React Native
const { effectiveSettings } = useAccessibilityToolkit();
const duration = effectiveSettings.reduceMotion ? 0 : 250;The SDK does not patch Animated globally. Read effectiveSettings.reduceMotion in each
animating component and short-circuit the animation yourself.
Screen Curtain
Renders a full-screen black overlay only when a screen reader is active on the device (VoiceOver on iOS, TalkBack on Android, VoiceOver on Flutter iOS, TalkBack on Flutter Android). Toggling the curtain without an active screen reader announces a warning and resets the toggle — this prevents sighted users from accidentally locking themselves out of the app.
Reading Guide
Displays a draggable horizontal highlight strip with dimmed regions above and below for focus tracking. Useful for users with dyslexia, ADHD or cognitive fatigue who benefit from a reduced visual field while reading.
Theming
Override any subset of colours and the FAB size through the theme prop. Unspecified values fall
back to the panel defaults.
React Native
<AccessibilityPanel
position="bottom-right"
theme={{
primaryColor: '#3D2ED6',
accentColor: '#4A3AE8',
backgroundColor: '#FFFFFF',
textColor: '#1E1E2F',
fabSize: 56,
}}
/>Limiting Features
Show only the features relevant to your users. If your app has no screen-reader-friendly content
flow yet, for example, you might hide screenCurtain until it’s ready.
<AccessibilityPanel
features={['textSize', 'highContrast', 'reduceMotion']}
/>The same pattern works on every platform with a features array.
Troubleshooting
Panel not visible — ensure the provider is installed at app startup and that the panel is attached at the window or navigation-root level, not inside a screen component. On Android specifically, the panel needs to be attached to the Activity; re-attach it in every Activity if your app has multiple.
Reduce motion toggle has no effect — the SDK does not patch the platform’s animation APIs
globally. Read effectiveSettings.reduceMotion in each animating component and short-circuit the
animation yourself.
Screen curtain doesn’t darken the screen — the curtain only activates when a screen reader (VoiceOver or TalkBack) is active on the device. This is intentional: it prevents sighted users from locking themselves out. Enable your OS screen reader to test the curtain.
iOS: “Directionality” error in Flutter — on Flutter, the screen-curtain and reading-guide
overlays wrap the child in a Stack only when active, because Stack requires a Directionality
ancestor. If you still see the error, confirm A11yProvider is wrapped above MaterialApp, not
below it.