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

PropTypeDefaultDescription
childrenReactNoderequiredYour application components
initialLabelstring''Initial app label/state
initInitOptions{ debug: false }Spatial navigation initialization config

Init Options

OptionTypeDefaultDescription
debugbooleanfalseEnable console debug logs
visualDebugbooleanfalseShow visual debugging overlay
throttlenumber0Throttle delay in milliseconds
throttleKeypressesbooleanfalseEnable key press throttling
rtlbooleanfalseRight-to-left layout
distanceCalculationMethodstringcentercenter | edges | corners

Context Methods (useAppProvider)

MethodTypeDescription
labelstringCurrent app label/state
setLabel(label: string) => voidUpdate app label/state
setFocus(focusKey: string) => voidProgrammatically focus an element
navigate(direction: Direction) => voidNavigate up/down/left/right
getFocusedKey() => stringGet currently focused key
setRtl(rtl: boolean) => voidToggle 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>
);
}