Skip to main content

IFrame Theming

Platforms that embed Closed Caption Creator in an iframe can customize the look of the editor so it feels native to their product. Theming covers UI chrome — the toolbar, panels, buttons, inputs, fonts, borders, and dropdowns — using a small set of design tokens that map onto Bootstrap CSS variables already used throughout the application.

The Konva timeline canvas, caption preview fonts, and QC style guides are not controlled by these APIs. Use setPreviewFontFamily / setPreviewFontSize for preview typography and loadStyleGuide for caption quality rules.

Approaches

There are two complementary ways to theme an iframe build:

  1. Build-time theme CSS — ship a customer stylesheet with the dedicated offline build. The file loads automatically based on the customer system slug. Best for hosted environments that always use one brand (for example a Grass Valley Framelight deployment).
  2. Runtime remote APIs — call setTheme, loadCustomStyles, or clearTheme from the parent page after the PenPal connection is ready. Best when the host needs to drive colors dynamically or share one build across multiple skins.

Most dedicated customer environments use build-time CSS for the baseline look, then optionally use the remote APIs for fine-tuning.

Build-Time Themes

Dedicated offline iframe environments are configured with a customer system slug (for example gv, tv2, or demo). When the system is not demo, the editor loads:

./assets/css/themes/{system}.css

Customer logos follow the same slug pattern:

AssetPath
Toolbar logo./assets/img/logos/{system}.png
Status modal icon./assets/img/logos/{system}-icon.png

Creating a customer theme

  1. Choose a short system slug for the customer.
  2. Add the logo assets named above.
  3. Add a CSS file at assets/css/themes/{system}.css that overrides Bootstrap variables under [data-bs-theme="dark"] (and light if needed).
  4. Prefer token overrides over pasting a host application's full stylesheet — large third-party CSS dumps conflict with Bootstrap and Closed Caption Creator component styles.
  5. Build and deploy the offline iframe package for that customer as usual.

Example theme snippet:

[data-bs-theme="dark"] {
--bs-primary: #408fe0;
--bs-primary-rgb: 64, 143, 224;
--bs-body-bg: #181c24;
--bs-body-color: rgba(255, 255, 255, 0.9);
--bs-secondary-color: rgba(255, 255, 255, 0.6);
--bs-border-color: rgba(255, 255, 255, 0.1);
--bs-light: #232a35;
--bs-link-color: #408fe0;
--bs-link-hover-color: #7cc4f5;
--bs-body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

[data-bs-theme="dark"] .btn-primary {
--bs-btn-color: #fff;
--bs-btn-bg: #408fe0;
--bs-btn-border-color: #408fe0;
--bs-btn-hover-bg: #1a8de8;
--bs-btn-hover-border-color: #1a8de8;
}

Also override .btn-outline-primary --bs-btn-* variables when you change the accent color so outline buttons stay consistent.

Runtime Theme APIs

Call theme methods immediately after connection.promise resolves and before importing media when possible, so users do not see a flash of the default teal branding.

iframe.addEventListener('load', async () => {
const messenger = new Penpal.WindowMessenger({
remoteWindow: iframe.contentWindow,
allowedOrigins: ['https://your-iframe-host.example.com']
});
const connection = Penpal.connect({ messenger, methods: {} });
const remote = await connection.promise;

await remote.setTheme({
primary: '#408fe0',
bodyBg: '#181c24',
bodyColor: 'rgba(255, 255, 255, 0.9)',
borderColor: 'rgba(255, 255, 255, 0.1)',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif'
});

await remote.setProjectName('My Project');
await remote.importMedia(mediaUrl);
await remote.importSubtitle(subtitleUrl, 'subRip');
});

setTheme(tokens)

Applies structured chrome overrides as CSS variables on the document root. Tokens may use short aliases or raw --bs-* variable names. When primary is a hex color and primaryRgb is omitted, the RGB triplet is derived automatically.

Returns { success: boolean, message: string }.

loadCustomStyles(cssText)

Injects or replaces a runtime <style> block with the provided CSS string. Use this for advanced chrome tweaks that go beyond simple token values. Prefer setTheme for color and font overrides.

Returns { success: boolean, message: string }.

clearTheme()

Removes runtime styles and token overrides applied by setTheme / loadCustomStyles. The build-time assets/css/themes/{system}.css file (if present) remains loaded.

Returns { success: boolean, message: string }.

Theme Token Contract

Alias (setTheme)CSS variableTypical use
primary--bs-primaryAccent color, active states
primaryRgb--bs-primary-rgbr, g, b for rgba() helpers
bodyBg--bs-body-bgMain workspace background
bodyBgRgb--bs-body-bg-rgbBackground RGB triplet
bodyColor--bs-body-colorPrimary text
bodyColorRgb--bs-body-color-rgbText RGB triplet
secondaryColor--bs-secondary-colorMuted labels
borderColor--bs-border-colorDividers and panel edges
fontFamily--bs-body-font-familyUI font stack
linkColor--bs-link-colorLinks
linkHoverColor--bs-link-hover-colorLink hover
light--bs-lightPanel / surface fill
danger--bs-dangerError / destructive accents
warning--bs-warningWarning accents
success--bs-successSuccess accents
info--bs-infoInformational accents

You can also pass raw property names such as "--bs-primary" in the setTheme object. Unknown keys are ignored with a console warning.

Scope and Limitations

  • Included: navbar, panels, modals, buttons, form controls, dropdowns, fonts, borders, and related chrome that consume Bootstrap variables.
  • Not included: Konva timeline track/waveform colors, caption burn-in / preview fonts (use display APIs), and QC style guides (use loadStyleGuide).
  • Light / dark: Customer themes should define tokens under [data-bs-theme="dark"] and optionally light. Iframe builds commonly default to dark.
  • Expectation: A perfect pixel match to every host UI is not guaranteed. Matching accent color, surfaces, borders, and typography is usually enough for a cohesive embed.