as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
AWS
Documentation
Support
Contact Us
My Cases
Get Started
Design and Develop
Publish
Reference
Support

TVFocusGuide

TVFocusGuide helps you to write intuitive TV apps. It supports autofocus that helps in finding/recovering the focus as well as remembering the focus on multiple visits. It also supports trapping and focus redirection that allows you to customize the focus behavior in your app.

This component makes sure that focusable controls can be navigated to, even if they are not directly in line with other controls. An example is provided in RNTester that shows two different ways of using this component.

Prop Value Description
destinations any[]? Array of Components to register as destinations of the FocusGuideView
autoFocus boolean? If true, TVFocusGuide will automatically manage focus for you. It will redirect the focus to the first focusable child on the first visit. It also remembers the last focused child and redirects the focus to it on the subsequent visits. destinations prop takes precedence over this prop when used together.
trapFocus* (Up, Down, Left, Right) Prevents focus escaping from the container for the given directions.  

The following animation shows navigating controls when using TVFocusGuideView.

More information on the focus handling improvements above can be found in this article.

Example

Copied to clipboard.


import React from 'react';
import {
  Dimensions,
  View,
  StyleSheet,
  TouchableHighlight,
  Text
} from 'react-native';
import {
  TVFocusGuideView
} from '@amazon-devices/react-native-kepler';

const screenHeight = Dimensions.get('window').height;
const scale = screenHeight / 1080;
const width = 200 * scale;
const height = 120 * scale;
const theme = {
  LinkColor: '#0984ffff',
  LabelColor: '#ffffffff',
  TertiarySystemFillColor: '#3085C3',
  BackgroundColor: '#0c0700ff'
};
const Button = React.forwardRef((props: $FlowFixMeProps, ref) => {
  const [focused, setFocused] = React.useState(false);
  return (
    <TouchableHighlight
      onPress={() => {
        if (props.onPress) {
          props.onPress();
        }
        console.log(`${props.label} in press`);
      }}
      onFocus={() => {
        if (props.onFocus) {
          props.onFocus();
        }
        console.log(`${props.label} in focus`);
        setFocused(true);
      }}
      onBlur={() => {
        if (props.onBlur) {
          props.onBlur();
        }
        console.log(`${props.label} in blur`);
        setFocused(false);
      }}
      style={focused ? styles.buttonStyleFocused : styles.buttonStyle}
      ref={ref}>
      <Text style={[{ color: theme.LinkColor }, styles.buttonText]}>
        {props.label}
      </Text>
    </TouchableHighlight>
  );
});

const ThemedView = (props: $FlowFixMeProps) => {
  return (
    <View style={[styles.buttonStyle, props.style]}>
      <Text style={[{ color: theme.LabelColor }, styles.buttonText]}>
        {props.label}
      </Text>
    </View>
  );
};

const TVFocusGuideExample = () => {
  const [destination, setDestination] = React.useState(null);
  const [destinationText, setDestinationText] = React.useState('');
  const destinations = destination?.current ? [destination?.current] : [];

  const buttonTopRight = React.useRef(null);
  const buttonBottomLeft = React.useRef(null);

  const rightButtonInFocusViewContainer = React.useRef(null);
  const containerDestinations = rightButtonInFocusViewContainer?.current
    ? [rightButtonInFocusViewContainer?.current]
    : [];

  const _setDestination = (o: Object, text: string) => {
    setDestination(o);
    setDestinationText(text);
  };

  return (
    <View
      style={[styles.container, { backgroundColor: theme.BackgroundColor }]}>
      <View style={styles.rowContainer}>
        <Button onPress={() => {}} label="Left Top" />
        <Button
          onPress={() => {}}
          onFocus={() => _setDestination(buttonBottomLeft, 'bottom left')}
          ref={buttonTopRight}
          label="Right Top"
        />
        <ThemedView label={`Focus guide points to ${destinationText}`} />
        {/* @ts-expect-error */}
        <TVFocusGuideView
          style={styles.containerFocusGuide}
          destinations={containerDestinations}>
          <Button onPress={() => {}} label="Wrapped button 1" />
          <Button onPress={() => {}} label="Wrapped button 2" />
          <Button
            ref={rightButtonInFocusViewContainer}
            onPress={() => {}}
            label="Wrapped button 3"
          />
        </TVFocusGuideView>
      </View>
      <View style={styles.rowContainer}>
        <Button
          onPress={() => {}}
          onFocus={() => _setDestination(buttonTopRight, 'top right')}
          ref={buttonBottomLeft}
          label="Left Bottom"
        />
        <TVFocusGuideView
          style={[
            { backgroundColor: theme.TertiarySystemFillColor },
            styles.focusGuide
          ]}
          destinations={destinations}>
          <Text style={[{ color: theme.LabelColor }, styles.buttonText]}>
            Focus guide
          </Text>
        </TVFocusGuideView>
        <ThemedView label="" />
        <ThemedView
          style={{
            width: width * 3
          }}
          label="Blue focus guide container above always points to button 3
                  if navigating from outside"
        />
      </View>
    </View>
  );
};

const marginSize = 20 * scale;
const styles = StyleSheet.create({
  container: {
    marginTop: -marginSize,
    height: screenHeight
  },
  rowContainer: {
    flexDirection: 'row',
    padding: 100 * scale
  },
  buttonText: {
    fontSize: 30 * scale
  },
  buttonStyle: {
    width,
    height,
    marginLeft: marginSize,
    marginRight: marginSize,
    marginTop: marginSize,
    marginBottom: marginSize
  },
  buttonStyleFocused: {
    opacity: 0.5,
    borderColor: 'white',
    borderWidth: 4,
    width,
    height,
    marginLeft: marginSize,
    marginRight: marginSize,
    marginTop: marginSize,
    marginBottom: marginSize
  },
  focusGuide: {
    width,
    height,
    marginLeft: marginSize,
    marginRight: marginSize,
    marginTop: marginSize,
    marginBottom: marginSize
  },
  containerFocusGuide: {
    backgroundColor: 'transparent',
    borderColor: 'blue',
    borderWidth: 2,
    flexDirection: 'row'
  }
});

export default TVFocusGuideExample;



Reference

Props

autoFocus

If true, TVFocusGuide will automatically manage focus for you. It will redirect the focus to the first focusable child on the first visit. It also remembers the last focused child and redirects the focus to it on the subsequent visits. destinations prop takes precedence over this prop when used

Type Required
boolean No

trapFocus* (Up, Down, Left, Right)

Prevents focus escaping from the container for the given directions.

Type Required
boolean No

destinations

Array of Components to register as destinations of the FocusGuideView.

Type Required
array of references No

Methods

setDestinations

Copied to clipboard.


setDestinations([ref1, ref2, ...]);

Array of Components to register as destinations of the FocusGuideView.

Type Required
array of references No

Known issues

  • setDestinations callback fails to update if component is not mounted. Either use destinations prop instead or add a delay using setTimeout before calling setDestinations
  • TVFocusGuide fails with Property 'children' does not exist on type when imported in .tsx with strict typechecking. Apps may add {/* @ts-expect-error */} or {/* @ts-ignore */} before component use to avoid the error.

Copied to clipboard.


const TVApp = () => {
  return (
    <View>
      {/* @ts-expect-error */}
      <TVFocusGuideView>
        <Text>Hello World</Text>
      </TVFocusGuideView>
    </View>
  );
};

Additional Resources

For information on additonal libraries, see Supported Third-Party Libraries and Services.


Last updated: Sep 30, 2025