Skip to content

feat(sandbox): dynamically load skins by styling#989

Merged
sampotts merged 3 commits intomainfrom
codex/sandbox-dynamic-styling
Mar 17, 2026
Merged

feat(sandbox): dynamically load skins by styling#989
sampotts merged 3 commits intomainfrom
codex/sandbox-dynamic-styling

Conversation

@sampotts
Copy link
Copy Markdown
Collaborator

@sampotts sampotts commented Mar 17, 2026

Summary

  • remove sandbox local storage syncing and keep sandbox state local to the shell plus preview iframe
  • dynamically load the correct React and HTML skin implementation based on the current styling
  • collapse the dedicated tailwind sandbox entries and keep styling local to each sandbox tab via the URL

Testing

  • pnpm -F @videojs/sandbox build

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 17, 2026

Deploy Preview for vjs10-site ready!

Name Link
🔨 Latest commit 17fc72c
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/69b9c8943995e60008c84e02
😎 Deploy Preview https://deploy-preview-989--vjs10-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v10-sandbox Ready Ready Preview, Comment Mar 17, 2026 9:33pm

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 17, 2026

📦 Bundle Size Report

🎨 @videojs/html

(no changes)

Presets (7)
Entry Size
/video (default) 22.86 kB
/video (default + hls) 153.21 kB
/video (minimal) 22.73 kB
/video (minimal + hls) 153.22 kB
/audio (default) 21.33 kB
/audio (minimal) 21.32 kB
/background 6.47 kB
Media (5)
Entry Size
/media/background-video 617 B
/media/container 1.91 kB
/media/dash-video 236.04 kB
/media/hls-video 131.29 kB
/media/simple-hls-video 11.95 kB
Players (3)
Entry Size
/video/player 6.33 kB
/audio/player 6.32 kB
/background/player 6.31 kB
Skins (16)
Entry Type Size
/video/minimal-skin.css css 2.99 kB
/video/skin.css css 3.03 kB
/video/minimal-skin js 22.15 kB
/video/minimal-skin.tailwind js 22.44 kB
/video/skin js 22.32 kB
/video/skin.tailwind js 22.63 kB
/audio/minimal-skin.css css 2.26 kB
/audio/skin.css css 2.29 kB
/audio/minimal-skin js 20.74 kB
/audio/minimal-skin.tailwind js 20.78 kB
/audio/skin js 20.79 kB
/audio/skin.tailwind js 21.01 kB
/background/skin.css css 124 B
/background/skin js 999 B
/base.css css 177 B
/shared.css css 43 B
UI Components (21)
Entry Size
/ui/alert-dialog 2.08 kB
/ui/alert-dialog-close 1.22 kB
/ui/alert-dialog-description 1.49 kB
/ui/alert-dialog-title 1.50 kB
/ui/buffering-indicator 1.78 kB
/ui/captions-button 1.75 kB
/ui/controls 1.80 kB
/ui/fullscreen-button 1.75 kB
/ui/mute-button 1.76 kB
/ui/pip-button 1.79 kB
/ui/play-button 1.75 kB
/ui/playback-rate-button 1.77 kB
/ui/popover 3.28 kB
/ui/poster 1.67 kB
/ui/seek-button 1.75 kB
/ui/slider 2.00 kB
/ui/thumbnail 2.11 kB
/ui/time 1.61 kB
/ui/time-slider 2.94 kB
/ui/tooltip 2.58 kB
/ui/volume-slider 2.17 kB

Sizes are marginal over the root entry point.

⚛️ @videojs/react

(no changes)

Presets (7)
Entry Size
/video (default) 18.72 kB
/video (default + hls) 149.50 kB
/video (minimal) 18.73 kB
/video (minimal + hls) 149.48 kB
/audio (default) 14.93 kB
/audio (minimal) 14.97 kB
/background 3.19 kB
Media (4)
Entry Size
/media/background-video 539 B
/media/dash-video 236.19 kB
/media/hls-video 131.64 kB
/media/simple-hls-video 12.38 kB
Skins (14)
Entry Type Size
/video/minimal-skin.css css 2.99 kB
/video/skin.css css 3.03 kB
/video/minimal-skin js 18.64 kB
/video/minimal-skin.tailwind js 21.68 kB
/video/skin js 18.64 kB
/video/skin.tailwind js 21.73 kB
/audio/minimal-skin.css css 2.26 kB
/audio/skin.css css 2.29 kB
/audio/minimal-skin js 14.88 kB
/audio/minimal-skin.tailwind js 16.93 kB
/audio/skin js 14.82 kB
/audio/skin.tailwind js 17.15 kB
/background/skin.css css 90 B
/background/skin js 272 B
UI Components (18)
Entry Size
/ui/alert-dialog 2.72 kB
/ui/buffering-indicator 2.24 kB
/ui/captions-button 2.30 kB
/ui/controls 2.24 kB
/ui/fullscreen-button 2.28 kB
/ui/mute-button 2.27 kB
/ui/pip-button 2.29 kB
/ui/play-button 2.28 kB
/ui/playback-rate-button 2.28 kB
/ui/popover 3.32 kB
/ui/poster 2.12 kB
/ui/seek-button 2.28 kB
/ui/slider 2.97 kB
/ui/thumbnail 2.54 kB
/ui/time 2.33 kB
/ui/time-slider 2.77 kB
/ui/tooltip 3.18 kB
/ui/volume-slider 2.69 kB

Sizes are marginal over the root entry point.

🧩 @videojs/core

(no changes)

Entries (6)
Entry Size
. 4.78 kB
/dom 8.40 kB
/dom/media/custom-media-element 1.81 kB
/dom/media/dash 235.63 kB
/dom/media/hls 131.19 kB
/dom/media/simple-hls 11.84 kB

🏷️ @videojs/element

(no changes)

Entries (2)
Entry Size
. 999 B
/context 936 B

📦 @videojs/store

(no changes)

Entries (3)
Entry Size
. 1.32 kB
/html 700 B
/react 360 B

🔧 @videojs/utils

(no changes)

Entries (10)
Entry Size
/array 104 B
/dom 1.25 kB
/events 227 B
/function 261 B
/object 119 B
/predicate 265 B
/string 148 B
/style 190 B
/time 478 B
/number 158 B

📦 @videojs/spf

(no changes)

Entries (3)
Entry Size
. 40 B
/dom 10.04 kB
/playback-engine 9.94 kB

ℹ️ How to interpret

All sizes are standalone totals (minified + brotli).

Icon Meaning
No change
🔺 Increased ≤ 10%
🔴 Increased > 10%
🔽 Decreased
🆕 New (no baseline)

Run pnpm size locally to check current sizes.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the sandbox to (1) keep skin/source selection in a shared in-memory store (instead of localStorage), and (2) dynamically load the correct React + HTML skin implementations based on the current styling (CSS vs Tailwind), removing the separate *-tailwind templates.

Changes:

  • Replaced localStorage-backed skin/source persistence with a shared store using BroadcastChannel + an in-memory registry.
  • Consolidated Tailwind vs CSS sandboxes by passing styling via URL params and dynamically loading the appropriate skin implementations.
  • Removed dedicated React/HTML Tailwind template directories and updated shell preview URL construction.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/sandbox/templates/react-video/main.tsx Stop importing skin CSS upfront; read styling from URL and pass into VideoSkinComponent.
packages/sandbox/templates/react-simple-hls-video/main.tsx Same as above for SimpleHlsVideo.
packages/sandbox/templates/react-hls-video/main.tsx Same as above for HlsVideo.
packages/sandbox/templates/react-dash-video/main.tsx Same as above for DashVideo.
packages/sandbox/templates/react-audio/main.tsx Same as above for audio skins.
packages/sandbox/templates/react-video-tailwind/main.tsx Removed dedicated Tailwind template.
packages/sandbox/templates/react-video-tailwind/index.html Removed dedicated Tailwind template HTML.
packages/sandbox/templates/react-audio-tailwind/main.tsx Removed dedicated Tailwind template.
packages/sandbox/templates/react-audio-tailwind/index.html Removed dedicated Tailwind template HTML.
packages/sandbox/templates/html-video/main.ts Switch to shared HTML sandbox state + dynamically loaded skin tags.
packages/sandbox/templates/html-simple-hls-video/main.ts Same as above for simple HLS.
packages/sandbox/templates/html-hls-video/main.ts Same as above for HLS.
packages/sandbox/templates/html-dash-video/main.ts Same as above for DASH.
packages/sandbox/templates/html-audio/main.ts Same as above for audio.
packages/sandbox/templates/html-video-tailwind/main.ts Removed dedicated Tailwind template.
packages/sandbox/templates/html-video-tailwind/index.html Removed dedicated Tailwind template HTML.
packages/sandbox/templates/html-audio-tailwind/main.ts Removed dedicated Tailwind template.
packages/sandbox/templates/html-audio-tailwind/index.html Removed dedicated Tailwind template HTML.
packages/sandbox/app/utils/create-shared-store.ts New shared store implementation using a global registry + BroadcastChannel.
packages/sandbox/app/utils/stores.ts Wire skinStore/sourceStore to the shared store and initialize from query params.
packages/sandbox/app/shared/sandbox-listener.ts Replace localStorage + postMessage syncing with shared stores.
packages/sandbox/app/shell/app.tsx Collapse *-tailwind routes; keep styling in URL state; remove iframe postMessage code.
packages/sandbox/app/shell/navbar.tsx Update Tailwind availability logic (no longer disables for DASH).
packages/sandbox/app/shell/preview.tsx Build/open preview URL including skin/styling/source (and set iframe src to it).
packages/sandbox/app/shared/react/skins.tsx Dynamically import the appropriate React skin component and CSS at runtime.
packages/sandbox/app/shared/html/skins.ts New dynamic loader for HTML skin tags (CSS and Tailwind variants).
packages/sandbox/app/shared/html/sandbox-state.ts New shared state helper for HTML templates + “latest loader” to avoid races.
packages/sandbox/app/shared/html/tailwind-setup.ts Refactor to expose Tailwind stylesheet via getTailwindStyles().
packages/sandbox/app/shared/html/stylesheets.ts Use a stable data-sandbox-stylesheet id to replace the active stylesheet link.
packages/sandbox/app/main.tsx Remove pre-mount query-param → localStorage syncing (no longer applicable).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread packages/sandbox/app/shell/preview.tsx Outdated
Comment thread packages/sandbox/app/utils/stores.ts Outdated
Comment thread packages/sandbox/app/utils/stores.ts Outdated
Comment on lines +12 to +13
if (skinParam) skinStore.initialize(skinParam);
if (sourceParam) sourceStore.initialize(sourceParam);
Comment thread packages/sandbox/app/shared/react/skins.tsx Outdated
mihar-22
mihar-22 previously approved these changes Mar 17, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the sandbox to drive skin/source/styling selection via in-memory state + URL params, and dynamically loads the correct React + HTML skin implementations (including Tailwind variants) instead of relying on separate *-tailwind sandbox entries and localStorage syncing.

Changes:

  • Removed localStorage-backed stores/hooks and switched sandbox state initialization to URL params + postMessage updates.
  • Collapsed dedicated Tailwind templates; styling is now selected per sandbox tab via ?styling=....
  • Added dynamic skin loaders for React (@videojs/react/*) and HTML (@videojs/html/*), including Tailwind stylesheet setup.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/sandbox/templates/react-video/main.tsx Reads styling from URL and passes it into the shared VideoSkinComponent; removes eager CSS skin imports.
packages/sandbox/templates/react-video-tailwind/main.tsx Removes the dedicated Tailwind React video template entry.
packages/sandbox/templates/react-video-tailwind/index.html Removes the dedicated Tailwind React video HTML entrypoint.
packages/sandbox/templates/react-simple-hls-video/main.tsx Same as react-video, but for SimpleHlsVideo.
packages/sandbox/templates/react-hls-video/main.tsx Same as react-video, but for HlsVideo.
packages/sandbox/templates/react-dash-video/main.tsx Same as react-video, but for DashVideo.
packages/sandbox/templates/react-audio/main.tsx Reads styling from URL and passes it into the shared AudioSkinComponent; removes eager CSS skin imports.
packages/sandbox/templates/react-audio-tailwind/main.tsx Removes the dedicated Tailwind React audio template entry.
packages/sandbox/templates/react-audio-tailwind/index.html Removes the dedicated Tailwind React audio HTML entrypoint.
packages/sandbox/templates/html-video/main.ts Switches HTML video template to dynamic skin-tag loading and shared in-memory sandbox state.
packages/sandbox/templates/html-video-tailwind/main.ts Removes the dedicated Tailwind HTML video template entry.
packages/sandbox/templates/html-video-tailwind/index.html Removes the dedicated Tailwind HTML video HTML entrypoint.
packages/sandbox/templates/html-simple-hls-video/main.ts Switches HTML simple-HLS template to dynamic skin-tag loading and shared in-memory sandbox state.
packages/sandbox/templates/html-hls-video/main.ts Switches HTML HLS template to dynamic skin-tag loading and shared in-memory sandbox state.
packages/sandbox/templates/html-dash-video/main.ts Switches HTML DASH template to dynamic skin-tag loading and shared in-memory sandbox state.
packages/sandbox/templates/html-audio/main.ts Switches HTML audio template to dynamic skin-tag loading and shared in-memory sandbox state.
packages/sandbox/templates/html-audio-tailwind/main.ts Removes the dedicated Tailwind HTML audio template entry.
packages/sandbox/templates/html-audio-tailwind/index.html Removes the dedicated Tailwind HTML audio HTML entrypoint.
packages/sandbox/app/utils/use-web-storage.ts Deletes localStorage hook wrapper (no longer used).
packages/sandbox/app/utils/use-source-switcher.ts Deletes localStorage-backed source switcher hook.
packages/sandbox/app/utils/use-skin-switcher.ts Deletes localStorage-backed skin switcher hook.
packages/sandbox/app/utils/use-external-store.ts Deletes useSyncExternalStore wrapper for removed stores.
packages/sandbox/app/utils/stores.ts Deletes localStorage-backed stores.
packages/sandbox/app/utils/create-web-storage-store.ts Deletes the generic web-storage store implementation.
packages/sandbox/app/shell/preview.tsx Adds styling and builds iframe URL once per mount (navigation on styling/page change via key).
packages/sandbox/app/shell/navbar.tsx Removes Tailwind disablement for DASH preset; Tailwind is now only disabled for background-video.
packages/sandbox/app/shell/app.tsx Moves initial skin/source to URL-param initialization (no localStorage), updates iframe URL logic, and keeps URL synced to state.
packages/sandbox/app/shared/sandbox-listener.ts Replaces web-storage syncing with URL param initialization + postMessage-driven updates (in-memory).
packages/sandbox/app/shared/react/skins.tsx Introduces dynamic loading for React skin components + CSS imports based on skin/styling.
packages/sandbox/app/shared/html/tailwind-setup.ts Refactors Tailwind setup to expose a shared constructed CSSStyleSheet.
packages/sandbox/app/shared/html/stylesheets.ts Updates stylesheet loading to replace per-kind links via data-sandbox-stylesheet ids.
packages/sandbox/app/shared/html/skins.ts New: dynamic HTML skin/tag loader for CSS and Tailwind variants.
packages/sandbox/app/shared/html/sandbox-state.ts New: shared HTML sandbox state and a “latest loader” helper for async rendering.
packages/sandbox/app/main.tsx Removes pre-mount localStorage sync (no longer applicable).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread packages/sandbox/app/shared/sandbox-listener.ts
Comment thread packages/sandbox/app/shared/react/skins.tsx Outdated
Comment thread packages/sandbox/app/shared/html/sandbox-state.ts Outdated
Comment thread packages/sandbox/app/shell/app.tsx
Comment thread packages/sandbox/app/shell/app.tsx
Comment thread packages/sandbox/app/shell/app.tsx
Comment thread packages/sandbox/templates/html-video/main.ts
Comment thread packages/sandbox/app/shared/sandbox-listener.ts
@sampotts sampotts force-pushed the codex/sandbox-dynamic-styling branch from 1482383 to 17fc72c Compare March 17, 2026 21:33
@sampotts sampotts merged commit c5ad81c into main Mar 17, 2026
20 checks passed
@sampotts sampotts deleted the codex/sandbox-dynamic-styling branch March 17, 2026 21:38
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.

3 participants