diff --git a/configs/storybook/main.js b/configs/storybook/main.ts similarity index 54% rename from configs/storybook/main.js rename to configs/storybook/main.ts index 528645d6a..ce24e7928 100644 --- a/configs/storybook/main.js +++ b/configs/storybook/main.ts @@ -1,22 +1,25 @@ -const fs = require('node:fs'); +import { readFileSync } from 'node:fs'; +import { isObject } from '@guardian/libs'; +import type { StorybookConfig } from '@storybook/react-webpack5'; + +export type { StorybookConfig }; const nodeModulesExclude = { and: [/node_modules/], not: [/@guardian\//], }; -module.exports = { +const config: StorybookConfig = { stories: [], addons: [ '@storybook/addon-a11y', '@storybook/addon-essentials', '@storybook/addon-links', ], - features: { - // used in composition - buildStoriesJson: true, - }, webpackFinal: async (config, { configType }) => { + config.module ??= { rules: [] }; + config.module.rules ??= []; + config.module.rules.push({ test: /\.(ts|tsx)$/, exclude: nodeModulesExclude, @@ -45,11 +48,23 @@ module.exports = { }); // update storybook webpack config to transpile *all* JS - config.module.rules.find( - (rule) => String(rule.test) === String(/\.(cjs|mjs|tsx?|jsx?)$/), - ).exclude = nodeModulesExclude; + for (const rule of config.module.rules) { + if (isObject(rule) && rule.test instanceof RegExp) { + if ( + rule.test.test('file.js') || + rule.test.test('file.cjs') || + rule.test.test('file.mjs') || + rule.test.test('file.jsx') || + rule.test.test('file.ts') || + rule.test.test('file.cts') || + rule.test.test('file.mts') || + rule.test.test('file.tsx') + ) { + rule.exclude = nodeModulesExclude; + } + } + } - config.resolve.plugins ||= []; return config; }, framework: { @@ -60,5 +75,7 @@ module.exports = { autodocs: true, }, previewHead: (head) => - head + fs.readFileSync(require.resolve('./preview-head.html'), 'utf8'), + head + readFileSync(require.resolve('./preview-head.html'), 'utf8'), }; + +export default config; diff --git a/configs/storybook/package.json b/configs/storybook/package.json index e62217b8e..4fa5f2216 100644 --- a/configs/storybook/package.json +++ b/configs/storybook/package.json @@ -11,6 +11,7 @@ "@babel/preset-typescript": "7.24.1", "@emotion/babel-plugin": "11.12.0", "@emotion/react": "11.11.3", + "@guardian/libs": "workspace:*", "@guardian/source": "workspace:*", "@storybook/addon-a11y": "8.2.7", "@storybook/addon-docs": "8.2.7", diff --git a/configs/storybook/preview/FocusManagerDecorator.tsx b/configs/storybook/preview/FocusManagerDecorator.tsx index 0a7722b31..9dd46bcf8 100644 --- a/configs/storybook/preview/FocusManagerDecorator.tsx +++ b/configs/storybook/preview/FocusManagerDecorator.tsx @@ -1,6 +1,6 @@ -import type { Decorator } from '@storybook/react'; -import { useEffect } from 'react'; import { FocusStyleManager } from '@guardian/source/foundations'; +import { useEffect } from 'react'; +import type { Decorator } from '@storybook/react'; export const FocusManagerDecorator: Decorator = (storyFn) => { useEffect(() => { diff --git a/configs/storybook/preview/ThemeProviderDecorator.tsx b/configs/storybook/preview/ThemeProviderDecorator.tsx index 28b7da8f1..d32223be1 100644 --- a/configs/storybook/preview/ThemeProviderDecorator.tsx +++ b/configs/storybook/preview/ThemeProviderDecorator.tsx @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unsafe-assignment -- storybook type contains `any`s */ - import { ThemeProvider } from '@emotion/react'; import type { Decorator } from '@storybook/react'; diff --git a/configs/storybook/preview/viewport.ts b/configs/storybook/preview/viewport.ts index 5c04e256d..2c05924ba 100644 --- a/configs/storybook/preview/viewport.ts +++ b/configs/storybook/preview/viewport.ts @@ -1,5 +1,5 @@ -import type { Breakpoint } from '@guardian/source/foundations'; import { breakpoints } from '@guardian/source/foundations'; +import type { Breakpoint } from '@guardian/source/foundations'; type ViewportMeta = { [key in Breakpoint]: { @@ -66,7 +66,7 @@ const viewportEntries = Object.entries(breakpoints).map(([name, width]) => { ]; }); -const viewportEntriesObject = Object.fromEntries(viewportEntries) as Viewports; +const viewportEntriesObject: Viewports = Object.fromEntries(viewportEntries); export const viewport = { viewports: { diff --git a/configs/storybook/tsconfig.json b/configs/storybook/tsconfig.json new file mode 100644 index 000000000..974d85027 --- /dev/null +++ b/configs/storybook/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["**/*"] +} diff --git a/libs/@guardian/source-development-kitchen/.storybook/main.js b/libs/@guardian/source-development-kitchen/.storybook/main.js deleted file mode 100644 index 650a39ec5..000000000 --- a/libs/@guardian/source-development-kitchen/.storybook/main.js +++ /dev/null @@ -1,22 +0,0 @@ -const rootMain = require('../../../../configs/storybook/main'); - -// To customise your Storybook config for this project, update this file - -module.exports = { - ...rootMain, - - core: { ...rootMain.core }, - - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], - addons: [...rootMain.addons], - webpackFinal: async (config, { configType }) => { - // apply any global webpack configs that might have been specified in .storybook/main.js - if (rootMain.webpackFinal) { - config = await rootMain.webpackFinal(config, { configType }); - } - - // add your own webpack tweaks if needed - - return config; - }, -}; diff --git a/libs/@guardian/source-development-kitchen/.storybook/main.ts b/libs/@guardian/source-development-kitchen/.storybook/main.ts new file mode 100644 index 000000000..52ee66ebd --- /dev/null +++ b/libs/@guardian/source-development-kitchen/.storybook/main.ts @@ -0,0 +1,9 @@ +import base from '../../../../configs/storybook/main'; +import type { StorybookConfig } from '../../../../configs/storybook/main'; + +const config: StorybookConfig = { + ...base, + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], +}; + +export default config; diff --git a/libs/@guardian/source/.storybook/main.js b/libs/@guardian/source/.storybook/main.js deleted file mode 100644 index 650a39ec5..000000000 --- a/libs/@guardian/source/.storybook/main.js +++ /dev/null @@ -1,22 +0,0 @@ -const rootMain = require('../../../../configs/storybook/main'); - -// To customise your Storybook config for this project, update this file - -module.exports = { - ...rootMain, - - core: { ...rootMain.core }, - - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], - addons: [...rootMain.addons], - webpackFinal: async (config, { configType }) => { - // apply any global webpack configs that might have been specified in .storybook/main.js - if (rootMain.webpackFinal) { - config = await rootMain.webpackFinal(config, { configType }); - } - - // add your own webpack tweaks if needed - - return config; - }, -}; diff --git a/libs/@guardian/source/.storybook/main.ts b/libs/@guardian/source/.storybook/main.ts new file mode 100644 index 000000000..52ee66ebd --- /dev/null +++ b/libs/@guardian/source/.storybook/main.ts @@ -0,0 +1,9 @@ +import base from '../../../../configs/storybook/main'; +import type { StorybookConfig } from '../../../../configs/storybook/main'; + +const config: StorybookConfig = { + ...base, + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], +}; + +export default config; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecb1bd04f..198ce1136 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -170,6 +170,9 @@ importers: '@emotion/react': specifier: 11.11.3 version: 11.11.3(@types/react@18.2.11)(react@18.2.0) + '@guardian/libs': + specifier: workspace:* + version: link:../../libs/@guardian/libs '@guardian/source': specifier: workspace:* version: link:../../libs/@guardian/source