Button
A focusable button component optimized for TV remote control navigation with spatial focus support.
Import
import { Button } from '@smart-tv/ui';
Basic Usage
The Button component requires a unique focusKey
for navigation.
<Button
focusKey="my-button"
onEnterPress={() => console.log('Button pressed')}
>
Click Me
</Button>
With Custom Styling
Apply custom styles when focused using the active
prop.
<Button
focusKey="styled-button"
className="px-6 py-3 bg-blue-500 text-white rounded-lg"
active="scale-110 bg-blue-600 shadow-xl"
onEnterPress={() => alert('Clicked!')}
>
Styled Button
</Button>
Disabled State
<Button
focusKey="disabled-button"
disabled={true}
className="opacity-50 cursor-not-allowed"
>
Disabled Button
</Button>
Force Focus
Programmatically focus a button using the forceFocus
prop.
import { useState } from 'react';
function App() {
const [focus, setFocus] = useState(false);
return (
<>
<Button
focusKey="force-button"
forceFocus={focus}
onEnterPress={() => console.log('Focused button clicked')}
>
Force Focus Me
</Button>
<Button
focusKey="trigger"
onEnterPress={() => setFocus(true)}
>
Focus Above Button
</Button>
</>
);
}
Render Props Pattern
Use render props to dynamically render button content based on focus state.
<Button
focusKey="render-button"
onEnterPress={() => console.log('Clicked')}
>
{({ focused, focusSelf }) => (
<div className={`flex items-center gap-2 ${focused ? 'text-blue-500' : ''}`}>
{focused && <span>ā¶</span>}
<span>Play</span>
</div>
)}
</Button>
Event Handlers
<Button
focusKey="event-button"
onEnterPress={(props, details) => {
console.log('Button pressed', props, details);
}}
onEnterRelease={(props, details) => {
console.log('Button released');
}}
onFocus={(layout, props, details) => {
console.log('Button focused');
}}
onBlur={(layout, props, details) => {
console.log('Button blurred');
}}
onArrowPress={(direction, props, details) => {
console.log('Arrow pressed:', direction);
return false; // Prevent navigation
}}
>
Event Button
</Button>
With Payload Data
Pass additional data to event handlers using the payload
prop.
const videoData = { id: 123, title: 'Movie Title' };
<Button
focusKey="play-button"
payload={videoData}
onEnterPress={(props) => {
console.log('Play video:', props.payload);
// Access: props.payload.id, props.payload.title
}}
>
Play Video
</Button>
Mouse Hover Support
Enable mouse hover for hybrid TV/web applications.
<Button
focusKey="hover-button"
hover={true}
className="px-4 py-2 bg-gray-200"
active="bg-blue-500 text-white"
onEnterPress={() => console.log('Clicked')}
>
Hover-enabled Button
</Button>
Button Group
import { Row, Button } from '@smart-tv/ui';
<Row focusKey="button-group" className="flex gap-4">
<Button focusKey="btn-1" onEnterPress={() => console.log('Button 1')}>
Option 1
</Button>
<Button focusKey="btn-2" onEnterPress={() => console.log('Button 2')}>
Option 2
</Button>
<Button focusKey="btn-3" onEnterPress={() => console.log('Button 3')}>
Option 3
</Button>
</Row>
Props
Prop | Type | Default | Description |
---|---|---|---|
focusKey | string | required | Unique identifier for spatial navigation |
children | ReactNode | RenderFunction | - | Button content or render function |
onEnterPress | (props, details) => void | - | Called when Enter/OK is pressed |
onEnterRelease | (props, details) => void | - | Called when Enter/OK is released |
onFocus | (layout, props, details) => void | - | Called when button receives focus |
onBlur | (layout, props, details) => void | - | Called when button loses focus |
onArrowPress | (direction, props, details) => boolean | - | Called on arrow key press |
className | string | - | CSS classes for the button |
active | string | - | CSS classes when focused |
disabled | boolean | false | Disable button interactions |
forceFocus | boolean | false | Programmatically focus button |
hover | boolean | false | Enable mouse hover support |
payload | any | - | Data passed to event handlers |
style | CSSProperties | - | Inline styles |
Best Practices
- Always provide a unique
focusKey
for each button - Use clear, action-oriented button labels
- Provide strong visual feedback with the
active
prop when focused - Make buttons large enough for easy selection (min 48px height recommended)
- Use
payload
to pass additional context to event handlers - Consider using render props for dynamic content based on focus state