# Add keyboard shortcuts and gestures

Add keyboard shortcuts, tap and double-tap gestures, and on-screen feedback for input actions.

Add keyboard shortcuts and pointer gestures to the player declaratively, with on-screen feedback and screen-reader announcements.

> **Note**
>
> Using a pre-built [skin](https://videojs.org/docs/framework/react/guides/skins)? It already includes the controls shown here. You may still need the media or player setup in this guide. The component examples are for building your own player UI from individual [components](https://videojs.org/docs/framework/react/guides/ui-components).

## Recommended approach

Declare shortcuts with `Hotkey` and gestures with `Gesture` inside the player container. Each maps an input to a player action; the prebuilt skins ship a full set.

```tsx
import { Container, Gesture, Hotkey } from '@videojs/react';
import { Video, VideoPlayer } from '@videojs/react/video';

export default function App() {
  return (
    <VideoPlayer>
      <Container>
        <Video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" muted playsInline />

        <Hotkey keys="Space" action="togglePaused" />
        <Hotkey keys="m" action="toggleMuted" />
        <Hotkey keys="f" action="toggleFullscreen" />
        <Hotkey keys="ArrowRight" action="seekStep" value={5} />
        <Hotkey keys="ArrowLeft" action="seekStep" value={-5} />

        <Gesture type="tap" action="togglePaused" pointer="mouse" region="center" />
        <Gesture type="tap" action="toggleControls" pointer="touch" />
        <Gesture type="doubletap" action="seekStep" value={-10} region="left" />
        <Gesture type="doubletap" action="seekStep" value={10} region="right" />
      </Container>
    </VideoPlayer>
  );
}
```

## How it works

- `Hotkey` binds keys to player actions: `togglePaused`, `toggleMuted`, `toggleFullscreen`, `toggleSubtitles`, `togglePictureInPicture`, `seekStep`, `volumeStep`, `seekToPercent`, `speedUp`, and `speedDown`. Step actions have shared defaults and accept a custom `value`. The actions call the same feature state actions your components use.
- `Gesture` binds pointer input — `tap` and `doubletap` — to the same actions, minus `seekToPercent` and plus `toggleControls`. Bindings are scoped by `pointer` (`mouse` or `touch`) and `region` (`left`, `center`, `right`) — regions split the container’s width, not the rendered video’s — so double-tap-left rewinds while double-tap-right skips forward.
- `StatusAnnouncer` announces action results to screen readers, and the input indicator components render transient on-screen feedback (volume level, captions on/off) the way native players do. The prebuilt skins wire these up.

The prebuilt skins bind the conventional set: Space and `k` toggle playback, `m` mutes, `f` fullscreens, `c` toggles captions, `i` toggles picture-in-picture, arrows seek and change volume, `j`/`l` seek in larger steps, `0`–`9` jump to a percentage, and `<`/`>` change speed.

## Availability and constraints

- Hotkeys listen on the player container by default, so multiple players on a page don’t fight over keys. Pass `target="document"` on a hotkey to make it page-wide — appropriate only when one player owns the page.
- Typing is protected: while focus is in an editable field, single-key bindings are skipped automatically. Modifier combinations (for example `Ctrl+Shift+f`) still fire.
- Repeatable actions (seeking, volume) fire on held keys; toggle actions don’t repeat.
- Touch tap-to-toggle-controls and tap-to-pause are mutually exclusive per pointer type — the skins pause on mouse tap and toggle controls on touch tap, matching platform conventions.
- Gestures and the built-in touch handling coordinate through one recognizer; register gestures declaratively instead of adding raw pointer listeners next to them.

## Common variations

### Customize a shortcut

Render your own `Hotkey` set instead of a skin’s: every binding is just an element, so add, remove, or re-key them freely.

### Seek step size

`seekStep` takes its step from `value` — match your content: 5 seconds for short clips, 15 or 30 for long-form.

## Troubleshooting

### Shortcuts don’t fire

Focus is outside the player container. Click the player first, or move focus into it; hotkeys are player-scoped by design.

### Double-tap seek also toggles pause

Regions overlap: keep single-tap `togglePaused` on `center` only, and double-tap seek on `left` and `right`, as in the skin defaults.

### No visual feedback on keyboard actions

The input indicator components render that feedback; use a prebuilt skin or add `StatusAnnouncer` and the indicator components from the skin source to a custom UI.

## Related pages

### Components

- [Controls](https://videojs.org/docs/framework/react/reference/components/controls): Container component for composing and auto-hiding video player controls on user interaction
- [Tooltip](https://videojs.org/docs/framework/react/reference/components/tooltip): A tooltip component for displaying contextual labels on hover and focus

### API

- [Playback](https://videojs.org/docs/framework/react/reference/api/feature-playback): Play/pause state and actions for the player store
- [Volume](https://videojs.org/docs/framework/react/reference/api/feature-volume): Volume level and mute state for the player store
- [Fullscreen](https://videojs.org/docs/framework/react/reference/api/feature-fullscreen): Fullscreen state and actions for the player store

### Guides

- [Automatically show and hide controls](https://videojs.org/docs/framework/react/guides/controls): Show controls while the user is active, hide them during playback, and toggle them by touch.
- [Accessibility](https://videojs.org/docs/framework/react/guides/accessibility): How Video.js approaches accessibility, and what you should consider if you're deeply customizing your player

---

React documentation: https://videojs.org/docs/framework/react/llms.txt
All documentation: https://videojs.org/llms.txt
