All skills
callstackincubator avatar

/react-native-tv-best-practices

@fa0bad0 official

Reviews React Native TV apps for focus/D-pad navigation, 10-foot UI layout, TV playback/DRM integration, low-memory TV performance, and TV accessibility. Use when building, debugging, or reviewing react-native-tvos, Expo TV, Amazon Vega/Kepler, or React Native web TV targets where the issue depends on remote input, TV focus, TV packaging, TV hardware, or TV playback constraints.

Use this Skill: https://skilld.dev/gh/callstackincubator/agent-skills/react-native-tv-best-practices

This session only. Nothing lands on disk.

referencesfocus-performance.md

≈887 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Focus Performance

On TV, every D-pad press sends focus change events. Careless handling triggers dozens of component updates per press, tanking your frame rate.

Quick Reference

  • Keep focus effects local — don't update global state for visual changes
  • Prefer a single top-level focus frame over per-card overlays
  • Use transforms (scale, translate) not layout properties (width, height) for focus animations
  • Batch focus updates in one render frame

Why It's Worse on TV

  • Focus cascades: Changing focus in one row can cause style updates in multiple rows
  • Platform quirks: Tizen/webOS trigger both onBlur and onFocus for multiple elements in quick succession
  • Remote latency: Bluetooth/IR remotes already have inherent latency — any JS thread delay makes it worse
  • Users hold directions or rapidly press buttons — your app must process multiple focus events per second

Problem: Cascading Renders

Bad — Every card stores its own focus state in React state:

const [isFocused, setIsFocused] = useState(false);
useEffect(() => {
  if (focusedId === id) setIsFocused(true);
  else setIsFocused(false);
}, [focusedId]);

Every change to focusedId re-renders every card in the row.

Better — Memoize the card:

const Card = React.memo(({ isFocused, poster }) => (
  <Image
    style={isFocused ? styles.focused : styles.normal}
    source={poster}
  />
));

Only the focused card re-renders, not the whole row.

Problem: Overlay Flicker

Bad — Unmounting/remounting overlays on focus:

{isFocused && <FocusOverlay />}

Better — Toggle opacity:

<View style={{ opacity: isFocused ? 1 : 0 }}>
  <FocusOverlay />
</View>

Avoids flicker but mounts dozens of hidden overlays consuming memory.

Best — Single top-level focus frame:

const [frame, setFrame] = useState(null);
const onCardFocus = (ref) => {
  ref.current?.measure((x, y, w, h, pageX, pageY) => {
    setFrame({ x: pageX, y: pageY, w, h });
  });
};

return (
  <View style={{ flex: 1 }}>
    <FlatList data={movies} renderItem={({ item }) => {
      const ref = useRef(null);
      return (
        <Card ref={ref} item={item} onFocus={() => onCardFocus(ref)} />
      );
    }} />
    {frame && (
      <Animated.View style={[styles.absolute, {
        left: frame.x, top: frame.y,
        width: frame.w, height: frame.h
      }]} />
    )}
  </View>
);

One focus frame moves around — no duplication, minimal re-renders.

TV-Specific Checks

  1. Keep focus effects local — Don't update Redux/Zustand for visual focus changes.

  2. Preload focus styles — Shadows, glows, gradients are GPU-expensive to generate on the fly. Pre-render them and toggle visibility.

  3. Batch focus updates — A single D-pad press can fire blur and focus events across multiple elements.

  4. Avoid layout shifts — Changing focus geometry can make the next directional search unstable.

  5. Use platform-specific focus helpers:

    • On Android TV/Fire TV: focusable prop reduces extra focus jumps
    • On Apple TV/Android TV/Fire TV: TVFocusGuideView to control focus without excessive JS

Related Skills

Source: SKILL.md on GitHub

No alerts1mo3 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    This skill provides comprehensive documentation and best practices for developing React Native applications for TV platforms. It contains technical guidelines for focus management, performance, and video playback without any malicious patterns, obfuscation, or unsafe code execution.

  • Socket1mo

    No alerts

  • Snyk1mo

    Risk: LOW · No issues

Signed by skilld at fa0bad0. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated 2 months ago

README badge

README badge for callstackincubator/agent-skills/react-native-tv-best-practices