Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion vega-multi-tv-migration/LICENSE → LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2025 Vega Skills
Copyright (c) 2025 Amazon

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ A collection of **Agent Skills** — structured knowledge packages that give AI
| Skill | Description |
|-------|-------------|
| [vega-multi-tv-migration](vega-multi-tv-migration/SKILL.md) | Migrate Vega OS (Fire TV) apps to multi-platform React Native monorepo supporting Android TV, Apple TV, and more |
| [rn-tv-ui-best-practices](rn-tv-ui-best-practices/SKILL.md) | React Native TV UI best practices for tvOS, Android TV, Fire TV, and Vega OS — focus management, layouts, typography, and remote/D-pad navigation |

## Installation

Expand All @@ -24,6 +25,7 @@ Install a specific skill:

```bash
npx skills add AmazonAppDev/devices-agent-skills --skill vega-multi-tv-migration
npx skills add AmazonAppDev/devices-agent-skills --skill rn-tv-ui-best-practices
```

For more options, see the [skills CLI documentation](https://skills.sh/docs/cli).
Expand Down
16 changes: 16 additions & 0 deletions rn-tv-ui-best-practices/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# rn-tv-ui-best-practices

An agent skill for building React Native TV applications with best-practice UI patterns covering focus management, navigation, layout, typography, color, and keyboard handling.

## Attribution

Based on "The Ultimate Guide to React Native TV Development" (2025), co-authored by Amazon and Callstack.

Book: https://reactnativetv.com

## Authors

- Giovanni Laquidara — [@giolaq](https://github.com/giolaq)
- Karol Latusek — [@Zahoq](https://github.com/Zahoq)
- Anisha Malde — [@anishamalde](https://github.com/anishamalde)
- Michal Pierzchala — [@thymikee](https://github.com/thymikee)
77 changes: 77 additions & 0 deletions rn-tv-ui-best-practices/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
name: rn-tv-ui-best-practices
description: React Native TV UI best practices for tvOS, Android TV, Fire TV, and Vega OS (including react-native-tvos). Use whenever building, reviewing, or debugging a TV / set-top box / streaming (OTT) app. Covers focus management (TVFocusGuideView, hasTVPreferredFocus, trapFocus, requestTVFocus, useTVEventHandler, focus loss/jumping); D-pad / RCU / spatial navigation; swimlanes, hero banners, drawers, tabs, modals, overscan/safe zones; TV typography, contrast, HDR; remote-driven text or voice input.
---

# React Native TV UI Best Practices

Build polished React Native TV apps across tvOS, Android TV, Fire TV, Vega OS.

## When to Apply

Use when user is:
- Building or reviewing TV UI components
- Debugging focus/navigation issues
- Designing layouts for TV (10-foot experience)
- Choosing typography or color for TV displays
- Implementing keyboard/text input on TV

## When NOT to Apply

- Mobile-only React Native apps (no TV target)
- Web apps not targeting TV platforms
- General React Native performance issues unrelated to TV UX

## Quick Decision Tree

```
Starting a new TV app or doing a broad design review?
└─ Read in order: references/ten-foot-experience.md → references/layout-patterns.md → references/typography-and-color.md

Focus / navigation issue?
├─ Not sure which approach to use → references/navigation-and-focus.md (Focus Management Hierarchy)
├─ Focus doesn't start where expected → references/navigation-and-focus.md (hasTVPreferredFocus)
├─ Focus jumps unexpectedly → references/navigation-and-focus.md (Debugging Focus Issues + Common Focus Problems)
├─ Focus disappears (loader/empty/error state) → references/navigation-and-focus.md (Gotchas)
├─ Need modal/overlay focus trap → references/navigation-and-focus.md (Focus Traps)
├─ Back button not restoring focus → references/navigation-and-focus.md (Back Navigation and Focus Restoration)
├─ Need to move focus programmatically → references/navigation-and-focus.md (Imperative Focus)
└─ Cross-platform differences (tvOS vs Android TV vs Vega) → references/navigation-and-focus.md (Platform Focus Engines)

Building screens/components?
├─ Drawer / tabs / modals → references/layout-patterns.md (Navigation Patterns)
├─ Cards / rows / swimlanes / hero banners → references/layout-patterns.md (Common Components)
├─ Buttons / overlays / details panels → references/layout-patterns.md (Common Components)
└─ Safe zones / overscan / multi-aspect-ratio → references/layout-patterns.md (Layout and Safe Zones)

Visual design?
├─ Font sizes / line height / letter spacing → references/typography-and-color.md (Typography)
├─ Color / contrast / accessibility → references/typography-and-color.md (Color and Contrast)
├─ HDR / bright vs dim vs dark room → references/typography-and-color.md (HDR Considerations + Ambient Light Adaptation)
├─ Text over images or video → references/typography-and-color.md (Text Over Images)
└─ Animation / motion / feedback timing → references/ten-foot-experience.md (Feedback, Motion, and Rhythm)

Text input / search / auth?
├─ Reduce typing burden → references/keyboard-handling.md (Input Minimization)
├─ System keyboard + RCU events → references/keyboard-handling.md (Built-In System Keyboard)
├─ Custom keyboard UI → references/keyboard-handling.md (Custom Keyboard)
├─ Voice input → references/keyboard-handling.md (Voice Input)
└─ Phone-as-input / QR auth → references/keyboard-handling.md (Mobile Companion Apps)

Pre-ship review / sanity check?
├─ Focus traps & back navigation → references/navigation-and-focus.md (Verify before ship)
├─ Safe zones & aspect ratios → references/layout-patterns.md (Verify before ship)
├─ Typography sizes & contrast → references/typography-and-color.md (Verify before ship)
├─ Animation timing & input latency → references/ten-foot-experience.md (Verify before ship)
└─ Couch test (real device, real distance, real remote) → references/ten-foot-experience.md (Couch Sanity Checks)
```

## References

| File | When to Load |
|------|--------------|
| [ten-foot-experience.md](references/ten-foot-experience.md) | UX design decisions, remote interaction patterns, animation/motion |
| [layout-patterns.md](references/layout-patterns.md) | Building screens, navigation structure, component patterns, safe zones |
| [typography-and-color.md](references/typography-and-color.md) | Setting font sizes, choosing colors, ensuring readability at distance |
| [navigation-and-focus.md](references/navigation-and-focus.md) | Focus bugs, TVFocusGuideView, focus traps, back navigation, platform differences |
| [keyboard-handling.md](references/keyboard-handling.md) | Search screens, login forms, any text input UI |
130 changes: 130 additions & 0 deletions rn-tv-ui-best-practices/references/keyboard-handling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Keyboard Handling

Input patterns for React Native TV apps. D-pad typing is the slowest interaction on TV — minimize it first, then optimize what remains.

## Input Minimization (Priority #1)

Before building keyboard UI, reduce the need for typing:

- Pre-filled options and smart defaults (past searches, popular searches).
- Voice input via system dictation or `react-native-voice`.
- Real-time validation to minimize corrections.
- Maintain input history so users don't retype.
- QR code authentication (TV shows QR, phone scans to authenticate).
- Mobile companion apps for complex input (auth, casting, search).

## Built-In System Keyboard

Trigger by rendering a standard `TextInput`. Keyboard appears automatically on focus.

### Platform Differences

- **Android TV (Gboard)**: Grid-based, arrow-navigated. Pops up center/bottom, covers UI beneath.
- **Apple tvOS**: Row-based, Siri Remote swipe-friendly. Also supports iOS Remote app and dictation.

### Keyboard Types

Use the appropriate type to minimize friction:

- `default`: Full autocomplete & autocorrect
- `email-address`: @, ., .com shortcuts; autocorrect off
- `numeric`: Numbers only
- `number-pad`: Digits only (PINs, codes)
- `decimal-pad`: Numeric with decimal point
- `phone-pad`: Digits + #, +
- `url`: Includes /, ., .com shortcuts
- Password: Use `secureTextEntry` prop (not a keyboardType)

**iOS-only types:** `ascii-capable`, `ascii-capable-number-pad`, `name-phone-pad`, `numbers-and-punctuation`, `twitter`, `web-search`

**Android-only:** `visible-password`

### Enhancing with RCU Events

Map remote buttons to keyboard actions using `useTVEventHandler`:

```jsx
import { useTVEventHandler } from 'react-native';

const SearchScreen = () => {
const inputRef = useRef(null);
const inputValueRef = useRef('');

const handleSearch = () => {
// Call search API with inputValueRef.current
};

useTVEventHandler((evt) => {
if (evt.eventType === 'play') {
handleSearch(); // "play" button = submit search
}
});

return (
<View>
<TextInput
ref={inputRef}
placeholder="Search TV shows..."
onChangeText={(text) => { inputValueRef.current = text; }}
onSubmitEditing={handleSearch}
/>
</View>
);
};
```

`onSubmitEditing` fires when the text input's submit button is pressed, which is the most common trigger. Depending on your UI, you may also want `onBlur` (submit when focus leaves the field) or to listen for events from surrounding `Pressable` / `Touchable` components (e.g., a dedicated "Search" button next to the input). Pick whichever matches how users actually complete the action in your flow.

## Custom Keyboard

When the system keyboard covers important UI or you need more control:

### Implementation Pattern

```jsx
const [showKeyboard, setShowKeyboard] = useState(false);

return (
<KeyboardAvoidingView behavior="position" style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<TextInput
onFocus={() => setShowKeyboard(true)}
showSoftInputOnFocus={false} // Suppress default keyboard
/>
</View>
{showKeyboard && <CustomKeyboard onKeyPress={handleKeyPress} />}
</KeyboardAvoidingView>
);
```

### Custom Keyboard Considerations

- Set `showSoftInputOnFocus={false}` to suppress the default keyboard.
- Each key button needs two states: **focused** and **selected** (user skips over buttons to reach target letter).
- Wire each button's output to the TextInput value.
- Focus management within the keyboard grid follows standard TV navigation rules.

### Tradeoff

Custom keyboards give full UI control but users must learn your specific layout. The system keyboard is familiar even if less pretty. Only build custom when the system keyboard genuinely blocks critical UI (like YouTube's search with results visible below).

## Voice Input

- **With system keyboard**: Already handles dictation. Just wait for system to fill the TextInput.
- **With custom keyboard**: Need native code. Use `react-native-voice` library.
- Remember: adding voice requires microphone + speech recognition permissions.

## Mobile Companion Apps

Companion apps (YouTube, Netflix, Spotify pattern) offload input to the phone:
- Authentication via QR code (TV shows code, phone scans, backend binds devices via shared token).
- Search input typed on phone keyboard, sent to TV over local network.
- Media casting from phone to TV (no TV-side login needed).

## Key Rules

1. Prioritize input minimization — every keystroke saved is UX gained.
2. Use appropriate keyboard types (don't show full keyboard for a PIN).
3. Maintain input history.
4. Enable voice input where possible.
5. Consider companion app flows for complex authentication.
Loading