Skip to content

fix(docs): split ejected React skin sample into player + component files#1588

Open
R-Delfino95 wants to merge 1 commit into
videojs:mainfrom
R-Delfino95:fix/ejected-react-skin-fast-refresh-1484
Open

fix(docs): split ejected React skin sample into player + component files#1588
R-Delfino95 wants to merge 1 commit into
videojs:mainfrom
R-Delfino95:fix/ejected-react-skin-fast-refresh-1484

Conversation

@R-Delfino95

@R-Delfino95 R-Delfino95 commented May 22, 2026

Copy link
Copy Markdown
Collaborator

fix(docs): split ejected React skin sample into player + component files

Closes #1484

Summary

  • Split the ejected React skin sample into player.ts (owns the createPlayer({ features }) call) and VideoPlayer.tsx / AudioPlayer.tsx (owns the component). Co-locating both in one file made React Fast Refresh bail out — Fast Refresh requires a file to export only React components, and the Player const returned by createPlayer violated that rule.
  • EjectedSkin.astro now renders one tab per file (component file first, player.ts second, CSS last). Filename → Shiki language is inferred from the extension so .ts files highlight as TS instead of TSX.
  • No changes to the actual skin sources in packages/react/src/presets/** — those already export only the component. This is purely a build-output + docs-rendering fix.
  • Companion issues [Docs] Ejected skin sample uses any type, should be unknown #1485 (anyunknown) and [Docs] Next.js ejected skin sample missing 'use client' directive #1486 ('use client' directive) are already closed, so this PR is scoped strictly to Docs: Ejected Skin Sample Causes Fast Refresh Warning in React #1484.

Changes

Build script (site/scripts/build-ejected-skins.ts)

  • flattenSkinIntoPlayer now returns { player: string; component: string } instead of a single concatenated string. The player content is a static template with the two imports and the createPlayer call; the component content carries 'use client', the rest of the imports plus import { Player } from './player';, and the JSX component.
  • processReactSkin returns { tsx: Record<string, string>; jsx: Record<string, string> } keyed by filename (player.ts + VideoPlayer.tsx for the TSX variant; player.js + VideoPlayer.jsx for the JSX variant). tsxToJsx runs per-file.
  • EjectedSkinEntry.tsx/jsx updated to Record<string, string> to match.

Content collection schema (site/src/content.config.ts)

  • ejectedSkins.tsx/jsx Zod schema changed from z.string().optional() to z.record(z.string(), z.string()).optional().

Docs rendering (site/src/components/docs/EjectedSkin.astro)

  • Iterates Object.entries(skin.tsx) to build one <Tab> + <TabsPanel> per file. Component files (*.tsx / *.jsx) sort first so they're the initial tab. The CSS tab stays at the end.
  • lang for <ServerCode> is inferred from the filename extension via a small EXT_TO_LANG map (ts'ts', tsx'tsx', etc.).

Home demo (site/src/components/home/Demo/Demo.astro)

  • The "Take full control" teaser card now reads defaultVideoReact.tsx!['VideoPlayer.tsx']! (the component file only) instead of the whole TSX string. Visually unchanged for end users — still a single code block.

E2E sync (apps/e2e/scripts/sync-ejected-skins.ts)

  • Updated to consume the new tsx record shape. Writes both player.ts and ejected-react-video-skin.tsx (component renamed to keep the existing import path in generate-pages.ts stable). The component file's import { Player } from './player' resolves to the sibling player.ts.

Testing

  • pnpm -F site run ejected-skins → 16 entries written. default-video-react.tsx has keys ['player.ts', 'VideoPlayer.tsx']. player.ts only contains the two imports + export const Player; VideoPlayer.tsx opens with 'use client', imports Player from ./player, and createPlayer appears 0 times in the component file. Same shape for audio, minimal, and Tailwind variants.
  • pnpm -F @videojs/e2e sync-ejected-skins → writes player.ts, ejected-react-video-skin.tsx, and player.css to apps/e2e/apps/vite/src/_generated/.
  • pnpm -F site astro check → 0 errors, 0 warnings.
  • pnpm -F site test → 18 files, 397 tests pass.
  • pnpm -F site dev/docs/framework/react/how-to/customize-skins renders two tabs (VideoPlayer.tsx initial + player.ts) plus the existing CSS tab for each React skin.
  • Manual Fast Refresh smoke test in a scratch Vite+React project — paste both files, edit the component, confirm HMR applies without a full reload.

Note

Medium Risk
Medium risk because it changes the shape of generated ejected-skins.json for React skins and updates multiple downstream consumers (docs UI, home demo, and e2e sync) that rely on that output.

Overview
React ejected-skin generation now outputs multiple files per skin: a separate player.ts/js containing the createPlayer({ features }) export and a VideoPlayer.tsx/AudioPlayer.tsx component that imports Player, replacing the previous single-file TSX/JSX snippet.

Docs and consumers are updated to match the new Record<filename, code> shape: EjectedSkin.astro renders one tab per React file with filename-based syntax highlighting, the home demo displays only VideoPlayer.tsx, the content schema validates tsx/jsx as records, and the e2e sync script now writes both player.ts and the component (renamed to keep the existing e2e import path stable).

Reviewed by Cursor Bugbot for commit 566cfe2. Bugbot is set up for automated code reviews on this repo. Configure here.

The ejected React skin sample co-located the createPlayer({ features })
call and the React component in a single file. React Fast Refresh
requires a file to export only components — the Player const returned
by createPlayer broke that rule and caused HMR to bail out for users
copy-pasting the sample.

Split the output into player.ts (owns createPlayer) and
VideoPlayer.tsx / AudioPlayer.tsx (owns the component). The build
script now emits a Record<filename, source> per skin; EjectedSkin.astro
renders one tab per file with the component as the initial tab. The
e2e sync script and home-page demo were updated to read the new shape.

Closes videojs#1484

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@netlify

netlify Bot commented May 22, 2026

Copy link
Copy Markdown

👷 Deploy request for vjs10-site pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 566cfe2

@vercel

vercel Bot commented May 22, 2026

Copy link
Copy Markdown

@R-Delfino95 is attempting to deploy a commit to the Mux Team on Vercel.

A member of the Team first needs to authorize it.

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

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Docs: Ejected Skin Sample Causes Fast Refresh Warning in React

1 participant