diff --git a/.storybook/main.ts b/.storybook/main.ts index e6fba25d90c..4ff20a65922 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -61,6 +61,34 @@ const storybookConfig: StorybookConfig = { transcludeMarkdown: true, }, }, + { + name: '@storybook/addon-styling-webpack', + options: { + rules: [ + { + test: /\.module\.scss$/, + use: [ + 'style-loader', + { + loader: 'css-loader', + options: { + modules: true, + importLoaders: 1, + esModule: false, + }, + }, + { + loader: 'sass-loader', + }, + ], + }, + { + test: /(? ({ ...config, diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 9f9e428736e..7c6d08c9cf4 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -6,6 +6,7 @@ import { Preview } from '@storybook/react-webpack5'; import GlobalStyles from '../src/app/legacy/psammead/psammead-styles/src/global-styles'; import DocsDecorator from './DocsDecorator'; import ThemeProvider from '../src/app/components/ThemeProvider'; +import ThemeProviderSCSSModules from '#app/components/ThemeProviderSCSSModules'; import { ServiceContextProvider } from '../src/app/contexts/ServiceContext'; import { ToggleContextProvider } from '../src/app/contexts/ToggleContext'; import { UserContextProvider } from '../src/app/contexts/UserContext'; @@ -228,12 +229,17 @@ const preview: Preview = { pageData={pageDataFixture} > - - - + + + + diff --git a/.vscode/launch.json b/.vscode/launch.json index bfad998f02c..45df8de7527 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -24,5 +24,16 @@ "request": "launch", "command": "cd ws-nextjs-app && nvm use && yarn dev" }, + { + "name": "Storybook debug", + "type": "node-terminal", + "request": "launch", + "command": "yarn storybook", + "serverReadyAction": { + "pattern": "Local:.+(https?://[^:]+:[0-9]+)", + "uriFormat": "%s", + "action": "debugWithChrome" + } + }, ] } \ No newline at end of file diff --git a/.yarn/cache/@adobe-css-tools-npm-4.3.3-72a4f624fb-0e77057efb.zip b/.yarn/cache/@adobe-css-tools-npm-4.3.3-72a4f624fb-0e77057efb.zip new file mode 100644 index 00000000000..7b6c30d4c03 Binary files /dev/null and b/.yarn/cache/@adobe-css-tools-npm-4.3.3-72a4f624fb-0e77057efb.zip differ diff --git a/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10.zip b/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10.zip new file mode 100644 index 00000000000..df4de222508 Binary files /dev/null and b/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10.zip differ diff --git a/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10.zip b/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10.zip deleted file mode 100644 index eea4066e35e..00000000000 Binary files a/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10.zip and /dev/null differ diff --git a/.yarn/cache/@img-sharp-darwin-arm64-npm-0.34.5-5cc67024f5-10.zip b/.yarn/cache/@img-sharp-darwin-arm64-npm-0.34.5-5cc67024f5-10.zip new file mode 100644 index 00000000000..ca713339c96 Binary files /dev/null and b/.yarn/cache/@img-sharp-darwin-arm64-npm-0.34.5-5cc67024f5-10.zip differ diff --git a/.yarn/cache/@img-sharp-libvips-darwin-arm64-npm-1.2.4-09e109d5ab-10.zip b/.yarn/cache/@img-sharp-libvips-darwin-arm64-npm-1.2.4-09e109d5ab-10.zip new file mode 100644 index 00000000000..dd8b2f006c5 Binary files /dev/null and b/.yarn/cache/@img-sharp-libvips-darwin-arm64-npm-1.2.4-09e109d5ab-10.zip differ diff --git a/.yarn/cache/@img-sharp-libvips-linux-x64-npm-1.2.4-105fd6d44d-10.zip b/.yarn/cache/@img-sharp-libvips-linux-x64-npm-1.2.4-105fd6d44d-10.zip deleted file mode 100644 index 160f001b364..00000000000 Binary files a/.yarn/cache/@img-sharp-libvips-linux-x64-npm-1.2.4-105fd6d44d-10.zip and /dev/null differ diff --git a/.yarn/cache/@img-sharp-linux-x64-npm-0.34.5-06b002e5f6-10.zip b/.yarn/cache/@img-sharp-linux-x64-npm-0.34.5-06b002e5f6-10.zip deleted file mode 100644 index c8030238cc0..00000000000 Binary files a/.yarn/cache/@img-sharp-linux-x64-npm-0.34.5-06b002e5f6-10.zip and /dev/null differ diff --git a/.yarn/cache/@next-swc-linux-x64-gnu-npm-16.2.3-36544134ac-10.zip b/.yarn/cache/@next-swc-darwin-arm64-npm-16.2.3-ed59a16fc3-10.zip similarity index 73% rename from .yarn/cache/@next-swc-linux-x64-gnu-npm-16.2.3-36544134ac-10.zip rename to .yarn/cache/@next-swc-darwin-arm64-npm-16.2.3-ed59a16fc3-10.zip index dbca4c1ba59..bd5ddf8ca5d 100644 Binary files a/.yarn/cache/@next-swc-linux-x64-gnu-npm-16.2.3-36544134ac-10.zip and b/.yarn/cache/@next-swc-darwin-arm64-npm-16.2.3-ed59a16fc3-10.zip differ diff --git a/.yarn/cache/@parcel-watcher-darwin-arm64-npm-2.5.1-12be747bca-10.zip b/.yarn/cache/@parcel-watcher-darwin-arm64-npm-2.5.1-12be747bca-10.zip new file mode 100644 index 00000000000..809e7aabc6c Binary files /dev/null and b/.yarn/cache/@parcel-watcher-darwin-arm64-npm-2.5.1-12be747bca-10.zip differ diff --git a/.yarn/cache/@parcel-watcher-npm-2.5.1-018e8f2cc2-2cc1405166.zip b/.yarn/cache/@parcel-watcher-npm-2.5.1-018e8f2cc2-2cc1405166.zip new file mode 100644 index 00000000000..9b5ebbd5308 Binary files /dev/null and b/.yarn/cache/@parcel-watcher-npm-2.5.1-018e8f2cc2-2cc1405166.zip differ diff --git a/.yarn/cache/@storybook-addon-styling-webpack-npm-3.0.0-78bf7cc2e0-31cc7a3cec.zip b/.yarn/cache/@storybook-addon-styling-webpack-npm-3.0.0-78bf7cc2e0-31cc7a3cec.zip new file mode 100644 index 00000000000..ce0c7fce216 Binary files /dev/null and b/.yarn/cache/@storybook-addon-styling-webpack-npm-3.0.0-78bf7cc2e0-31cc7a3cec.zip differ diff --git a/.yarn/cache/@swc-core-linux-x64-gnu-npm-1.15.24-c08977ba22-10.zip b/.yarn/cache/@swc-core-darwin-arm64-npm-1.15.24-ffb5dba236-10.zip similarity index 51% rename from .yarn/cache/@swc-core-linux-x64-gnu-npm-1.15.24-c08977ba22-10.zip rename to .yarn/cache/@swc-core-darwin-arm64-npm-1.15.24-ffb5dba236-10.zip index 18d0bcd24d8..81b82e7b20b 100644 Binary files a/.yarn/cache/@swc-core-linux-x64-gnu-npm-1.15.24-c08977ba22-10.zip and b/.yarn/cache/@swc-core-darwin-arm64-npm-1.15.24-ffb5dba236-10.zip differ diff --git a/.yarn/cache/@types-identity-obj-proxy-npm-3.0.2-c967fa469f-77387ee587.zip b/.yarn/cache/@types-identity-obj-proxy-npm-3.0.2-c967fa469f-77387ee587.zip new file mode 100644 index 00000000000..bb73f1eb70a Binary files /dev/null and b/.yarn/cache/@types-identity-obj-proxy-npm-3.0.2-c967fa469f-77387ee587.zip differ diff --git a/.yarn/cache/@types-postcss-modules-local-by-default-npm-4.0.2-842c2023dc-c4a50f0fab.zip b/.yarn/cache/@types-postcss-modules-local-by-default-npm-4.0.2-842c2023dc-c4a50f0fab.zip new file mode 100644 index 00000000000..4682253f4f7 Binary files /dev/null and b/.yarn/cache/@types-postcss-modules-local-by-default-npm-4.0.2-842c2023dc-c4a50f0fab.zip differ diff --git a/.yarn/cache/@types-postcss-modules-scope-npm-3.0.4-abf8e267ba-4249ace340.zip b/.yarn/cache/@types-postcss-modules-scope-npm-3.0.4-abf8e267ba-4249ace340.zip new file mode 100644 index 00000000000..b40b9ae08f8 Binary files /dev/null and b/.yarn/cache/@types-postcss-modules-scope-npm-3.0.4-abf8e267ba-4249ace340.zip differ diff --git a/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.0-0842d0cc77-10.zip b/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.0-0842d0cc77-10.zip new file mode 100644 index 00000000000..0dc23fea39c Binary files /dev/null and b/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.0-0842d0cc77-10.zip differ diff --git a/.yarn/cache/@unrs-resolver-binding-linux-x64-gnu-npm-1.11.0-f4a171e974-10.zip b/.yarn/cache/@unrs-resolver-binding-linux-x64-gnu-npm-1.11.0-f4a171e974-10.zip deleted file mode 100644 index 8eb42d8dc85..00000000000 Binary files a/.yarn/cache/@unrs-resolver-binding-linux-x64-gnu-npm-1.11.0-f4a171e974-10.zip and /dev/null differ diff --git a/.yarn/cache/copy-anything-npm-2.0.6-1cede50956-3b41be8f63.zip b/.yarn/cache/copy-anything-npm-2.0.6-1cede50956-3b41be8f63.zip new file mode 100644 index 00000000000..53694f1036f Binary files /dev/null and b/.yarn/cache/copy-anything-npm-2.0.6-1cede50956-3b41be8f63.zip differ diff --git a/.yarn/cache/detect-libc-npm-1.0.3-c30ac344d4-3849fe7720.zip b/.yarn/cache/detect-libc-npm-1.0.3-c30ac344d4-3849fe7720.zip new file mode 100644 index 00000000000..3f842cba07a Binary files /dev/null and b/.yarn/cache/detect-libc-npm-1.0.3-c30ac344d4-3849fe7720.zip differ diff --git a/.yarn/cache/dotenv-npm-16.6.1-01334288ea-1d18971443.zip b/.yarn/cache/dotenv-npm-16.6.1-01334288ea-1d18971443.zip new file mode 100644 index 00000000000..7820c73e7d8 Binary files /dev/null and b/.yarn/cache/dotenv-npm-16.6.1-01334288ea-1d18971443.zip differ diff --git a/.yarn/cache/errno-npm-0.1.8-10ebc185bf-93076ed11b.zip b/.yarn/cache/errno-npm-0.1.8-10ebc185bf-93076ed11b.zip new file mode 100644 index 00000000000..860aca17a5a Binary files /dev/null and b/.yarn/cache/errno-npm-0.1.8-10ebc185bf-93076ed11b.zip differ diff --git a/.yarn/cache/fsevents-patch-6b67494872-10.zip b/.yarn/cache/fsevents-patch-6b67494872-10.zip new file mode 100644 index 00000000000..9887ada72d9 Binary files /dev/null and b/.yarn/cache/fsevents-patch-6b67494872-10.zip differ diff --git a/.yarn/cache/harmony-reflect-npm-1.6.2-47a9f53361-69d30ebfb5.zip b/.yarn/cache/harmony-reflect-npm-1.6.2-47a9f53361-69d30ebfb5.zip new file mode 100644 index 00000000000..6c46590ae44 Binary files /dev/null and b/.yarn/cache/harmony-reflect-npm-1.6.2-47a9f53361-69d30ebfb5.zip differ diff --git a/.yarn/cache/identity-obj-proxy-npm-3.0.0-080ab9ac1e-66fe4d2ffc.zip b/.yarn/cache/identity-obj-proxy-npm-3.0.0-080ab9ac1e-66fe4d2ffc.zip new file mode 100644 index 00000000000..cb590907cb6 Binary files /dev/null and b/.yarn/cache/identity-obj-proxy-npm-3.0.0-080ab9ac1e-66fe4d2ffc.zip differ diff --git a/.yarn/cache/image-size-npm-0.5.5-4dec53b956-f41ec6cfcc.zip b/.yarn/cache/image-size-npm-0.5.5-4dec53b956-f41ec6cfcc.zip new file mode 100644 index 00000000000..247537b57e6 Binary files /dev/null and b/.yarn/cache/image-size-npm-0.5.5-4dec53b956-f41ec6cfcc.zip differ diff --git a/.yarn/cache/immutable-npm-5.1.4-cddca3d05c-0655b33af2.zip b/.yarn/cache/immutable-npm-5.1.4-cddca3d05c-0655b33af2.zip new file mode 100644 index 00000000000..162a364c45f Binary files /dev/null and b/.yarn/cache/immutable-npm-5.1.4-cddca3d05c-0655b33af2.zip differ diff --git a/.yarn/cache/is-what-npm-3.14.1-7260378616-249beb4a8c.zip b/.yarn/cache/is-what-npm-3.14.1-7260378616-249beb4a8c.zip new file mode 100644 index 00000000000..18920dcc134 Binary files /dev/null and b/.yarn/cache/is-what-npm-3.14.1-7260378616-249beb4a8c.zip differ diff --git a/.yarn/cache/less-npm-4.5.1-8849a9c167-ea48075c73.zip b/.yarn/cache/less-npm-4.5.1-8849a9c167-ea48075c73.zip new file mode 100644 index 00000000000..dccf84d056d Binary files /dev/null and b/.yarn/cache/less-npm-4.5.1-8849a9c167-ea48075c73.zip differ diff --git a/.yarn/cache/lilconfig-npm-2.1.0-a179261924-b1314a2e55.zip b/.yarn/cache/lilconfig-npm-2.1.0-a179261924-b1314a2e55.zip new file mode 100644 index 00000000000..24d1cd79c05 Binary files /dev/null and b/.yarn/cache/lilconfig-npm-2.1.0-a179261924-b1314a2e55.zip differ diff --git a/.yarn/cache/lodash.camelcase-npm-4.3.0-bf268e3bf0-c301cc3793.zip b/.yarn/cache/lodash.camelcase-npm-4.3.0-bf268e3bf0-c301cc3793.zip new file mode 100644 index 00000000000..af48cd518aa Binary files /dev/null and b/.yarn/cache/lodash.camelcase-npm-4.3.0-bf268e3bf0-c301cc3793.zip differ diff --git a/.yarn/cache/mini-css-extract-plugin-npm-2.9.4-9bd74fa138-24a0418dc4.zip b/.yarn/cache/mini-css-extract-plugin-npm-2.9.4-9bd74fa138-24a0418dc4.zip new file mode 100644 index 00000000000..f88ec040306 Binary files /dev/null and b/.yarn/cache/mini-css-extract-plugin-npm-2.9.4-9bd74fa138-24a0418dc4.zip differ diff --git a/.yarn/cache/needle-npm-3.3.1-069ce952ef-31925ec72b.zip b/.yarn/cache/needle-npm-3.3.1-069ce952ef-31925ec72b.zip new file mode 100644 index 00000000000..60bdbffcb61 Binary files /dev/null and b/.yarn/cache/needle-npm-3.3.1-069ce952ef-31925ec72b.zip differ diff --git a/.yarn/cache/node-addon-api-npm-7.1.1-bfb302df19-ee1e1ed628.zip b/.yarn/cache/node-addon-api-npm-7.1.1-bfb302df19-ee1e1ed628.zip new file mode 100644 index 00000000000..12b52b82de8 Binary files /dev/null and b/.yarn/cache/node-addon-api-npm-7.1.1-bfb302df19-ee1e1ed628.zip differ diff --git a/.yarn/cache/parse-node-version-npm-1.0.1-7dd3b14751-ac9b40c647.zip b/.yarn/cache/parse-node-version-npm-1.0.1-7dd3b14751-ac9b40c647.zip new file mode 100644 index 00000000000..d7413836239 Binary files /dev/null and b/.yarn/cache/parse-node-version-npm-1.0.1-7dd3b14751-ac9b40c647.zip differ diff --git a/.yarn/cache/postcss-load-config-npm-3.1.4-1cb8a7e276-75fa409d77.zip b/.yarn/cache/postcss-load-config-npm-3.1.4-1cb8a7e276-75fa409d77.zip new file mode 100644 index 00000000000..6e5c4b2dbc7 Binary files /dev/null and b/.yarn/cache/postcss-load-config-npm-3.1.4-1cb8a7e276-75fa409d77.zip differ diff --git a/.yarn/cache/prr-npm-1.0.1-608d442761-3bca2db047.zip b/.yarn/cache/prr-npm-1.0.1-608d442761-3bca2db047.zip new file mode 100644 index 00000000000..30374d9eb66 Binary files /dev/null and b/.yarn/cache/prr-npm-1.0.1-608d442761-3bca2db047.zip differ diff --git a/.yarn/cache/reserved-words-npm-0.1.2-eed4b16ca9-72e80f71dc.zip b/.yarn/cache/reserved-words-npm-0.1.2-eed4b16ca9-72e80f71dc.zip new file mode 100644 index 00000000000..bc57b4b8cf6 Binary files /dev/null and b/.yarn/cache/reserved-words-npm-0.1.2-eed4b16ca9-72e80f71dc.zip differ diff --git a/.yarn/cache/sass-loader-npm-16.0.5-4af1120998-978b553900.zip b/.yarn/cache/sass-loader-npm-16.0.5-4af1120998-978b553900.zip new file mode 100644 index 00000000000..53def4ab4eb Binary files /dev/null and b/.yarn/cache/sass-loader-npm-16.0.5-4af1120998-978b553900.zip differ diff --git a/.yarn/cache/sass-npm-1.94.2-25ad66b92d-e60c214ea9.zip b/.yarn/cache/sass-npm-1.94.2-25ad66b92d-e60c214ea9.zip new file mode 100644 index 00000000000..a8ab68f9bb7 Binary files /dev/null and b/.yarn/cache/sass-npm-1.94.2-25ad66b92d-e60c214ea9.zip differ diff --git a/.yarn/cache/sass-npm-1.97.3-632c69cd32-707ef8e525.zip b/.yarn/cache/sass-npm-1.97.3-632c69cd32-707ef8e525.zip new file mode 100644 index 00000000000..e08581db450 Binary files /dev/null and b/.yarn/cache/sass-npm-1.97.3-632c69cd32-707ef8e525.zip differ diff --git a/.yarn/cache/sax-npm-1.3.0-e6c479267f-bb571b31d3.zip b/.yarn/cache/sax-npm-1.3.0-e6c479267f-bb571b31d3.zip new file mode 100644 index 00000000000..43adb91d0e1 Binary files /dev/null and b/.yarn/cache/sax-npm-1.3.0-e6c479267f-bb571b31d3.zip differ diff --git a/.yarn/cache/sax-npm-1.4.4-0d170e0f2d-00ff7b258b.zip b/.yarn/cache/sax-npm-1.4.4-0d170e0f2d-00ff7b258b.zip new file mode 100644 index 00000000000..567646733a3 Binary files /dev/null and b/.yarn/cache/sax-npm-1.4.4-0d170e0f2d-00ff7b258b.zip differ diff --git a/.yarn/cache/source-map-npm-0.7.6-a3854be193-c8d2da7c57.zip b/.yarn/cache/source-map-npm-0.7.6-a3854be193-c8d2da7c57.zip new file mode 100644 index 00000000000..84e26314f69 Binary files /dev/null and b/.yarn/cache/source-map-npm-0.7.6-a3854be193-c8d2da7c57.zip differ diff --git a/.yarn/cache/stylus-npm-0.62.0-39f30c9d62-a2d975e619.zip b/.yarn/cache/stylus-npm-0.62.0-39f30c9d62-a2d975e619.zip new file mode 100644 index 00000000000..b3033ede5ff Binary files /dev/null and b/.yarn/cache/stylus-npm-0.62.0-39f30c9d62-a2d975e619.zip differ diff --git a/.yarn/cache/typescript-plugin-css-modules-npm-5.2.0-2a105149d7-4101b4f5d2.zip b/.yarn/cache/typescript-plugin-css-modules-npm-5.2.0-2a105149d7-4101b4f5d2.zip new file mode 100644 index 00000000000..2f38d209f79 Binary files /dev/null and b/.yarn/cache/typescript-plugin-css-modules-npm-5.2.0-2a105149d7-4101b4f5d2.zip differ diff --git a/dirAlias.js b/dirAlias.js index 6e0d1bcaadd..0232732e3e1 100644 --- a/dirAlias.js +++ b/dirAlias.js @@ -7,6 +7,7 @@ const resolvePath = relativePath => path.resolve(appDirectory, relativePath); module.exports = { webpackDirAlias: { + '@scss': resolvePath('src/app/components/ThemeProviderSCSSModules'), '#app': resolvePath('src/app'), '#src': resolvePath('src'), '#nextjs': resolvePath('ws-nextjs-app/'), diff --git a/jest.config.js b/jest.config.js index 7371105785d..9d03bd30422 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,7 +7,10 @@ const unitTests = { './src/testHelpers/setupTests.js', 'jest-expect-message', ], - moduleNameMapper: jestDirAlias, + moduleNameMapper: { + ...jestDirAlias, + '\\.module\\.(css|scss)$': 'identity-obj-proxy', + }, testEnvironment: 'jsdom', snapshotSerializers: ['@emotion/jest/serializer'], transform: { @@ -37,7 +40,10 @@ const clientUnitTests = { './src/testHelpers/setupTests.js', 'jest-expect-message', ], - moduleNameMapper: jestDirAlias, + moduleNameMapper: { + ...jestDirAlias, + '\\.module\\.(css|scss)$': 'identity-obj-proxy', + }, testEnvironment: '@happy-dom/jest-environment', snapshotSerializers: ['@emotion/jest/serializer'], transform: { diff --git a/package.json b/package.json index 9bf52380be3..04bb6dd82e4 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "sideEffects": [ "./src/app/legacy/psammead/moment-timezone-include/**/*.*", "./src/app/legacy/psammead/psammead-locales/**/*.*", - "./cypress/**/*.*" + "./cypress/**/*.*", + "**/*.scss", + "**/*.css" ], "workspaces": { "packages": [ @@ -166,6 +168,7 @@ "@loadable/webpack-plugin": "5.15.2", "@storybook/addon-a11y": "10.3.5", "@storybook/addon-docs": "10.3.5", + "@storybook/addon-styling-webpack": "^3.0.0", "@storybook/builder-webpack5": "10.3.5", "@storybook/cli": "10.3.5", "@storybook/react-webpack5": "10.3.5", @@ -174,6 +177,7 @@ "@testing-library/react": "16.3.1", "@testing-library/react-hooks": "8.0.1", "@testing-library/user-event": "14.6.1", + "@types/identity-obj-proxy": "3.0.2", "@types/jest": "30.0.0", "@types/js-cookie": "^3.0.3", "@types/jsdom": "27.0.0", @@ -200,6 +204,7 @@ "compression-webpack-plugin": "11.1.0", "copy-webpack-plugin": "13.0.1", "crypto": "1.0.1", + "css-loader": "7.1.2", "cypress": "15.11.0", "cypress-axe": "1.7.0", "cypress-multi-reporters": "2.0.5", @@ -220,6 +225,7 @@ "eslint-plugin-react-hooks": "5.2.0", "happy-dom": "20.8.9", "husky": "9.1.7", + "identity-obj-proxy": "3.0.0", "jest": "30.3.0", "jest-environment-jsdom": "30.2.0", "jest-expect-message": "1.1.3", @@ -229,6 +235,7 @@ "jest-silent-reporter": "0.6.0", "jsdom": "27.0.0", "lighthouse": "13.0.1", + "mini-css-extract-plugin": "2.9.4", "minimist": "1.2.8", "mkdirp": "3.0.1", "mocha-junit-reporter": "2.2.1", @@ -236,16 +243,20 @@ "prettier": "3.8.1", "puppeteer": "24.22.3", "retry": "0.13.1", + "sass": "1.94.2", + "sass-loader": "16.0.5", "start-server-nestjs-webpack-plugin": "2.2.5", "storybook": "10.3.5", "stream-browserify": "3.0.0", "strip-ansi": "7.1.2", + "style-loader": "4.0.0", "supertest": "7.2.2", "terser-webpack-plugin": "5.3.14", "timemachine": "0.3.2", "ts-jest": "29.4.9", "ts-loader": "9.5.4", "typescript": "5.9.3", + "typescript-plugin-css-modules": "5.2.0", "wait-on": "9.0.3", "webpack": "5.106.0", "webpack-bundle-analyzer": "5.3.0", diff --git a/scripts/dependencyCheck.js b/scripts/dependencyCheck.js index d35e4112fca..4c0b837e895 100644 --- a/scripts/dependencyCheck.js +++ b/scripts/dependencyCheck.js @@ -12,6 +12,8 @@ const options = { '@testing-library/dom', '@storybook/addon-knobs', 'next', // next/dynamic is referenced in some shared components with Express and Next.js, but is swapped out by Babel at build time in the Express app, so depcheck thinks it's missing + 'ThemeProviderSCSSModules', // internal SCSS module path resolved via webpack/next.js sassOptions.loadPaths + '@scss', // webpack alias for src/app/components, resolved via resolve.alias in webpack/next.js ], }; @@ -24,7 +26,7 @@ depcheck( // Filter out dependencies prefixed with "#". const missingFiltered = Object.keys(missing).reduce((obj, key) => { - if (key.startsWith('#')) { + if (key.startsWith('#') || key.startsWith('@scss/')) { return obj; } diff --git a/src/app/components/ArticleLinksBlock/Promo/index.module.scss b/src/app/components/ArticleLinksBlock/Promo/index.module.scss new file mode 100644 index 00000000000..607cedd0ece --- /dev/null +++ b/src/app/components/ArticleLinksBlock/Promo/index.module.scss @@ -0,0 +1,89 @@ +@use '@scss/themeTokens' as theme; + +.link { + @include theme.fontSizes-gel-font-size(pica); + @include theme.fontVariants-gel-font-variant('serif-bold'); + display: inline-block; + vertical-align: middle; + text-decoration: none; + overflow-x: hidden; + overflow-y: hidden; + line-clamp: 4; + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; + color: theme.$palette-grey-8; + + &:hover, + &:focus { + text-decoration: underline; + } + + &:visited { + color: theme.$palette-grey-6; + } + + &::before { + bottom: 0; + content: ''; + left: 0; + overflow: hidden; + position: absolute; + right: 0; + top: 0; + z-index: 1; + } + + // Dark UI override + :global([data-is-dark-ui='true']) & { + color: theme.$palette-grey-2; + } +} + +.promoBox { + position: relative; + background-color: theme.$palette-white; + padding: #{theme.$spacings-double}; + padding-inline-end: #{theme.pixelsToRem-px-to-rem(38)}; + height: auto; + display: block; + width: 100%; + + // Dark UI override + :global([data-is-dark-ui='true']) & { + background-color: theme.$palette-grey-7; + } + + // Opera Mini overrides + :global(.is-opera-mini) & { + position: relative; + background-color: theme.$palette-white; + padding: #{theme.$spacings-double}; + margin-bottom: #{theme.$spacings-double}; + width: calc(100% - #{theme.$spacings-full}); + + :global([data-is-dark-ui='true']) & { + background-color: theme.$palette-grey-3; + } + + @media (min-width: #{theme.$mediaQueries-group-2-min-width-bp}) { + width: calc(50% - #{theme.$spacings-double}); + } + } +} + +.timestamp { + margin-top: #{theme.$spacings-full}; + + // Dark UI override + :global([data-is-dark-ui='true']) & { + color: theme.$palette-grey-1; + } +} + +.chevron { + position: absolute; + top: 50%; + transform: translateY(-50%); + inset-inline-end: #{theme.pixelsToRem-px-to-rem(12)}; + fill: currentColor; +} diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index 9676918d455..aa1d539424c 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -5,7 +5,7 @@ import { OptimoBlock } from '#app/models/types/optimo'; import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; import { Chevron, ChevronOrientation } from '#app/components/icons'; import { ServiceContext } from '../../../contexts/ServiceContext'; -import styles from './index.styles'; +import styles from './index.module.scss'; interface PromoProps { block: OptimoBlock; @@ -32,18 +32,18 @@ const Promo = ({ block, clickTracker }: PromoProps) => { textBlock?.model?.blocks?.[0]?.model?.blocks?.[0]?.model?.text ?? ''; return ( -
- +
+ {title} {timestamp && ( {timestamp} diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.module.scss b/src/app/components/ArticleLinksBlock/PromoList/index.module.scss new file mode 100644 index 00000000000..385c40a3404 --- /dev/null +++ b/src/app/components/ArticleLinksBlock/PromoList/index.module.scss @@ -0,0 +1,61 @@ +@use '@scss/themeTokens' as theme; + +.promo { + & ul { + list-style: none; + padding-inline-start: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: #{theme.$spacings-full}; + width: 100%; + } + + // Opera Mini overrides + :global(.is-opera-mini) & { + list-style: none; + padding-inline-start: 0; + margin: 0; + } +} + +.list { + display: flex; + flex-shrink: 0; + margin-inline: #{theme.$spacings-full}; + + &:last-of-type { + margin-bottom: #{theme.$spacings-triple}; + } + + @media #{theme.$mediaQueries-forced-colours} { + border: solid #{theme.pixelsToRem-px-to-rem(3)} transparent; + } + + @media (min-width: #{theme.$mediaQueries-group-2-min-width-bp}) { + margin-inline: #{theme.$spacings-double}; + } + + @media (min-width: #{theme.$mediaQueries-group-3-min-width-bp}) { + margin-inline: #{theme.$spacings-double}; + } + + @media (min-width: #{theme.$mediaQueries-group-4-min-width-bp}) { + margin-inline: 0; + } + + // Opera Mini overrides + :global(.is-opera-mini) & { + @media (max-width: #{theme.$mediaQueries-group-0-max-width-bp}) { + margin-inline: #{theme.$spacings-full}; + } + + @media (min-width: #{theme.$mediaQueries-group-2-min-width-bp}) { + margin-inline: #{theme.$spacings-double}; + } + + @media (min-width: #{theme.$mediaQueries-group-4-min-width-bp}) { + margin-inline: 0; + } + } +} diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index 391b45d644b..224d6cb827c 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -2,7 +2,7 @@ import { OptimoBlock } from '#app/models/types/optimo'; import { ViewTracker } from '#app/lib/analyticsUtils/types'; import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; import Promo from '../Promo'; -import styles from './index.styles'; +import styles from './index.module.scss'; interface PromoListProps { blocks: OptimoBlock[]; @@ -14,12 +14,12 @@ const PromoList = ({ blocks, viewTracker, clickTracker }: PromoListProps) => { const listBlocks = blocks.slice(0, 3); return ( -
+