Skip to content

feat(player): add a fullscreen button to the preview player - #7726

Open
robinebers wants to merge 1 commit into
heygen-com:mainfrom
robinebers:feat/player-fullscreen-button
Open

robinebers wants to merge 1 commit into
heygen-com:mainfrom
robinebers:feat/player-fullscreen-button

Conversation

@robinebers

Copy link
Copy Markdown
Contributor

Why

A HyperFrames video embedded in a page plays at whatever size the page gives it. In a small preview, like a 512 × 268 side panel, the details are hard to see, and the player offers no way to make it bigger. People expect the fullscreen button they know from other video players, and it isn't there.

What changes

The control bar now ends with a fullscreen button.

  • Click it and the player fills the screen. The controls come with it, so play, pause, the timeline, volume and speed all still work.
  • Click it again or press Esc to put the player back in the page. Playback carries on.
  • The button always shows the right icon and name ("Full screen" or "Exit full screen"), however fullscreen ends.
  • It works from the keyboard like the other buttons.
  • It only appears where the page is allowed to go fullscreen. iPhone Safari has no fullscreen for page elements, and an iframe needs allow="fullscreen", so the button stays out of the bar there.
  • A page that doesn't want it adds disable-fullscreen (or sets player.disableFullscreen = true).
  • hyperframes play gets the button too, because its page uses the built-in controls.

Before

A player embedded at 512 × 268 with controls and sandbox-origin="opaque". The bar has play, timeline, time, volume and speed, and nothing that makes the video bigger.

Before: the control bar has no fullscreen button

After

The same embed. The bar ends with the fullscreen button.

After: the control bar ends with a fullscreen button

One click later the player fills the screen, controls included (Chrome, 1920 × 1080).

After: the player fills the screen with its controls

A 13-second screen recording shows a click into fullscreen, playback there, and Esc back to the page, where the video keeps playing.

Test plan

  • Unit tests added/updated. 10 new cases in controls.test.ts and hyperframes-player.test.ts cover where the button appears, its names and icons, changes it didn't cause, a refused request (no unhandled rejection, name unchanged), cleanup on destroy, and that its click doesn't play the video. bun run --cwd packages/player test passes all 589 tests.
  • Manual testing performed. Real fullscreen was checked by hand in a visible Chrome 157 window with real mouse and keyboard input, on the embed above. A click on the button fills the screen with the player, and play and pause work there. The Esc key brings the player back with its playback position, and the button reads "Full screen" again. Enter and Space on the focused button go in and out of fullscreen. The screen recording above shows the click, playback in fullscreen and Esc.
  • The existing player browser tests (test:browser-security, test:browser-box) and the Studio tests that turn on player controls still pass.
  • Player typecheck and build, oxlint, oxfmt, fallow, comment citations, comment ratchet, git diff --check and bun run verify:packed-manifests (with pnpm 10.17.1) pass.
  • Documentation updated. The README and docs/packages/player.mdx get the new controls wording, a disable-fullscreen row, one paragraph and the disableFullscreen property.
  • Comments follow CONTRIBUTING.md "Comments". The one new comment in source says why a refused request is safe to ignore.

Not checked: Safari, Firefox, and real iPhone and iPad devices.

How

  • The button calls requestFullscreen() on the <hyperframes-player> element, not on its iframe, so the controls in its shadow root stay on screen. When the player is already fullscreen it calls document.exitFullscreen().
  • It reads its state from player.matches(":fullscreen") on every fullscreenchange. That also covers a player inside another shadow root, where document.fullscreenElement names the outer host.
  • It is created only when document.fullscreenEnabled is true. A refused request still fires fullscreenerror on the player.
  • disable-fullscreen is one CSS rule (:host([disable-fullscreen]) .hfp-fullscreen-btn { display: none }), so it works at any time without a new observed attribute.
  • The icons are Material's fullscreen glyphs at 20 px, like the volume icons, and the names match the slideshow's fullscreen button in this package.
  • Raises the player's package size budget (packed 157,145 → 160,200, unpacked 541,601 → 549,500). With CI's pnpm 10.17.1, main packs to 158,705 bytes (544,891 unpacked) and this branch to 160,137 (549,402). The difference is about 1.3 KB in each of the three bundles and 575 bytes of README.

Related work

No issue or PR covers fullscreen for the embeddable player. #997 added a fullscreen preview to Studio's own player controls, and the slideshow in this package already has a fullscreen button. Like the speed menu (#241) and the volume control (#651), the button is on by default, and the opt-out attribute follows disable-click-to-play (#4505).

The button puts the whole player, controls included, in fullscreen and follows every
fullscreen change. Set disable-fullscreen to hide it.

It raises the player's package size budget. With pnpm 10.17.1, main packs to 158,705 bytes
(544,891 unpacked) and this branch to 160,137 (549,402).
@mintlify

mintlify Bot commented Nov 14, 2026

Copy link
Copy Markdown

Preview approval required

This pull request comes from a fork, so Mintlify won't build a preview until someone with write access approves commit 357fd27.

Approve preview

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant