# PiPButton

Accessible picture-in-picture toggle button with keyboard support and state reflection

## Import

```tsx
import { PiPButton } from '@videojs/react';
```

## Anatomy

```tsx
<PiPButton />
```

## Behavior

Toggles picture-in-picture (PiP) mode. The button derives two state hooks from `availability`:

- **`disabled`** (`true` until PiP is available, or when the `disabled` prop is set) — sets `aria-disabled="true"` and `data-disabled`. A prop-disabled, available button stays focusable but does not activate.
- **`hidden`** (`true` while PiP is `"unavailable"` or `"unsupported"`) — the component returns `null`.

## Styling

You can style the button based on PiP state:

React renders a `<button>` element. Add a `className` to style it:

```css
/* In PiP mode */
.pip-button[data-pip] {
  background: red;
}

/* Non-interactive (disabled prop) */
.pip-button[data-disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}
```

The button remains hidden until picture-in-picture is available.

The component returns `null`. No extra CSS is required.

## Accessibility

Renders a `<button>` with an automatic `aria-label`: “Enter PiP” or “Exit PiP”. Override with the `label` prop. Keyboard activation: Enter / Space.

## Examples

### Basic Usage

**App.tsx**

```tsx
import { Container, createPlayer, PiPButton } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

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

export default function BasicUsage() {
  return (
    <Player>
      <Container className="media-container">
        <Video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" autoPlay muted playsInline loop />
        <PiPButton
          className="media-pip-button"
          render={(props, state) => <button {...props}>{state.pip ? 'Exit PiP' : 'Enter PiP'}</button>}
        />
      </Container>
    </Player>
  );
}
```

**App.css**

```css
.media-container {
  position: relative;
}

.media-container video {
  width: 100%;
}

.media-pip-button {
  position: absolute;
  right: 10px;
  bottom: 10px;
  padding-block: 8px;
  padding-inline: 20px;
  color: black;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 9999px;
  backdrop-filter: blur(10px);
}
```

## API Reference

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `disabled` | `boolean` | `false` | Whether the button is disabled. |
| `label` | `{ key: string; text: string } \| string \| ((state: PiPButtonState) => Text \| string)` | `''` | Custom label for the button. |

### State

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

| Property | Type | Description |
| --- | --- | --- |
| `pip` | `boolean` | Whether picture-in-picture mode is currently active. |
| `label` | `{ key: string; text: string } \| string` | |
| `availability` | `MediaFeatureAvailability` | Whether picture-in-picture can be requested on this platform. |
| `disabled` | `boolean` | Non-interactive but still focusable (mirrors `aria-disabled`). |
| `hidden` | `boolean` | Whether the button is hidden until picture-in-picture is available. |

### Data attributes

| Attribute | Type | Description |
| --- | --- | --- |
| `data-pip` | — | Present when picture-in-picture mode is active. |
| `data-availability` | `MediaFeatureAvailability` | Indicates picture-in-picture availability (`available`, `unavailable`, `unsupported`). |
| `data-disabled` | — | Present when the button is non-interactive (mirrors `aria-disabled`). |
| `data-hidden` | — | Present when the button is hidden because picture-in-picture is not available. |

---

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