Skip to content
FrameworkStyle

CaptionsButton

Accessible captions toggle button with availability detection and state reflection

Anatomy

<CaptionsButton />

Behavior

Toggles captions and subtitles on and off. The button checks the media’s text track list for tracks with kind="captions" or kind="subtitles". When none are present, the HTML custom element receives the native hidden attribute and the React component returns null. The raw state remains available as data-availability.

An explicitly disabled button with caption tracks stays visible and focusable with aria-disabled="true" and data-disabled, but does not toggle captions.

When menuTrigger is enabled and multiple caption or subtitle tracks are available, activation opens the linked captions menu instead of toggling captions directly. React enables menuTrigger automatically when a CaptionsButton is rendered inside Menu.Trigger.

Styling

Style the button based on active state:

media-captions-button[data-active] .icon-on { display: inline; }
media-captions-button:not([data-active]) .icon-off { display: inline; }

Style an explicitly disabled, available button:

media-captions-button[data-disabled] {
  cursor: not-allowed;
  opacity: 0.5;
}

The button hides automatically when no caption tracks are available. No availability selector or extra hiding CSS is required.

Accessibility

Renders a <button> with an automatic aria-label: “Disable captions” when active, “Enable captions” when inactive. Override with the label prop. Keyboard activation: Enter / Space.

In menu-trigger mode, the button behaves as a menu trigger and reflects menu state through the trigger attributes.

Examples

Basic Usage

import { CaptionsButton, createPlayer } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

const Player = createPlayer({ features: videoFeatures });

export default function BasicUsage() {
  return (
    <Player.Provider>
      <Player.Container className="media-container">
        <Video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" autoPlay muted playsInline loop>
          <track kind="captions" src="/docs/demos/captions-button/captions.vtt" srcLang="en" label="English" />
        </Video>
        <CaptionsButton
          className="media-captions-button"
          render={(props, state) => (
            <button {...props}>{state.subtitlesShowing ? 'Captions Off' : 'Captions On'}</button>
          )}
        />
      </Player.Container>
    </Player.Provider>
  );
}

API Reference

Props

PropTypeDefaultDetails
disabledbooleanfalse
labelText | string | Text) | function''
menuTriggerbooleanfalse

State

State is accessible via the render, className, and style props.

PropertyTypeDetails
availability'available' | 'unavailable'
disabledboolean
hiddenboolean
subtitlesShowingboolean
labelText | string

Data attributes

AttributeTypeDetails
data-active
data-availability'available' | 'unavailable'
data-disabled
data-hidden