Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Media

Video Player

Media

Video Player React component for Tailwind CSS v4

Step PlayerAgent Status Card
Live props
Content
poster
title
Layout
aspectRatio
fit
Appearance
radius
tone
color
captionSize
Behavior
controls
hideDelay2500ms
skipSeconds10s
doubleTapSeek
pip
fullscreen
autoPlay
muted
loop
startTimeStart
exclusive
mediaSession
preload
State
captionsDefault
Code
import { VideoPlayer } from "@/components/ui/video-player"

<VideoPlayer />
  1. Home
  2. Components
  3. Media
  4. Video Player
Pro

Video Player React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React video player with controls that hide while you watch, a chapter scrubber, captions, speed, picture in picture and full screen.

Click or tap the big play button (or anywhere on the picture) to start; with a mouse, a click on the picture plays and pauses and a double click goes full screen. While it plays, the controls and the title fade away after 2.5 s of stillness and come back when you move the mouse, tap or focus a control; the captions glide down with them. Hover the scrubber and it thickens, a thumb appears and a pill shows the time and the chapter under the pointer; press and drag to scrub (a mouse seeks as it moves, a finger seeks on release), chapters are small ticks on the bar. The row has play, skip back / forward 10 s, mute with a volume slider, the time, a captions button (a menu when there are several languages), a speed menu, picture in picture and full screen; on phones the menus open as bottom sheets. On a touch screen a tap shows or hides the controls, a tap on the middle of the picture plays and pauses while they show, the big button is flanked by skip buttons, and a double tap on the left or right third jumps 10 s with a ripple and a pill that counts up as you keep tapping. Keyboard (focus the player or any control): Space or k play and pause, Left / Right seek 5 s, j / l 10 s, Up / Down volume, m mute, 0 to 9 jump to 0% to 90%, Home / End, < and > change the speed, f full screen, c captions on or off, i picture in picture; on the focused scrubber Left / Right seek 5 s, PageUp / PageDown 30 s. While it plays in picture in picture the stage says so and the bar stays usable. A missing file shows a message with a retry button.

Video Player is a Pro React component in the React media components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add video-player, together with Button, Dropdown Menu, Slider, Spinner, Tooltip and 5 more and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add video-player

Video Player is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import VideoPlayer from @/components/ui/video-player.

import { VideoPlayer } from "@/components/ui/video-player"

export function CityTour() {
  return (
    <VideoPlayer
      src="/demo/city-tour.mp4"
      poster="/demo/city-tour.jpg"
      title="City tour"
      tracks={[
        { src: "/demo/city-tour.en.vtt", srclang: "en", label: "English", default: true },
        { src: "/demo/city-tour.ro.vtt", srclang: "ro", label: "Romanian" },
      ]}
      chapters={[
        { start: 0, title: "The main boulevard" },
        { start: 7.8, title: "The mountains" },
        { start: 11, title: "Home" },
        { start: 16, title: "Final" },
      ]}
    />
  )
}

Props

  • src*
    string | VideoSource[]

    The video url, or several { src, type } sources (webm, mp4) for the browser to pick from.

  • posterdefault ""
    string

    The still shown before the first play (it fades out on play). Also the lock-screen artwork.

  • titledefault ""
    ReactNode

    A title in a top scrim while the controls show; when it is a string, also the region name and the lock-screen title.

  • tracksdefault "[]"
    VideoTrack[]

    WebVTT captions { src, srclang, label, kind?, default? }. The native tracks stay hidden and the player draws the active cue itself, above the controls. Tracks on another origin need CORS (the video gets crossOrigin anonymous).

  • chapters
    VideoChapter[]

    { start, title } in seconds: ticks on the scrubber, the chapter in the time pill and next to the time on wide players.

  • aspectRatiodefault "16 / 9"
    string

    CSS aspect ratio of the stage, e.g. 1 / 1 for a listing card or 9 / 16 for a story.

  • fitdefault "contain"
    "contain" | "cover"

    contain letterboxes the whole picture on black, cover crops it to fill the stage.

  • radiusdefault "md"
    "none" | "sm" | "md" | "lg"

    Corner radius of the stage (0 / 12 / 16 / 24px). Full screen drops the corners.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    Colors the played part of the scrubber and the captions-on underline. neutral is white on the black stage in both themes.

  • colordefault ""
    string

    Any CSS color for the played bar; replaces the tone.

  • captionSizedefault "md"
    "sm" | "md" | "lg"

    Caption text size. Each step also grows with the player's own width, so a card and a full-screen player both read well.

  • controlsdefault "auto"
    "auto" | "always" | "none"

    auto hides the controls while playing and idle for hideDelay (paused, a menu open, keyboard focus or scrubbing keep them up); always keeps them; none shows only the picture, for background clips.

  • hideDelaydefault 2500
    number

    Milliseconds of stillness before the controls hide while playing. The mouse cursor hides with them.

  • skipSecondsdefault 10
    number

    Seconds for the skip buttons, a double tap and j / l. Arrow keys seek half of it.

  • doubleTapSeekdefault true
    boolean

    Touch: a double tap on the left or right third seeks by skipSeconds; more taps keep adding and the pill counts.

  • pipdefault true
    boolean

    The picture in picture button (and the i key) where the browser supports it. While it is out, the stage says so.

  • fullscreendefault true
    boolean

    The full screen button, the f key and double click. The whole player goes full screen, so the controls and captions stay ours; phones try to turn to landscape. iOS Safari falls back to its native player.

  • autoPlaydefault false
    boolean

    Starts muted (browsers require it), pauses while scrolled out of view and resumes when back, unless the viewer paused it.

  • muteddefault false
    boolean

    Starts without sound; the mute button stays usable.

  • loopdefault false
    boolean

    Starts again from the beginning when it ends.

  • startTimedefault 0
    number

    Seconds to start from once the metadata loads, for continue watching. 0 starts at the beginning.

  • exclusivedefault true
    boolean

    Starting this player pauses every other exclusive player and audio player on the page.

  • mediaSessiondefault true
    boolean

    While playing, sets the lock-screen title and artwork and handles play, pause and seek from the lock screen and headphones.

  • preloaddefault "metadata"
    "none" | "metadata" | "auto"

    How much the browser loads before play. metadata knows the duration without downloading the film.

  • captionsDefaultdefault ""
    string | "off"

    The caption language on at start (a track srclang), or "off". Empty uses the track marked default, else off.

  • ratesdefault "MEDIA_RATES"
    readonly number[]

    Speeds in the speed menu (0.5 to 2 by default). One rate hides the menu.

  • onPlay
    () => void

    Called when playback starts.

  • onPause
    () => void

    Called when playback pauses, including the automatic pause of autoPlay off screen.

  • onEnded
    () => void

    Called at the end (never while looping).

  • onError
    (error: MediaError | null) => void

    Called when the video cannot be loaded or played.

  • onTimeUpdate
    (seconds: number) => void

    Whole seconds while playing and after seeks, for saving progress.

  • setApi
    (api: VideoPlayerApi) => void

    The media controls (play, pause, seek, second, duration, progress…) plus fullscreen, pip, captions, enterFullscreen(), exitFullscreen(), togglePip() and setCaptions(lang | "off"). Called after mount and whenever the state changes.

  • labels
    Partial<VideoPlayerLabels>

    Every visible and spoken string, English by default: play, pause, replay, seek, skipBack(s), skipForward(s), skippedBack(s), skippedForward(s), volume, mute, unmute, captions, captionsOff, speed, normal, rate(r), pip, exitPip, pipActive, fullscreen, exitFullscreen, error, retry, cancel (the phone sheet button), live, loading, video, position(current, total).

  • classNames
    Partial<Record<"video" | "poster" | "bigPlay" | "spinner" | "captions" | "cue" | "ripple" | "center" | "skip" | "pip" | "title" | "controls" | "scrubber" | "track" | "thumb" | "bubble" | "row" | "button" | "time" | "error" | "live", string>>

    Extra classes for the inner parts.

  • className
    string

    Extra classes for the stage, merged last.

Parts

  • DEFAULT_VIDEO_PLAYER_LABELS

    constant

    The English strings for every button, the scrubber, captions, speed, picture in picture and the screen reader position. Spread it and override a few keys through labels.

  • VideoPlayerApi

    type

    What setApi hands you: the media controls plus fullscreen, pip, captions and the methods to toggle them.

  • VideoTrack

    type

    A captions or subtitles file for tracks: { src, srclang, label, kind?: "subtitles" | "captions", default? }.

  • VideoChapter

    type

    One chapter for the scrubber: { start (seconds), title }.

  • VideoPlayerProps

    type

    The props of VideoPlayer, for wrappers that pass them through.

Examples

Hero background

autoPlay, muted, loop and no controls behind a headline; it pauses when scrolled out of view.

Large captions

English captions on from the start at captionSize lg, drawn above the controls.

Listing video card

A square cover crop in a listing card, three speeds and no picture in picture.

On a phone

Tap for controls, double tap left or right to skip; speed and captions open as bottom sheets.

Chapters with setApi

An outside chapter list that seeks the player and follows the playhead.

Brand tone, resume position

tone brand colors the played bar; startTime resumes at 0:08 like continue watching.

Error

A missing file shows the message and a retry button.

Dependencies

motionlucide-reactbuttondropdown-menusliderspinnertooltipuse-media-controlsuse-media-querymotiontonesui-config

Files

  • components/ui/video-player.tsx

FAQ

Is the React Video Player component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Video Player?

Run npx wingo-ui@latest add video-player. It also adds the Wingo UI items it builds on (Button, Dropdown Menu, Slider, Spinner, Tooltip and 5 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/video-player.

How does Video Player behave on phones?

The row has play, skip back / forward 10 s, mute with a volume slider, the time, a captions button (a menu when there are several languages), a speed menu, picture in picture and full screen; on phones the menus open as bottom sheets.

See also

useMediaControlshookAudio PlayerImage LightboxCarousel

Used in

File System

More React media components

Image CropperLocation MapExcel ViewerDOCX ViewerCSV ViewerDOCX Editor
All 17 React media components
PreviousStep PlayerNext Agent Status Card
0:00 / --:-- · The main boulevard

hideDelay=2500 · skipSeconds=10 · doubleTapSeek=true · exclusive=true · mediaSession=true · preload="metadata" · autoPlay=false · muted=false · loop=false · startTime=0 · captionSize="md" · captionsDefault=""