AppProvider
⭐ The mandatory root provider that initializes spatial navigation and manages focus throughout your Smart TV application.
⚠️ Required Component
AppProvider is mandatory for all Smart TV components. Without it, spatial navigation and focus management will not work.
Always wrap your application's root component with AppProvider before using any other UI component.
Import
import { AppProvider } from '@smart-tv/ui';
import '@smart-tv/ui/styles.css'; // Don't forget to import styles
Basic Usage
Wrap your entire application with AppProvider at the root level.
import { AppProvider, Screen, Button } from '@smart-tv/ui';
function App() {
return (
<AppProvider>
<Screen focusKey="main-screen">
<h1>My Smart TV App</h1>
<Button focusKey="play-button" onEnterPress={() => console.log('Play')}>
Play
</Button>
</Screen>
</AppProvider>
);
}
export default App;
With Initialization Config
Configure the spatial navigation system with initialization options.
<AppProvider
init={{
// Enable debug mode to visualize focus (development only)
debug: false,
// Show visual debugging overlay
visualDebug: false,
// Throttle key presses in milliseconds
throttle: 0,
// Enable throttling for key presses
throttleKeypresses: false,
// Use getBoundingClientRect for layout calculations
useGetBoundingClientRect: true,
// Focus DOM nodes directly
shouldFocusDOMNode: false,
// Right-to-left layout support
rtl: false,
// Distance calculation method for spatial navigation
distanceCalculationMethod: 'center', // 'center' | 'edges' | 'corners'
}}
>
<YourApp />
</AppProvider>
With Initial Label
Set an initial label for the app context (useful for app state management).
<AppProvider initialLabel="home">
<YourApp />
</AppProvider>
Using AppProvider Context
Access navigation methods and state using the useAppProvider hook.
import { useAppProvider } from '@smart-tv/ui';
function MyComponent() {
const {
label,
setLabel,
setFocus,
navigate,
getFocusedKey,
setRtl,
} = useAppProvider();
const handleAction = () => {
// Set focus to a specific component
setFocus('play-button');
// Navigate programmatically
navigate('down');
// Get currently focused key
const currentFocus = getFocusedKey();
console.log('Focused:', currentFocus);
// Change layout direction
setRtl(true);
// Update app label/state
setLabel('playing');
};
return (
<button onClick={handleAction}>
Current State: {label}
</button>
);
}
Debug Mode
Enable debug mode during development to see focus events and navigation details in the console.
<AppProvider
init={{
debug: process.env.NODE_ENV === 'development',
visualDebug: true, // Shows visual overlay of focusable elements
}}
>
<YourApp />
</AppProvider>
RTL Support
Enable right-to-left layout for languages like Arabic and Hebrew.
// Set RTL at initialization
<AppProvider init={{ rtl: true }}>
<YourApp />
</AppProvider>
// Or toggle RTL dynamically
function LanguageSelector() {
const { setRtl } = useAppProvider();
return (
<select onChange={(e) => setRtl(e.target.value === 'ar')}>
<option value="en">English</option>
<option value="ar">Arabic</option>
</select>
);
}
Props
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | required | Your application components |
initialLabel | string | '' | Initial app label/state |
init | InitOptions | { debug: false } | Spatial navigation initialization config |
Init Options
Option | Type | Default | Description |
---|---|---|---|
debug | boolean | false | Enable console debug logs |
visualDebug | boolean | false | Show visual debugging overlay |
throttle | number | 0 | Throttle delay in milliseconds |
throttleKeypresses | boolean | false | Enable key press throttling |
rtl | boolean | false | Right-to-left layout |
distanceCalculationMethod | string | center | center | edges | corners |
Context Methods (useAppProvider)
Method | Type | Description |
---|---|---|
label | string | Current app label/state |
setLabel | (label: string) => void | Update app label/state |
setFocus | (focusKey: string) => void | Programmatically focus an element |
navigate | (direction: Direction) => void | Navigate up/down/left/right |
getFocusedKey | () => string | Get currently focused key |
setRtl | (rtl: boolean) => void | Toggle RTL layout |
Best Practices
- Always place AppProvider at the root of your application
- Import the CSS file:
import '@smart-tv/ui/styles.css'
- Enable debug mode during development to troubleshoot focus issues
- Set throttle to 0 unless you experience performance issues
- Use the useAppProvider hook only within components wrapped by AppProvider
- Configure RTL based on user's language preference
Common Patterns
App Structure
// app.tsx or main.tsx
import { AppProvider } from '@smart-tv/ui';
import '@smart-tv/ui/styles.css';
import { MainScreen } from './screens/MainScreen';
export default function App() {
return (
<AppProvider init={{ debug: false }}>
<MainScreen />
</AppProvider>
);
}
With Router
import { AppProvider, RouterProvider, Route } from '@smart-tv/ui';
export default function App() {
return (
<AppProvider>
<RouterProvider initial="/">
<Route path="/" component={HomeScreen} />
<Route path="/player/:id" component={PlayerScreen} />
<Route path="/settings" component={SettingsScreen} />
</RouterProvider>
</AppProvider>
);
}