Video

Atom
Plays a clip with an optional poster: tap to play inline, or full transport controls (the platform's own on iOS and Android, the kit's bar on the web), with boolean fit, autoplay, loop and muted props.

Playground

Every control sets a real prop of VideoProps. The JSX below updates as you go.
0:00
0:00
Props
controls
boolean
Fit
pick one
muted
boolean
loop
boolean
JSX · VideoProps
<Video controls cover />

Variants

3 examples from src/atoms/video/video.md, each rendered live from its own JSX.
0:00
0:00
Controls
<Video source={{ uri: "/video-sample.mp4" }} poster={{ uri: "/video-sample.jpg" }} controls accessibilityLabel="Sample clip with controls" />
Cover
<Video source={{ uri: "/video-sample.mp4" }} poster={{ uri: "/video-sample.jpg" }} cover aspectRatio={1} accessibilityLabel="Square crop of the sample clip" />
Loop and muted
<Video source={{ uri: "/video-sample.mp4" }} poster={{ uri: "/video-sample.jpg" }} loop muted accessibilityLabel="Looping muted sample clip" />

Anatomy

0:00
0:00
1
Frame
2
Poster
3
Play control
4
Scrubber
Dimmed parts appear only in some states or variants.

Props

16 props on VideoProps, grouped as they are declared in source. Required props are marked *.
Prop
Type
Default
Description
Props
2 props
source *
VideoSource
–
The clip: a remote { uri }, or a bundled asset from require(...).
poster
ImageSourcePropType
–
A still shown until the clip's first frame is on screen: a remote { uri } or a bundled asset.
Fit
pick one
14 props
contain
boolean
false
Fit: show the whole picture, letterboxed on black. The default (pick one).
cover
boolean
false
Fit: fill the frame, cropping the overflow (pick one).
stretch
boolean
false
Fit: fill the frame by distorting the aspect ratio (pick one).
autoplay
boolean
false
Start playing as soon as the clip is ready, unless the system asks to reduce motion. Browsers autoplay only muted clips, so pair it with muted on the web.
loop
boolean
false
Play again from the start at the end.
muted
boolean
false
Play without sound.
controls
boolean
false
Transport controls: the platform's own player controls on iOS and Android, the kit's control bar on the web.
aspectRatio
number
–
Width over height of the clip; the frame fills its parent's width at this ratio (default 16 / 9).
radius
VideoRadius
–
Corner radius from the kit's radius scale (pick one): none, sm, md, lg, xl, 2xl, 3xl, full.
accessibilityLabel
string
–
The clip's accessible name, used in the names of its controls (default "video").
onPlayingChange
(playing: boolean) => void
–
Called when playback starts or stops.
onEnd
() => void
–
Called when the clip plays to its end (each time round, when looping).
testID
string
–
E2E hook forwarded to the frame.
style
LayoutStyle
–
Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.

Accessibility and keyboard

Keyboard
Enter
Activates
Space
Activates
Tab
Moves focus on
Semantics
Roles
button
image
img
ARIA on web
aria-hidden
aria-label
Below the platform minimum, the touch area grows to 44 pt on iOS and 48 dp on Android without moving the layout.
From the docs
autoplay starts a clip once it is ready unless the system asks to reduce motion; browsers autoplay only muted clips, and this site's own policy blocks autoplay, so the examples here play on tap. Name every clip with accessibilityLabel: its controls are announced as "Play", "Pause", "Seek" and "Mute" followed by that name. Playback runs through the optional expo-video peer; without it the frame keeps its size and poster in a labeled frame.

Platform skins

The playground's props on each platform: same tree, native shapes, type and touch sizes.
Web
control 10 · field 10 · card 16 · Instrument Sans
iOS
capsule controls · field 8 · card 12 · SF Pro · 44 pt
Android
Material 3 stadium · field 4 · card 12 · Roboto · 48 dp

Usage

<Video source={{ uri: "/video-sample.mp4" }} poster={{ uri: "/video-sample.jpg" }} accessibilityLabel="Sample clip" />
Give it a source (a { uri }, or a bundled asset from require), an optional poster shown until the clip's first frame is on screen, and the clip's aspectRatio (width over height, 16 / 9 by default): the frame fills its parent's width at that ratio and letterboxes the picture on black, inside the v4 hand-off's frame: a 14 px corner on a hairline (radius picks a step of the kit's scale instead). Without controls it is an inline player: the whole picture is one play and pause control, a play emblem sits over the paused picture, and a spinner shows while the clip loads. With controls each platform shows transport its own way: iOS and Android hand the frame to their own player controls, and the web draws the kit's control bar under the picture, with play and pause, the elapsed time, a seek slider, the length, mute, and full screen.
autoplay starts a clip once it is ready unless the system asks to reduce motion; browsers autoplay only muted clips, and this site's own policy blocks autoplay, so the examples here play on tap. Name every clip with accessibilityLabel: its controls are announced as "Play", "Pause", "Seek" and "Mute" followed by that name. Playback runs through the optional expo-video peer; without it the frame keeps its size and poster in a labeled frame.

Tokens

Read from the playground render. Values follow the scheme and the ion hue.
--cyan
--fd
--fm
--ft
--ion
--ln

Related components