From 1145f09e522ee2e099619c3a617e41e0085b6dce Mon Sep 17 00:00:00 2001 From: Renzo Delfino <75499398+R-Delfino95@users.noreply.github.com> Date: Fri, 12 Jun 2026 14:57:42 -0300 Subject: [PATCH] feat(site): list required css imports per skin in preset reference (#1521) --- site/scripts/api-docs-builder/src/pipeline.ts | 1 + .../api-docs-builder/src/preset-handler.ts | 11 +++++++--- .../api-docs-builder/src/tests/e2e.test.ts | 15 ++++++++----- .../packages/react/src/presets/audio/skin.css | 1 + .../react/src/presets/video/minimal-skin.css | 1 + .../packages/react/src/presets/video/skin.css | 1 + .../docs/api-reference/PresetReference.astro | 21 +++++++++---------- site/src/content/docs/concepts/skins.mdx | 2 +- site/src/types/preset-reference.ts | 1 + 9 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/audio/skin.css create mode 100644 site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/video/minimal-skin.css create mode 100644 site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/video/skin.css diff --git a/site/scripts/api-docs-builder/src/pipeline.ts b/site/scripts/api-docs-builder/src/pipeline.ts index 3c9d6a6c..970240c9 100644 --- a/site/scripts/api-docs-builder/src/pipeline.ts +++ b/site/scripts/api-docs-builder/src/pipeline.ts @@ -549,6 +549,7 @@ export { generateFeatureReferences } from './feature-handler.js'; export interface PresetSkinDef { name: string; tagName?: string; + cssImport?: string; } export interface PresetReference { diff --git a/site/scripts/api-docs-builder/src/preset-handler.ts b/site/scripts/api-docs-builder/src/preset-handler.ts index 5d5e0ece..60798f91 100644 --- a/site/scripts/api-docs-builder/src/preset-handler.ts +++ b/site/scripts/api-docs-builder/src/preset-handler.ts @@ -384,7 +384,7 @@ function scanHtmlDirectory(scanDir: string): { skins: PresetSkinDef[]; mediaElem return { skins, mediaElement }; } -function scanReactDirectory(scanDir: string, barrelPath: string): PresetSkinDef[] { +function scanReactDirectory(scanDir: string, barrelPath: string, presetName: string): PresetSkinDef[] { const skins: PresetSkinDef[] = []; if (!fs.existsSync(scanDir)) return skins; @@ -397,11 +397,16 @@ function scanReactDirectory(scanDir: string, barrelPath: string): PresetSkinDef[ for (const file of files) { const filePath = path.join(scanDir, file); const exports = extractValueExports(filePath); + const basename = path.basename(file, path.extname(file)); + const cssFile = path.join(scanDir, `${basename}.css`); + const cssImport = fs.existsSync(cssFile) ? `@videojs/react/${presetName}/${basename}.css` : undefined; for (const name of exports) { if (isFeatureBundle(name)) continue; if (isReactSkin(name)) { - skins.push({ name }); + const skin: PresetSkinDef = { name }; + if (cssImport) skin.cssImport = cssImport; + skins.push(skin); } } } @@ -426,7 +431,7 @@ function buildPresetReference(preset: PresetInfo, featureBundleMap: Map { expect(ref.html.mediaElement).toBeUndefined(); }); - it('detects React skins', () => { + it('detects React skins with CSS imports', () => { const skins = findPreset('video')!.reference.react.skins; - expect(skins).toEqual(expect.arrayContaining([{ name: 'VideoSkin' }, { name: 'MinimalVideoSkin' }])); + expect(skins).toEqual( + expect.arrayContaining([ + { name: 'VideoSkin', cssImport: '@videojs/react/video/skin.css' }, + { name: 'MinimalVideoSkin', cssImport: '@videojs/react/video/minimal-skin.css' }, + ]) + ); }); it('excludes React tailwind skins', () => { @@ -981,9 +986,9 @@ describe('Preset pipeline (end-to-end)', () => { expect(ref.html.mediaElement).toBeUndefined(); }); - it('detects single React skin', () => { + it('detects single React skin with CSS import', () => { const skins = findPreset('audio')!.reference.react.skins; - expect(skins).toEqual([{ name: 'AudioSkin' }]); + expect(skins).toEqual([{ name: 'AudioSkin', cssImport: '@videojs/react/audio/skin.css' }]); }); it('detects React media element', () => { @@ -1022,7 +1027,7 @@ describe('Preset pipeline (end-to-end)', () => { expect(skinNames).not.toContain('BackgroundVideoPlayerElement'); }); - it('detects React skin', () => { + it('detects React skin without CSS import when no CSS file exists', () => { const skins = findPreset('background')!.reference.react.skins; expect(skins).toEqual([{ name: 'BackgroundVideoSkin' }]); }); diff --git a/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/audio/skin.css b/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/audio/skin.css new file mode 100644 index 00000000..823fb8c0 --- /dev/null +++ b/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/audio/skin.css @@ -0,0 +1 @@ +/* fixture */ diff --git a/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/video/minimal-skin.css b/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/video/minimal-skin.css new file mode 100644 index 00000000..823fb8c0 --- /dev/null +++ b/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/video/minimal-skin.css @@ -0,0 +1 @@ +/* fixture */ diff --git a/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/video/skin.css b/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/video/skin.css new file mode 100644 index 00000000..823fb8c0 --- /dev/null +++ b/site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/presets/video/skin.css @@ -0,0 +1 @@ +/* fixture */ diff --git a/site/src/components/docs/api-reference/PresetReference.astro b/site/src/components/docs/api-reference/PresetReference.astro index 6613a5f6..32a70833 100644 --- a/site/src/components/docs/api-reference/PresetReference.astro +++ b/site/src/components/docs/api-reference/PresetReference.astro @@ -142,17 +142,16 @@ const listFormat = new Intl.ListFormat('en', { style: 'long', type: 'unit' });
{preset.react.skins.length > 0 - ? listFormat - .formatToParts( - preset.react.skins.map((s) => s.name), - ) - .map((part) => - part.type === "element" ? ( - {`<${part.value}>`} - ) : ( - {part.value} - ), - ) + ? preset.react.skins.map((skin) => ( +
+ {`<${skin.name}>`} + {skin.cssImport && ( +
+ {`import '${skin.cssImport}';`} +
+ )} +
+ )) : "–"}
diff --git a/site/src/content/docs/concepts/skins.mdx b/site/src/content/docs/concepts/skins.mdx index 68067eb7..df6042dc 100644 --- a/site/src/content/docs/concepts/skins.mdx +++ b/site/src/content/docs/concepts/skins.mdx @@ -105,7 +105,7 @@ There are currently two options for styling: -- Vanilla CSS where you import the stylesheet in your app. This is the default. +- Vanilla CSS — import the stylesheet listed for each skin in the [preset table](#skins-features-and-presets). This is the default. - Tailwind where you [eject](../how-to/customize-skins#ejecting) the skin and use Tailwind classnames in your app. diff --git a/site/src/types/preset-reference.ts b/site/src/types/preset-reference.ts index 58f7c042..ac3bd650 100644 --- a/site/src/types/preset-reference.ts +++ b/site/src/types/preset-reference.ts @@ -6,6 +6,7 @@ import { z } from 'astro/zod'; export const PresetSkinDefSchema = z.object({ name: z.string(), tagName: z.string().optional(), + cssImport: z.string().optional(), }); export const PresetReferenceSchema = z.object({