← Back to Native mobile foundation team
See how it helps
Mobile performance and accessibility
Improves responsiveness and assistive access together using measured startup, list, image and interaction behavior.
mobile-performance-accessibility
Team members using this skill
When is it useful?
Use when long mobile lists stutter or screen-reader navigation cannot complete the flow.
What does it help you do?
- Measures startup and frame costs with representative workloads.
- Uses virtualization and bounded image or memory resources.
- Checks semantic labels, focus and VoiceOver or TalkBack behavior.
Try asking this
Optimize a long contact list and verify selection using a screen reader on the target device. Scroll representative data and select an offscreen contact using assistive navigation. Measure frame behavior while verifying recycled rows retain correct labels and selection.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Mobile Performance & Accessibility
Deliver smooth 60/120fps scrolling, fast cold start and low memory footprint on real mobile hardware while ensuring every screen is operable with iOS VoiceOver, Android TalkBack, Dynamic Type and Switch Control.
1. List virtualization and frame-budget discipline (16.6ms / 8.3ms)
- Measure before optimizing: profile in release/profile mode (
flutter run --profile, RN Perf Monitor / Flashlight / Xcode Instruments / Android Studio Profiler), as debug builds skew timings. - Virtualized lists only:
- React Native: use
FlashList,LegendListorFlatList—never.map()inside aScrollViewfor dynamic collections. Pass a stablekeyExtractor, memoizerenderItem(useCallback) and row components (React.memo), avoid inline style/closure allocations in rows, and provideestimatedItemSize/getItemLayout. - Flutter: use
ListView.builder,ListView.separatedorCustomScrollView+SliverList.builderwithconstchild widgets,itemExtent/prototypeItemwhen heights are uniform, and avoidshrinkWrap: truein nested scroll views (useSlivers). - Native: use
LazyVStack/UICollectionViewDiffableDataSource(iOS) andLazyColumnwith stablekey = { it.id }andcontentType(Compose).
- React Native: use
- Keep UI & JS/main threads unblocked:
- Run gesture-driven animations on the UI/render thread (
react-native-reanimatedworklets,useNativeDriver: true, FlutterAnimationControllerscoped to leafAnimatedBuilder/RepaintBoundary). - Offload large JSON parsing, crypto, sorting/filtering and image processing to background threads/isolates (
Isolate.runin Flutter, native workers in RN,Dispatchers.Defaultin Kotlin, Swift concurrency).
- Run gesture-driven animations on the UI/render thread (
2. Startup time (TTI), images and memory management
- Fast cold start: defer non-critical SDK init, analytics and background sync until after the first screen renders (
InteractionManager/ post-frame callback), tying splash dismissal (SplashScreen.preventAutoHideAsync()->hideAsync()) to initial route readiness. - Image sizing & caching: request thumbnails sized to display dimensions (
width * pixelRatio), use cached image components (expo-image,cached_network_image,Coil/Nuke), and release media buffers on unmount to prevent OOM termination.
3. Mobile accessibility (VoiceOver & TalkBack)
- Explicit semantics, roles and states:
- Give every interactive element an accessible role (
accessibilityRole="button"/"switch"/"tab"/"header"in RN;Semantics(button: true, header: true)in Flutter;.accessibilityAddTraits/Modifier.semanticsin native). - Provide a concise, localized
accessibilityLabelfor every icon-only button, close button, avatar and badge, and expose state (disabled,selected,checked,busy,expanded).
- Give every interactive element an accessible role (
- Composite card grouping & custom actions:
- Group multi-line list rows/cards into one focusable element (
accessible={true}in RN,MergeSemanticsin Flutter,.accessibilityElement(children: .combine)in SwiftUI,Modifier.semantics(mergeDescendants = true)in Compose) so screen readers read the card in one swipe instead of 6 separate stops. - Attach
accessibilityActions/CustomAccessibilityActionfor secondary row actions (Delete, Favorite, Share) so screen-reader and Switch Control users never depend on swipe gestures.
- Group multi-line list rows/cards into one focusable element (
- Focus management, touch targets, Dynamic Type (200%) & Reduced Motion:
- Move focus to opened modals/dialogs, restore on close, and announce async errors/toasts (
AccessibilityInfo.announceForAccessibility,accessibilityLiveRegion="polite",SemanticsService.announce). - Enforce hit targets
>= 44x44 pt(iOS) /48x48 dp(Android) (hitSlop/MaterialTapTargetSize.padded). - Never fix text container heights in pixels; allow layouts to reflow at 200% font scaling and honor OS reduced-motion settings (
isReduceMotionEnabled/MediaQuery.disableAnimationsOf(context)).
- Move focus to opened modals/dialogs, restore on close, and announce async errors/toasts (
Before you finish
- Dynamic lists are virtualized with stable keys, memoized/
constrows and no nestedshrinkWrap. - Animations run on the UI thread; heavy CPU work and large images do not block frames or leak memory.
- Controls have roles, localized labels, states, card grouping and
>= 44pt/48dphit targets. - Screens announce async errors/modals, survive 200% font scaling, and respect reduced motion.
Included files 2
LICENSE.txtSKILL.md
