← Back to Mobile application starters · project planning pack

Skill · Version 1.0.0

Mobile performance and accessibility

Improves responsiveness and assistive access together using measured startup, list, image and interaction behavior.

mobile-performance-accessibility

Agents using this skill

See how it helps

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.

Details…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, LegendList or FlatList—never .map() inside a ScrollView for dynamic collections. Pass a stable keyExtractor, memoize renderItem (useCallback) and row components (React.memo), avoid inline style/closure allocations in rows, and provide estimatedItemSize / getItemLayout.
    • Flutter: use ListView.builder, ListView.separated or CustomScrollView + SliverList.builder with const child widgets, itemExtent / prototypeItem when heights are uniform, and avoid shrinkWrap: true in nested scroll views (use Slivers).
    • Native: use LazyVStack / UICollectionViewDiffableDataSource (iOS) and LazyColumn with stable key = { it.id } and contentType (Compose).
  • Keep UI & JS/main threads unblocked:
    • Run gesture-driven animations on the UI/render thread (react-native-reanimated worklets, useNativeDriver: true, Flutter AnimationController scoped to leaf AnimatedBuilder / RepaintBoundary).
    • Offload large JSON parsing, crypto, sorting/filtering and image processing to background threads/isolates (Isolate.run in Flutter, native workers in RN, Dispatchers.Default in Kotlin, Swift concurrency).

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.semantics in native).
    • Provide a concise, localized accessibilityLabel for every icon-only button, close button, avatar and badge, and expose state (disabled, selected, checked, busy, expanded).
  • Composite card grouping & custom actions:
    • Group multi-line list rows/cards into one focusable element (accessible={true} in RN, MergeSemantics in 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 / CustomAccessibilityAction for secondary row actions (Delete, Favorite, Share) so screen-reader and Switch Control users never depend on swipe gestures.
  • 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)).

Before you finish

  • Dynamic lists are virtualized with stable keys, memoized/const rows and no nested shrinkWrap.
  • 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/48dp hit targets.
  • Screens announce async errors/modals, survive 200% font scaling, and respect reduced motion.

Included files 2

  • LICENSE.txt
  • SKILL.md