Split Components
Use StreamLayerSDKTvContent and StreamLayerSDKTvPauseAd for full control over SDK UI element placement. Place sidebars, notifications, banners, and pause ads independently within your own layout instead of relying on the all-in-one StreamLayerSDKTv wrapper.
Overview
By default, the Integration Guide recommends wrapping your video element with StreamLayerSDKTv. This all-in-one component manages sidebar, notification, banner, and pause ad rendering automatically.
Safe to wrap your video:
StreamLayerSDKTvwraps your video element, which may raise concerns about affecting video rendering. The SDK uses internal fallbacks — if anything goes wrong, your children (video) are always rendered. The SDK will never prevent your video from displaying.
However, if you need fine-grained control over where each UI element is rendered — for example, placing the sidebar outside the video container or customizing notification positions — you can use the split components instead:
| Component | Purpose |
|---|---|
StreamLayerSDKTvContent | Renders sidebars, notifications, or banners |
StreamLayerSDKTvPauseAd | Renders the pause ad overlay |
Both components must be rendered inside a StreamLayerProvider.
Important: Split components do not include any positioning styles by default. If you place them without CSS, nothing will appear on screen. You must define positioning styles yourself using the SDK's internal CSS class names.
When to Use Split Components
| Use Case | Recommended Approach |
|---|---|
| Standard integration, minimal customization | StreamLayerSDKTv |
| Custom layout for sidebar / notification / banner | Split components |
| Pause ad managed separately from other SDK features | Split components |
| Different positioning per UI element type | Split components |
Components
StreamLayerSDKTvContent
Renders interactive SDK content based on the current UI state. Use the notification and banner props to control which type of content is rendered. Without either prop, it renders sidebar content (promotions and questions).
type StreamLayerSDKTvContentProps = {
persistent?: boolean // Persist UI state across re-renders
notification?: boolean // Render notification content
banner?: boolean // Render banner content
}To render all three types, use three separate instances:
<StreamLayerSDKTvContent /> {/* Sidebar */}
<StreamLayerSDKTvContent notification /> {/* Notifications */}
<StreamLayerSDKTvContent banner /> {/* Banners */}Each instance only renders when the SDK has matching content to display.
StreamLayerSDKTvPauseAd
Renders the pause ad overlay independently. Accepts the same props as the pause ad configuration on StreamLayerSDKTv.
type StreamLayerSDKTvPauseAdProps = {
showPauseAd?: boolean
onRender?: (params: { rendered: boolean }) => void
onClose?: () => void
videoPlayerController: VideoPlayerCallback
options?: StreamLayerSDKTvOptions
vastUrls?: Array<{ template?: 'default'; url: string }>
}For detailed documentation on pause ad props and state management (showPauseAd vs pauseAdRendered), see Exposed Pause Ad.
Required CSS Styling
Split components render without positioning. You must add CSS for the internal class names to position elements correctly within your layout.
CSS Class Names
| Class Name | Element |
|---|---|
.SL-AdvertisementWebOs--sidebar | Sidebar panel |
.SL-AdvertisementWebOs--notification | Notification |
.SL-AdvertisementWebOs--banner | Banner |
.SL_PauseAd | Pause ad |
Minimal Positioning Styles
The styles below are the minimum required to position SDK elements on screen. Without them, split components will render in the DOM but will not be visible. Apply these in your global CSS or a styled-component wrapping the video container:
/* Sidebar – anchored to the right edge */
.SL-AdvertisementWebOs--sidebar {
position: absolute;
width: 350px;
right: 0;
top: 0;
bottom: 0;
}
/* Notification – anchored to the bottom-left */
.SL-AdvertisementWebOs--notification {
position: absolute;
left: 0;
bottom: 0;
top: auto;
z-index: 1000;
}
/* Banner – bottom bar, leaving room for the sidebar */
.SL-AdvertisementWebOs--banner {
position: absolute;
left: 10px;
right: 360px; /* 350px sidebar + 10px gap */
bottom: 10px;
top: auto;
z-index: 1000;
height: 90px;
}
/* Pause Ad – right-aligned overlay */
.SL_PauseAd {
width: 300px !important;
left: auto !important;
}Adjust values to match your app's layout. For example, the right: 360px on the banner accounts for a 350px sidebar plus a 10px gap — update accordingly if you change the sidebar width.
Discovering Additional Class Names
You can inspect SDK elements in your browser's developer tools to discover additional internal class names. All rendered SDK elements can be further styled using regular CSS targeting these class names. This gives you full flexibility to customize the look and positioning beyond the minimal styles above.
useStreamLayerUI Hook
The useStreamLayerUI hook exposes boolean flags that reflect the current SDK UI state. With split components, you can use these flags to control when and where each element renders — giving you full ownership of the rendering logic.
import { useStreamLayerUI } from '@streamlayer/web-os'Available Flags
| Flag | Description |
|---|---|
promotionSidebar | A promotion sidebar is ready to display |
promotionNotification | A promotion notification is ready to display |
promotionBanner | A promotion banner is ready to display |
promotionOverlay | A promotion overlay is ready to display |
promotionExternalAd | An external ad promotion is ready to display |
app | An interactive app (poll, trivia, etc.) is active |
appSidebar | An app sidebar is ready to display |
appBanner | An app banner is ready to display |
appNotification | An app notification is ready to display |
onboardingNotification | An onboarding notification is ready to display |
exposedPauseAd | A pause ad is currently exposed |
Conditional Rendering Example
Each StreamLayerSDKTvContent instance already handles its own rendering internally — it only displays content when the SDK has matching data. You do not need to conditionally render these components yourself for them to work correctly.
However, combining useStreamLayerUI flags with conditional rendering gives you greater customization control. For example, you can:
- Adjust your layout dynamically — resize the video area when a sidebar appears, or shift controls when a banner is active
- Add custom animations or transitions when SDK elements mount or unmount
- Introduce delays before showing or hiding elements
- Completely remove component containers from the DOM when not in use, giving you full control over your page structure
import { useStreamLayerUI, StreamLayerSDKTvContent } from '@streamlayer/web-os'
const SDKOverlays = () => {
const uiState = useStreamLayerUI()
const hasSidebar = uiState.promotionSidebar || uiState.app || uiState.appSidebar
const hasNotification = uiState.promotionNotification || uiState.onboardingNotification || uiState.appNotification
const hasBanner = uiState.promotionBanner || uiState.appBanner
return (
<>
{/* Conditionally render sidebar — e.g., to adjust video area width */}
{hasSidebar && (
<StreamLayerSDKTvContent />
)}
{/* Conditionally render notification — e.g., to add a mount animation */}
{hasNotification && (
<StreamLayerSDKTvContent notification />
)}
{/* Conditionally render banner — e.g., to shift controls when active */}
{hasBanner && (
<StreamLayerSDKTvContent banner />
)}
</>
)
}This pattern is entirely optional — all three StreamLayerSDKTvContent instances can be rendered unconditionally and will work correctly. Use this approach only when you need additional control over your layout or rendering behavior.
For more details on the UI context hook, see Using StreamLayer UI Context.
Full Integration Example
import { useState, useCallback, useRef } from 'react'
import {
StreamLayerProvider,
StreamLayerSDKTvContent,
StreamLayerSDKTvPauseAd,
type VideoPlayerCallback,
} from '@streamlayer/web-os'
import '@streamlayer/web-os/style.css'
export const VideoSplitView = () => {
const [showPauseAd, setShowPauseAd] = useState(false)
const [pauseAdRendered, setPauseAdRendered] = useState(false)
const videoRef = useRef<HTMLVideoElement>(null)
const onClosePauseAd = useCallback(() => {
setShowPauseAd(false)
}, [])
const onRenderPauseAd = useCallback((params: { rendered: boolean }) => {
setPauseAdRendered(params.rendered)
}, [])
const videoPlayerController: VideoPlayerCallback = useCallback((data) => {
if (data.play === true) {
setShowPauseAd(false)
videoRef.current?.play()
}
}, [])
const onVideoPlay = useCallback(() => {
setShowPauseAd(false)
}, [])
const onVideoPause = useCallback(() => {
setShowPauseAd(true)
}, [])
// Always use pauseAdRendered (not showPauseAd) to control UI visibility
const showControls = !pauseAdRendered
return (
<StreamLayerProvider sdkKey="your-sdk-key" event="your-event-id">
<div style={{ position: 'relative', width: '100%', height: '100%' }}>
{/* Video element */}
<video
ref={videoRef}
onPause={onVideoPause}
onPlay={onVideoPlay}
style={{ width: '100%', height: '100%' }}
/>
{/* Your custom controls – hidden when pause ad is rendered */}
{showControls && (
<div className="video-controls">
{/* Play button, timeline, volume, etc. */}
</div>
)}
{/* Split SDK components – place anywhere inside the container */}
<StreamLayerSDKTvContent />
<StreamLayerSDKTvContent notification />
<StreamLayerSDKTvContent banner />
<StreamLayerSDKTvPauseAd
showPauseAd={showPauseAd}
onRender={onRenderPauseAd}
onClose={onClosePauseAd}
videoPlayerController={videoPlayerController}
options={{ showPauseButton: false }}
vastUrls={[
{
template: 'default',
url: 'https://your-vast-tag-url.com/vast.xml',
},
]}
/>
</div>
</StreamLayerProvider>
)
}Add the required positioning styles (see Required CSS Styling above) to your app's stylesheet or a styled wrapper around the video container.
Key Points
- Wrapping video is safe:
StreamLayerSDKTvuses fallbacks internally — your children (video) are always rendered even if the SDK encounters an error. - Three content instances: Use separate
StreamLayerSDKTvContentcomponents for sidebar, notification, and banner — each with the appropriate prop. - CSS is required: Without positioning styles on the SDK's internal class names, elements will not be visible. Use browser dev tools to inspect rendered elements and discover class names for further styling.
- Container must be
position: relative: The split components useposition: absolute, so their parent container needs relative positioning. - Customize rendering with
useStreamLayerUI: EachStreamLayerSDKTvContentinstance handles its own rendering internally. Use the hook's boolean flags for additional customization — adjusting your layout, adding animations, or controlling when component containers are in the DOM. - Pause ad state: Use
pauseAdRendered(fromonRendercallback) — notshowPauseAd— to control your UI visibility. See Exposed Pause Ad for details. - Single provider: All split components must live inside one
StreamLayerProvider. Do not create multiple providers.
Related Documentation
- Integration Guide – All-in-one
StreamLayerSDKTvapproach - Exposed Pause Ad – Pause ad state management and props reference
- Using StreamLayer UI Context – Full reference for
useStreamLayerUIhook - Getting Started – Supported platforms and quick start
Updated 2 days ago
