From a710ee8bdafd6a7b67f066ddc6bcb44276f85c04 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 09:46:51 +0000 Subject: [PATCH 001/100] move scrollable promo to components location and update imports --- .../{legacy => }/components/ScrollablePromo/Promo/index.jsx | 4 ++-- .../components/ScrollablePromo/Promo/index.test.jsx | 4 ++-- .../components/ScrollablePromo/PromoList/index.jsx | 2 +- .../ScrollablePromo/__snapshots__/index.test.jsx.snap | 0 src/app/{legacy => }/components/ScrollablePromo/fixtures.js | 0 .../components/ScrollablePromo/helpers/fixtureData.js | 0 src/app/{legacy => }/components/ScrollablePromo/index.jsx | 2 +- .../{legacy => }/components/ScrollablePromo/index.stories.jsx | 0 .../{legacy => }/components/ScrollablePromo/index.test.jsx | 4 ++-- src/app/legacy/containers/Navigation/index.stories.jsx | 2 +- src/app/pages/ArticlePage/ArticlePage.tsx | 2 +- src/app/pages/MediaArticlePage/MediaArticlePage.tsx | 2 +- 12 files changed, 11 insertions(+), 11 deletions(-) rename src/app/{legacy => }/components/ScrollablePromo/Promo/index.jsx (97%) rename src/app/{legacy => }/components/ScrollablePromo/Promo/index.test.jsx (96%) rename src/app/{legacy => }/components/ScrollablePromo/PromoList/index.jsx (98%) rename src/app/{legacy => }/components/ScrollablePromo/__snapshots__/index.test.jsx.snap (100%) rename src/app/{legacy => }/components/ScrollablePromo/fixtures.js (100%) rename src/app/{legacy => }/components/ScrollablePromo/helpers/fixtureData.js (100%) rename src/app/{legacy => }/components/ScrollablePromo/index.jsx (99%) rename src/app/{legacy => }/components/ScrollablePromo/index.stories.jsx (100%) rename src/app/{legacy => }/components/ScrollablePromo/index.test.jsx (98%) diff --git a/src/app/legacy/components/ScrollablePromo/Promo/index.jsx b/src/app/components/ScrollablePromo/Promo/index.jsx similarity index 97% rename from src/app/legacy/components/ScrollablePromo/Promo/index.jsx rename to src/app/components/ScrollablePromo/Promo/index.jsx index b123a3606b7..ebf5b22193e 100644 --- a/src/app/legacy/components/ScrollablePromo/Promo/index.jsx +++ b/src/app/components/ScrollablePromo/Promo/index.jsx @@ -17,8 +17,8 @@ import { import filterForBlockType from '#lib/utilities/blockHandlers'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import PromoTimestamp from '#components/Promo/timestamp'; -import LiveLabel from '../../../../components/LiveLabel'; -import { ServiceContext } from '../../../../contexts/ServiceContext'; +import LiveLabel from '../../LiveLabel'; +import { ServiceContext } from '../../../contexts/ServiceContext'; const StyledLink = styled(Link)` ${({ theme: { fontSizes } }) => fontSizes.pica}; diff --git a/src/app/legacy/components/ScrollablePromo/Promo/index.test.jsx b/src/app/components/ScrollablePromo/Promo/index.test.jsx similarity index 96% rename from src/app/legacy/components/ScrollablePromo/Promo/index.test.jsx rename to src/app/components/ScrollablePromo/Promo/index.test.jsx index 69e4cd67c04..46dbb714536 100644 --- a/src/app/legacy/components/ScrollablePromo/Promo/index.test.jsx +++ b/src/app/components/ScrollablePromo/Promo/index.test.jsx @@ -1,4 +1,4 @@ -import { render } from '../../../../components/react-testing-library-with-providers'; +import { render } from '../../react-testing-library-with-providers'; import { PromoSingleBlock, oneLinkWithTimestamp, @@ -7,7 +7,7 @@ import { topStoriesBlocksWithLiveItem, } from '../helpers/fixtureData'; import Promo from '.'; -import { ServiceContextProvider } from '../../../../contexts/ServiceContext'; +import { ServiceContextProvider } from '../../../contexts/ServiceContext'; const ScrollablePromo = ({ block, experimentVariant }) => ( diff --git a/src/app/legacy/components/ScrollablePromo/PromoList/index.jsx b/src/app/components/ScrollablePromo/PromoList/index.jsx similarity index 98% rename from src/app/legacy/components/ScrollablePromo/PromoList/index.jsx rename to src/app/components/ScrollablePromo/PromoList/index.jsx index aa8cb854588..88cec38b7d1 100644 --- a/src/app/legacy/components/ScrollablePromo/PromoList/index.jsx +++ b/src/app/components/ScrollablePromo/PromoList/index.jsx @@ -10,7 +10,7 @@ import { GEL_GROUP_4_SCREEN_WIDTH_MIN, } from '#psammead/gel-foundations/src/breakpoints'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; -import { ServiceContext } from '../../../../contexts/ServiceContext'; +import { ServiceContext } from '../../../contexts/ServiceContext'; import Promo from '../Promo'; const StandardScrollPromo = styled.ul` diff --git a/src/app/legacy/components/ScrollablePromo/__snapshots__/index.test.jsx.snap b/src/app/components/ScrollablePromo/__snapshots__/index.test.jsx.snap similarity index 100% rename from src/app/legacy/components/ScrollablePromo/__snapshots__/index.test.jsx.snap rename to src/app/components/ScrollablePromo/__snapshots__/index.test.jsx.snap diff --git a/src/app/legacy/components/ScrollablePromo/fixtures.js b/src/app/components/ScrollablePromo/fixtures.js similarity index 100% rename from src/app/legacy/components/ScrollablePromo/fixtures.js rename to src/app/components/ScrollablePromo/fixtures.js diff --git a/src/app/legacy/components/ScrollablePromo/helpers/fixtureData.js b/src/app/components/ScrollablePromo/helpers/fixtureData.js similarity index 100% rename from src/app/legacy/components/ScrollablePromo/helpers/fixtureData.js rename to src/app/components/ScrollablePromo/helpers/fixtureData.js diff --git a/src/app/legacy/components/ScrollablePromo/index.jsx b/src/app/components/ScrollablePromo/index.jsx similarity index 99% rename from src/app/legacy/components/ScrollablePromo/index.jsx rename to src/app/components/ScrollablePromo/index.jsx index 95fbf921f22..0213772f950 100644 --- a/src/app/legacy/components/ScrollablePromo/index.jsx +++ b/src/app/components/ScrollablePromo/index.jsx @@ -22,7 +22,7 @@ import useViewTracker from '#hooks/useViewTracker'; import useClickTrackerHandler from '#hooks/useClickTrackerHandler'; import idSanitiser from '#lib/utilities/idSanitiser'; import { GREY_2 } from '#app/components/ThemeProvider/palette'; -import { ServiceContext } from '../../../contexts/ServiceContext'; +import { ServiceContext } from '../../contexts/ServiceContext'; import Promo from './Promo'; import PromoList from './PromoList'; diff --git a/src/app/legacy/components/ScrollablePromo/index.stories.jsx b/src/app/components/ScrollablePromo/index.stories.jsx similarity index 100% rename from src/app/legacy/components/ScrollablePromo/index.stories.jsx rename to src/app/components/ScrollablePromo/index.stories.jsx diff --git a/src/app/legacy/components/ScrollablePromo/index.test.jsx b/src/app/components/ScrollablePromo/index.test.jsx similarity index 98% rename from src/app/legacy/components/ScrollablePromo/index.test.jsx rename to src/app/components/ScrollablePromo/index.test.jsx index 63ce2abb127..2209d3fc7ca 100644 --- a/src/app/legacy/components/ScrollablePromo/index.test.jsx +++ b/src/app/components/ScrollablePromo/index.test.jsx @@ -1,6 +1,6 @@ import * as viewTracking from '#hooks/useViewTracker'; import * as clickTracking from '#hooks/useClickTrackerHandler'; -import { render } from '../../../components/react-testing-library-with-providers'; +import { render } from '../react-testing-library-with-providers'; import { threeLinks, oneLinkOnly, @@ -11,7 +11,7 @@ import { } from './helpers/fixtureData'; import ScrollablePromo from '.'; import { edOjA, edOjB } from './fixtures'; -import { MEDIA_ARTICLE_PAGE } from '../../../routes/utils/pageTypes'; +import { MEDIA_ARTICLE_PAGE } from '../../routes/utils/pageTypes'; describe('ScrollablePromo', () => { describe('Mid Page ScrollablePromo', () => { diff --git a/src/app/legacy/containers/Navigation/index.stories.jsx b/src/app/legacy/containers/Navigation/index.stories.jsx index c80af4e4bbe..b8b5a8ef741 100644 --- a/src/app/legacy/containers/Navigation/index.stories.jsx +++ b/src/app/legacy/containers/Navigation/index.stories.jsx @@ -3,7 +3,7 @@ import { HOME_PAGE } from '#app/routes/utils/pageTypes'; import { topStoriesBlocks, mostReadBlocks, -} from '../../components/ScrollablePromo/helpers/fixtureData'; +} from '../../../components/ScrollablePromo/helpers/fixtureData'; import AmpDecorator from '../../../../../.storybook/helpers/ampDecorator'; import Navigation from '.'; diff --git a/src/app/pages/ArticlePage/ArticlePage.tsx b/src/app/pages/ArticlePage/ArticlePage.tsx index c588bdce5a7..ce4171725c6 100644 --- a/src/app/pages/ArticlePage/ArticlePage.tsx +++ b/src/app/pages/ArticlePage/ArticlePage.tsx @@ -44,7 +44,7 @@ import { import { Translations } from '#app/models/types/translations'; import { Recommendation } from '#app/models/types/onwardJourney'; -import ScrollablePromo from '#components/ScrollablePromo'; +import ScrollablePromo from '#app/components/ScrollablePromo'; import Recommendations from '#app/components/Recommendations'; import { ReadTimeArticleExperiment as ReadTime } from '#app/components/ReadTime'; import PWAPromotionalBanner from '#app/components/PWAPromotionalBanner'; diff --git a/src/app/pages/MediaArticlePage/MediaArticlePage.tsx b/src/app/pages/MediaArticlePage/MediaArticlePage.tsx index d04867e6fdc..fb5339c5da0 100644 --- a/src/app/pages/MediaArticlePage/MediaArticlePage.tsx +++ b/src/app/pages/MediaArticlePage/MediaArticlePage.tsx @@ -24,7 +24,7 @@ import { } from '../../lib/utilities/parseAssetData'; import filterForBlockType from '../../lib/utilities/blockHandlers'; -import ScrollablePromo from '../../legacy/components/ScrollablePromo'; +import ScrollablePromo from '../../components/ScrollablePromo'; import headings from '../../legacy/containers/Headings'; import visuallyHiddenHeadline from '../../legacy/containers/VisuallyHiddenHeadline'; From 4ad283db7ef193b1e21bb65e163de01393d22ef0 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 10:16:17 +0000 Subject: [PATCH 002/100] more import and reference updates --- .../{ScrollablePromo => ArticleLinksBlock}/Promo/index.jsx | 0 .../Promo/index.test.jsx | 0 .../PromoList/index.jsx | 0 .../__snapshots__/index.test.jsx.snap | 0 .../{ScrollablePromo => ArticleLinksBlock}/fixtures.js | 0 .../helpers/fixtureData.js | 0 .../{ScrollablePromo => ArticleLinksBlock}/index.jsx | 0 .../index.stories.jsx | 0 .../{ScrollablePromo => ArticleLinksBlock}/index.test.jsx | 0 src/app/legacy/containers/Navigation/index.stories.jsx | 2 +- src/app/pages/ArticlePage/ArticlePage.tsx | 4 ++-- src/app/pages/MediaArticlePage/MediaArticlePage.tsx | 6 ++++-- 12 files changed, 7 insertions(+), 5 deletions(-) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/Promo/index.jsx (100%) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/Promo/index.test.jsx (100%) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/PromoList/index.jsx (100%) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/__snapshots__/index.test.jsx.snap (100%) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/fixtures.js (100%) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/helpers/fixtureData.js (100%) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/index.jsx (100%) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/index.stories.jsx (100%) rename src/app/components/{ScrollablePromo => ArticleLinksBlock}/index.test.jsx (100%) diff --git a/src/app/components/ScrollablePromo/Promo/index.jsx b/src/app/components/ArticleLinksBlock/Promo/index.jsx similarity index 100% rename from src/app/components/ScrollablePromo/Promo/index.jsx rename to src/app/components/ArticleLinksBlock/Promo/index.jsx diff --git a/src/app/components/ScrollablePromo/Promo/index.test.jsx b/src/app/components/ArticleLinksBlock/Promo/index.test.jsx similarity index 100% rename from src/app/components/ScrollablePromo/Promo/index.test.jsx rename to src/app/components/ArticleLinksBlock/Promo/index.test.jsx diff --git a/src/app/components/ScrollablePromo/PromoList/index.jsx b/src/app/components/ArticleLinksBlock/PromoList/index.jsx similarity index 100% rename from src/app/components/ScrollablePromo/PromoList/index.jsx rename to src/app/components/ArticleLinksBlock/PromoList/index.jsx diff --git a/src/app/components/ScrollablePromo/__snapshots__/index.test.jsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap similarity index 100% rename from src/app/components/ScrollablePromo/__snapshots__/index.test.jsx.snap rename to src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap diff --git a/src/app/components/ScrollablePromo/fixtures.js b/src/app/components/ArticleLinksBlock/fixtures.js similarity index 100% rename from src/app/components/ScrollablePromo/fixtures.js rename to src/app/components/ArticleLinksBlock/fixtures.js diff --git a/src/app/components/ScrollablePromo/helpers/fixtureData.js b/src/app/components/ArticleLinksBlock/helpers/fixtureData.js similarity index 100% rename from src/app/components/ScrollablePromo/helpers/fixtureData.js rename to src/app/components/ArticleLinksBlock/helpers/fixtureData.js diff --git a/src/app/components/ScrollablePromo/index.jsx b/src/app/components/ArticleLinksBlock/index.jsx similarity index 100% rename from src/app/components/ScrollablePromo/index.jsx rename to src/app/components/ArticleLinksBlock/index.jsx diff --git a/src/app/components/ScrollablePromo/index.stories.jsx b/src/app/components/ArticleLinksBlock/index.stories.jsx similarity index 100% rename from src/app/components/ScrollablePromo/index.stories.jsx rename to src/app/components/ArticleLinksBlock/index.stories.jsx diff --git a/src/app/components/ScrollablePromo/index.test.jsx b/src/app/components/ArticleLinksBlock/index.test.jsx similarity index 100% rename from src/app/components/ScrollablePromo/index.test.jsx rename to src/app/components/ArticleLinksBlock/index.test.jsx diff --git a/src/app/legacy/containers/Navigation/index.stories.jsx b/src/app/legacy/containers/Navigation/index.stories.jsx index b8b5a8ef741..f3723da0dda 100644 --- a/src/app/legacy/containers/Navigation/index.stories.jsx +++ b/src/app/legacy/containers/Navigation/index.stories.jsx @@ -3,7 +3,7 @@ import { HOME_PAGE } from '#app/routes/utils/pageTypes'; import { topStoriesBlocks, mostReadBlocks, -} from '../../../components/ScrollablePromo/helpers/fixtureData'; +} from '../../../components/ArticleLinksBlock/helpers/fixtureData'; import AmpDecorator from '../../../../../.storybook/helpers/ampDecorator'; import Navigation from '.'; diff --git a/src/app/pages/ArticlePage/ArticlePage.tsx b/src/app/pages/ArticlePage/ArticlePage.tsx index ce4171725c6..538f98cf1d8 100644 --- a/src/app/pages/ArticlePage/ArticlePage.tsx +++ b/src/app/pages/ArticlePage/ArticlePage.tsx @@ -44,7 +44,7 @@ import { import { Translations } from '#app/models/types/translations'; import { Recommendation } from '#app/models/types/onwardJourney'; -import ScrollablePromo from '#app/components/ScrollablePromo'; +import ArticleLinksBlock from '#app/components/ArticleLinksBlock'; import Recommendations from '#app/components/Recommendations'; import { ReadTimeArticleExperiment as ReadTime } from '#app/components/ReadTime'; import PWAPromotionalBanner from '#app/components/PWAPromotionalBanner'; @@ -358,7 +358,7 @@ const ArticlePage = ({ pageData }: { pageData: Article }) => { embedImages: EmbedImages, embedUploader: Uploader, group: gist, - links: ScrollablePromo, + links: ArticleLinksBlock, mpu: getMpuComponent(allowAdvertising), wsoj: getWsojComponent, disclaimer: DisclaimerWithPaddingOverride, diff --git a/src/app/pages/MediaArticlePage/MediaArticlePage.tsx b/src/app/pages/MediaArticlePage/MediaArticlePage.tsx index fb5339c5da0..36e6bffd6a8 100644 --- a/src/app/pages/MediaArticlePage/MediaArticlePage.tsx +++ b/src/app/pages/MediaArticlePage/MediaArticlePage.tsx @@ -24,7 +24,7 @@ import { } from '../../lib/utilities/parseAssetData'; import filterForBlockType from '../../lib/utilities/blockHandlers'; -import ScrollablePromo from '../../components/ScrollablePromo'; +import ArticleLinksBlock from '../../components/ArticleLinksBlock'; import headings from '../../legacy/containers/Headings'; import visuallyHiddenHeadline from '../../legacy/containers/VisuallyHiddenHeadline'; @@ -121,7 +121,9 @@ const getBylineComponent = ) : null; -const Links = (props: ComponentToRenderProps) => ; +const Links = (props: ComponentToRenderProps) => ( + +); const getImageComponent = (preloadLeadImageToggle: boolean) => (props: ComponentToRenderProps) => ( From 84c23118ad3654771e6e379a1fb05ff4d254b40c Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 11:10:31 +0000 Subject: [PATCH 003/100] update component name --- src/app/components/ArticleLinksBlock/index.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.jsx b/src/app/components/ArticleLinksBlock/index.jsx index 0213772f950..1d583d0ae40 100644 --- a/src/app/components/ArticleLinksBlock/index.jsx +++ b/src/app/components/ArticleLinksBlock/index.jsx @@ -142,7 +142,7 @@ const LabelComponentOJTopBar = styled(({ ariaLabel, ...props }) => ( width: 100vw; `; -const ScrollablePromo = ({ +const ArticleLinksBlock = ({ blocks, blockGroupIndex = null, experimentVariant = null, @@ -257,4 +257,4 @@ const ScrollablePromo = ({ ); }; -export default ScrollablePromo; +export default ArticleLinksBlock; From 0d41fd2eeffe23203cade260b5f133a8efadce1f Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 12:02:39 +0000 Subject: [PATCH 004/100] remove some experiment tests and code --- .../ArticleLinksBlock/Promo/index.test.jsx | 84 ------------------- .../components/ArticleLinksBlock/index.jsx | 31 ++----- .../ArticleLinksBlock/index.stories.jsx | 19 +---- .../ArticleLinksBlock/index.test.jsx | 83 ------------------ 4 files changed, 12 insertions(+), 205 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.test.jsx b/src/app/components/ArticleLinksBlock/Promo/index.test.jsx index 46dbb714536..59e5ca6a61c 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.test.jsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.test.jsx @@ -49,88 +49,4 @@ describe('ScrollablePromo', () => { ); expect(container.getElementsByTagName('time')[0]).toBeInTheDocument(); }); - - describe('OJ Top Bar Promo', () => { - it('should display Top Stories content when experimentVariant is top-bar-top-stories', () => { - const { container } = render( - , - ); - const expectedHeadline = - topStoriesBlocks[0].headlines.promoHeadline.blocks[0].model.blocks[0] - .model.text; - expect(container).toHaveTextContent(expectedHeadline); - }); - - it('should display Top Stories content when experimentVariant is read-more-a-and-top-stories', () => { - const { container } = render( - , - ); - const expectedHeadline = - topStoriesBlocks[0].headlines.promoHeadline.blocks[0].model.blocks[0] - .model.text; - expect(container).toHaveTextContent(expectedHeadline); - }); - - it('should display Most Read content when experimentVariant is top-bar-most-read', () => { - const { container } = render( - , - ); - const expectedHeadline = mostReadBlocks[0].title; - expect(container).toHaveTextContent(expectedHeadline); - }); - - it('should render a link on Top Stories article headline when experimentVariant is top-bar-top-stories', () => { - const { queryByRole } = render( - , - ); - expect(queryByRole('link')).toBeInTheDocument(); - }); - - it('should render a link on Most Read article headline when experimentVariant is top-bar-most-read', () => { - const { queryByRole } = render( - , - ); - expect(queryByRole('link')).toBeInTheDocument(); - }); - - it('should not display a timestamp when experimentVariant is top-bar-top-stories or top-bar-most-read', () => { - const { queryByTestId } = render( - , - ); - expect(queryByTestId('timestamp')).not.toBeInTheDocument(); - }); - - it('should display a LiveLabel when returning Top Stories', () => { - const { container } = render( - , - ); - expect( - container.querySelector('[class*="liveLabelPulse"]'), - ).toBeInTheDocument(); - expect( - container.querySelector('[class*="liveLabelText"]'), - ).toBeInTheDocument(); - }); - }); }); diff --git a/src/app/components/ArticleLinksBlock/index.jsx b/src/app/components/ArticleLinksBlock/index.jsx index 1d583d0ae40..52f3de0e5a3 100644 --- a/src/app/components/ArticleLinksBlock/index.jsx +++ b/src/app/components/ArticleLinksBlock/index.jsx @@ -147,7 +147,7 @@ const ArticleLinksBlock = ({ blockGroupIndex = null, experimentVariant = null, }) => { - const { script, service, dir, translations, mostRead } = use(ServiceContext); + const { script, service, dir, translations } = use(ServiceContext); const eventTrackingData = { componentName: `edoj${blockGroupIndex}`, @@ -166,23 +166,12 @@ const ArticleLinksBlock = ({ return null; } - let title; - if ( - ['top-bar-top-stories', 'read-more-a-and-top-stories'].includes( - experimentVariant, - ) - ) { - title = translations.topStoriesTitle || 'Top Stories'; - } else if (experimentVariant === 'top-bar-most-read') { - title = mostRead.header || 'Most Read'; - } else { - title = - blocks[0].type === 'title' && - path( - ['0', 'model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'text'], - blocks, - ); - } + const title = + blocks[0].type === 'title' && + path( + ['0', 'model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'text'], + blocks, + ); const blocksWithoutTitle = blocks[0].type === 'title' ? tail(blocks) : blocks; @@ -191,10 +180,8 @@ const ArticleLinksBlock = ({ const ariaLabel = title && idSanitiser(title); const a11yAttributes = { - ...(!experimentVariant && { - as: 'section', - role: 'region', - }), + as: 'section', + role: 'region', ...(ariaLabel ? { 'aria-labelledby': ariaLabel } : { diff --git a/src/app/components/ArticleLinksBlock/index.stories.jsx b/src/app/components/ArticleLinksBlock/index.stories.jsx index de5a43b26fd..3908948563d 100644 --- a/src/app/components/ArticleLinksBlock/index.stories.jsx +++ b/src/app/components/ArticleLinksBlock/index.stories.jsx @@ -92,33 +92,20 @@ export const WithTimestamp = (_, { service }) => ( ); export const OJTopBarTopStories = (_, { service }) => ( - + ); export const OJTopBarTopStoriesWithLiveLabel = (_, { service }) => ( ); export const OJTopBarMostRead = (_, { service }) => ( - + ); export const OJTopBarMostReadRTL = () => ( - + ); diff --git a/src/app/components/ArticleLinksBlock/index.test.jsx b/src/app/components/ArticleLinksBlock/index.test.jsx index 2209d3fc7ca..4e9cac9d0fc 100644 --- a/src/app/components/ArticleLinksBlock/index.test.jsx +++ b/src/app/components/ArticleLinksBlock/index.test.jsx @@ -163,87 +163,4 @@ describe('ScrollablePromo', () => { expect(container).toMatchSnapshot(); }); }); - - describe('OJ Top Bar ScrollablePromo', () => { - it('it should display Top Stories label when experimentVariant is top-bar-top-stories', () => { - const { getByText, queryByText } = render( - , - ); - expect(getByText('Top Stories')).toBeVisible(); - expect(queryByText('Popular Reads')).toBeNull(); - }); - - it('it should display Top Stories label when experimentVariant is read-more-a-and-top-stories', () => { - const { getByText, queryByText } = render( - , - ); - expect(getByText('Top Stories')).toBeVisible(); - expect(queryByText('Popular Reads')).toBeNull(); - }); - - it('it should display Most Read label when experimentVariant is top-bar-most-read', () => { - const { getByText, queryByText } = render( - , - ); - expect(getByText('Popular Reads')).toBeVisible(); - expect(queryByText('Top Stories')).toBeNull(); - }); - - it('it should display 3 promo items with Top Stories when experimentVariant is top-bar-top-stories', () => { - const { getAllByRole } = render( - , - ); - expect(getAllByRole('listitem')).toHaveLength(3); - }); - - it('it should display 5 promo items with Most Read when experimentVariant is top-bar-most-read', () => { - const { getAllByRole } = render( - , - ); - expect(getAllByRole('listitem')).toHaveLength(5); - }); - - it('it should display Top Stories content when experimentVariant is top-bar-top-stories', () => { - const { getAllByRole } = render( - , - ); - const expectedFirstHeadline = - topStoriesBlocks[0].headlines.promoHeadline.blocks[0].model.blocks[0] - .model.text; - expect(getAllByRole('listitem')[0]).toHaveTextContent( - expectedFirstHeadline, - ); - }); - - it('it should display Most Read content when experimentVariant is top-bar-most-read', () => { - const { getAllByRole } = render( - , - ); - const expectedFirstHeadline = mostReadBlocks[0].title; - expect(getAllByRole('listitem')[0]).toHaveTextContent( - expectedFirstHeadline, - ); - }); - }); }); From 88b476d5b46e68c6be7c1abdae566841a63a179b Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 15:11:38 +0000 Subject: [PATCH 005/100] update name references --- .../ArticleLinksBlock/index.test.jsx | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.test.jsx b/src/app/components/ArticleLinksBlock/index.test.jsx index 4e9cac9d0fc..5688de0c8b4 100644 --- a/src/app/components/ArticleLinksBlock/index.test.jsx +++ b/src/app/components/ArticleLinksBlock/index.test.jsx @@ -6,35 +6,33 @@ import { oneLinkOnly, oneLinkWithNoTitle, moreThanThreeLinks, - topStoriesBlocks, - mostReadBlocks, } from './helpers/fixtureData'; -import ScrollablePromo from '.'; +import ArticleLinksBlock from '.'; import { edOjA, edOjB } from './fixtures'; import { MEDIA_ARTICLE_PAGE } from '../../routes/utils/pageTypes'; -describe('ScrollablePromo', () => { - describe('Mid Page ScrollablePromo', () => { +describe('Article Links Block', () => { + describe('Mid Page Article Links Block', () => { it('should return null if no data is passed', () => { - const { container } = render(); + const { container } = render(); expect(container).toBeEmptyDOMElement(); }); it('should render max 3 promo items', () => { const { getAllByRole } = render( - , + , ); expect(getAllByRole('listitem').length).toEqual(3); }); it('should render single promo item', () => { - const { container } = render(); + const { container } = render(); expect(container.childElementCount).toEqual(1); }); it('should render single promo item with a title', () => { const { container, getByTestId } = render( - , + , ); expect(container.childElementCount).toEqual(1); expect(getByTestId('eoj-recommendations-heading')).toBeInTheDocument(); @@ -42,7 +40,7 @@ describe('ScrollablePromo', () => { it('should render single promo item without a title', () => { const { container, queryByTestId } = render( - , + , ); expect(container.childElementCount).toEqual(1); expect( @@ -51,7 +49,9 @@ describe('ScrollablePromo', () => { }); it('should not render a list when there is only one promo', () => { - const { queryByRole } = render(); + const { queryByRole } = render( + , + ); expect(queryByRole('list')).not.toBeInTheDocument(); expect(queryByRole('listitem')).not.toBeInTheDocument(); @@ -59,7 +59,7 @@ describe('ScrollablePromo', () => { it('should render unordered list if more than 1 item', () => { const { queryByRole, getAllByRole } = render( - , + , ); expect(queryByRole('list')).toBeInTheDocument(); expect(getAllByRole('listitem').length).toEqual(3); @@ -74,7 +74,7 @@ describe('ScrollablePromo', () => { const viewTrackerSpy = jest.spyOn(viewTracking, 'default'); render( - , + , ); expect(viewTrackerSpy).toHaveBeenCalledWith({ @@ -86,10 +86,10 @@ describe('ScrollablePromo', () => { it('should call the view tracking hook with the correct params with multiple editorial onward journeys', () => { const viewTrackerSpy = jest.spyOn(viewTracking, 'default'); render( - , + , ); render( - , + , ); expect(viewTrackerSpy).toHaveBeenCalledTimes(4); @@ -106,7 +106,7 @@ describe('ScrollablePromo', () => { it('should call the click tracking hook with one editorial onward journey', () => { const clickTrackerSpy = jest.spyOn(clickTracking, 'default'); render( - , + , ); expect(clickTrackerSpy).toHaveBeenCalledWith({ @@ -118,10 +118,10 @@ describe('ScrollablePromo', () => { it('should call the click tracking hook with multiple editorial onward journeys', () => { const clickTrackerSpy = jest.spyOn(clickTracking, 'default'); render( - , + , ); render( - , + , ); expect(clickTrackerSpy).toHaveBeenCalledTimes(4); @@ -137,25 +137,25 @@ describe('ScrollablePromo', () => { }); it('it should match a11y snapshot for single card', () => { - const { container } = render(); + const { container } = render(); expect(container).toMatchSnapshot(); }); it('it should match a11y snapshot for list', () => { - const { container } = render(); + const { container } = render(); expect(container).toMatchSnapshot(); }); it('it should match a11y snapshot for list with no title', () => { const { container } = render( - , + , ); expect(container).toMatchSnapshot(); }); it('it should match snapshot when in dark ui mode', () => { const { container } = render( - , + , { pageType: MEDIA_ARTICLE_PAGE, }, From 3b813c861ec65051748626cea9cffdf9772c7c19 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 15:13:28 +0000 Subject: [PATCH 006/100] update name references --- .../ArticleLinksBlock/index.stories.jsx | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.stories.jsx b/src/app/components/ArticleLinksBlock/index.stories.jsx index 3908948563d..b2292b06021 100644 --- a/src/app/components/ArticleLinksBlock/index.stories.jsx +++ b/src/app/components/ArticleLinksBlock/index.stories.jsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; import { ServiceContextProvider } from '#contexts/ServiceContext'; -import ScrollablePromo from '.'; +import ArticleLinksBlock from '.'; import { threeLinks, oneLinkOnly, @@ -21,54 +21,54 @@ const BackGround = styled.div` padding: 2rem; `; -const ScrollablePromoComponent = ({ +const ArticleLinksBlockComponent = ({ data, service, experimentVariant = null, }) => ( - + ); export default { - title: 'Components/Scrollable Promo', - ScrollablePromoComponent, + title: 'Components/Article Links Block', + ArticleLinksBlockComponent, }; export const ThreeLinks = (_, { service }) => ( - + ); export const OnlyOneLink = (_, { service }) => ( - + ); export const OneLinkWithNoTitle = (_, { service }) => ( - + ); export const MoreThanThreeLinks = (_, { service }) => ( - + ); export const NoImagesInData = (_, { service }) => ( - + ); export const TruncatedTextInSingleLink = (_, { service }) => ( - @@ -77,7 +77,7 @@ export const TruncatedTextInSingleLink = (_, { service }) => ( export const ArabicText = () => ( - + ); @@ -87,25 +87,25 @@ ArabicText.globals = { export const WithTimestamp = (_, { service }) => ( - + ); export const OJTopBarTopStories = (_, { service }) => ( - + ); export const OJTopBarTopStoriesWithLiveLabel = (_, { service }) => ( - ); export const OJTopBarMostRead = (_, { service }) => ( - + ); export const OJTopBarMostReadRTL = () => ( - + ); From 1935590204251284958f8d20fb259ce8a5c0f6ba Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 15:14:49 +0000 Subject: [PATCH 007/100] update name references --- .../ArticleLinksBlock/Promo/index.test.jsx | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.test.jsx b/src/app/components/ArticleLinksBlock/Promo/index.test.jsx index 59e5ca6a61c..9f34ad5df6e 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.test.jsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.test.jsx @@ -1,15 +1,9 @@ import { render } from '../../react-testing-library-with-providers'; -import { - PromoSingleBlock, - oneLinkWithTimestamp, - topStoriesBlocks, - mostReadBlocks, - topStoriesBlocksWithLiveItem, -} from '../helpers/fixtureData'; +import { PromoSingleBlock, oneLinkWithTimestamp } from '../helpers/fixtureData'; import Promo from '.'; import { ServiceContextProvider } from '../../../contexts/ServiceContext'; -const ScrollablePromo = ({ block, experimentVariant }) => ( +const ArticleLinksBlock = ({ block, experimentVariant }) => ( ( ); -describe('ScrollablePromo', () => { +describe('Article Links Block', () => { it('should render a link', () => { const { queryByRole } = render( - , + , ); expect(queryByRole('link')).toBeInTheDocument(); }); it('should extract and render the correct title', () => { - const { getByText } = render(); + const { getByText } = render( + , + ); expect( getByText( 'This is a very long headline. I am creating this for a test purpose. I love creating these type of tests. I really do not know what to write.', @@ -38,14 +34,14 @@ describe('ScrollablePromo', () => { it('should extract and render the correct href', () => { const { queryByRole } = render( - , + , ); expect(queryByRole('link').href).toEqual('https://www.bbc.com/mundo'); }); it('should render timestamp if timestamp is available', () => { const { container } = render( - , + , ); expect(container.getElementsByTagName('time')[0]).toBeInTheDocument(); }); From e845b86dc0a8e06a5c728aa1cd0faef143a1e1fd Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 16:55:52 +0000 Subject: [PATCH 008/100] removal of experiment code from Promo --- .../ArticleLinksBlock/Promo/index.jsx | 124 ++++-------------- .../ArticleLinksBlock/Promo/index.test.jsx | 8 +- .../components/ArticleLinksBlock/index.jsx | 110 +--------------- 3 files changed, 30 insertions(+), 212 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.jsx b/src/app/components/ArticleLinksBlock/Promo/index.jsx index ebf5b22193e..c28a16b14d6 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.jsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.jsx @@ -9,7 +9,6 @@ import { } from '#psammead/gel-foundations/src/spacings'; import { GEL_GROUP_0_SCREEN_WIDTH_MIN, - GEL_GROUP_1_SCREEN_WIDTH_MIN, GEL_GROUP_2_SCREEN_WIDTH_MIN, GEL_GROUP_3_SCREEN_WIDTH_MIN, GEL_GROUP_4_SCREEN_WIDTH_MIN, @@ -17,7 +16,6 @@ import { import filterForBlockType from '#lib/utilities/blockHandlers'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import PromoTimestamp from '#components/Promo/timestamp'; -import LiveLabel from '../../LiveLabel'; import { ServiceContext } from '../../../contexts/ServiceContext'; const StyledLink = styled(Link)` @@ -28,13 +26,9 @@ const StyledLink = styled(Link)` overflow-x: hidden; overflow-y: hidden; - - ${({ experimentVariant }) => - !experimentVariant && - ` -webkit-line-clamp: 4; - -webkit-box-orient: vertical; - display: -webkit-box; - `} + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; + display: -webkit-box; &:hover, &:focus { @@ -64,22 +58,6 @@ const PromoBox = styled.div` @media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN}) { width: 12.6875rem; } - ${({ experimentVariant }) => - experimentVariant && - ` - display: block; - margin-bottom: 0; - @media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN}) { - width: 11.5rem; - } - @media (min-width: ${GEL_GROUP_1_SCREEN_WIDTH_MIN}) { - width: 17rem; - } - @media (min-width: ${GEL_GROUP_3_SCREEN_WIDTH_MIN}) { - width: 15.5rem; - } - padding: ${GEL_SPACING}; - `} `; const OperaPromoBox = styled.div` @@ -99,95 +77,45 @@ const TimeStamp = styled(PromoTimestamp)` color: ${({ theme }) => theme.isDarkUi && theme.palette.GREY_6}; `; -const Promo = ({ block, experimentVariant, clickTracker }) => { +const Promo = ({ block, clickTracker }) => { const { script, service, serviceDatetimeLocale } = use(ServiceContext); - let title; - let href; - let textBlock; - let aresLinkBlock; - let timestamp; - let isLive; - - switch (experimentVariant) { - case 'top-bar-top-stories': - case 'read-more-a-and-top-stories': { - const overtypedHeadline = block?.headlines?.overtyped ?? ''; - const mainHeadline = block?.headlines?.headline ?? ''; - const headlineBlockText = - block?.headlines?.promoHeadline?.blocks?.[0]?.model?.blocks?.[0]?.model - ?.text ?? ''; - const name = block?.name ?? ''; - - title = - overtypedHeadline || - mainHeadline || - headlineBlockText || - name || - block.headline || - ''; - - const canonicalUrl = block?.locators?.canonicalUrl ?? ''; - const assetUri = block?.locators?.assetUri ?? ''; - const uri = block?.uri ?? ''; - href = - canonicalUrl || - assetUri || - uri || - (block.destinationUrl - ? `https://www.bbc.com${block.destinationUrl}` - : ''); - isLive = block.isLive; - break; - } - case 'top-bar-most-read': - title = block.title; - href = block.href; - break; - default: - textBlock = filterForBlockType(block?.model?.blocks || {}, 'text'); - aresLinkBlock = filterForBlockType( - block?.model?.blocks || {}, - 'aresLink', - ); - timestamp = path( - ['model', 'blocks', '0', 'model', 'timestamp'], - aresLinkBlock, - ); - href = - path( - ['model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'locator'], - textBlock, - ) || ''; - title = - path( - ['model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'text'], - textBlock, - ) || ''; - break; - } + const textBlock = filterForBlockType(block?.model?.blocks || {}, 'text'); + const aresLinkBlock = filterForBlockType( + block?.model?.blocks || {}, + 'aresLink', + ); + const timestamp = path( + ['model', 'blocks', '0', 'model', 'timestamp'], + aresLinkBlock, + ); + const href = + path( + ['model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'locator'], + textBlock, + ) || ''; + const title = + path( + ['model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'text'], + textBlock, + ) || ''; const isOperaMini = useOperaMiniDetection(); const WrapperPromoBox = isOperaMini ? OperaPromoBox : PromoBox; return ( - + - {isLive && } {title} - {timestamp && !experimentVariant && ( - + {timestamp && ( + {timestamp} )} diff --git a/src/app/components/ArticleLinksBlock/Promo/index.test.jsx b/src/app/components/ArticleLinksBlock/Promo/index.test.jsx index 9f34ad5df6e..1f524583abf 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.test.jsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.test.jsx @@ -3,13 +3,9 @@ import { PromoSingleBlock, oneLinkWithTimestamp } from '../helpers/fixtureData'; import Promo from '.'; import { ServiceContextProvider } from '../../../contexts/ServiceContext'; -const ArticleLinksBlock = ({ block, experimentVariant }) => ( +const ArticleLinksBlock = ({ block }) => ( - {}} - experimentVariant={experimentVariant} - /> + {}} /> ); diff --git a/src/app/components/ArticleLinksBlock/index.jsx b/src/app/components/ArticleLinksBlock/index.jsx index 52f3de0e5a3..bd8fbed8784 100644 --- a/src/app/components/ArticleLinksBlock/index.jsx +++ b/src/app/components/ArticleLinksBlock/index.jsx @@ -2,7 +2,6 @@ import { use } from 'react'; import { GEL_SPACING, GEL_SPACING_DBL, - GEL_SPACING_QUAD, } from '#psammead/gel-foundations/src/spacings'; import styled from '@emotion/styled'; @@ -13,8 +12,6 @@ import tail from 'ramda/src/tail'; import { GEL_GROUP_0_SCREEN_WIDTH_MIN, GEL_GROUP_2_SCREEN_WIDTH_MIN, - GEL_GROUP_3_SCREEN_WIDTH_MAX, - GEL_GROUP_3_SCREEN_WIDTH_MIN, GEL_GROUP_4_SCREEN_WIDTH_MIN, } from '#psammead/gel-foundations/src/breakpoints'; import { GridItemMediumNoMargin } from '#components/Grid'; @@ -47,28 +44,6 @@ const ScrollablePromoContainer = styled.div` &::-webkit-scrollbar { display: none; } - ${({ experimentVariant }) => - experimentVariant && - experimentVariant !== 'off' && - ` - padding: 0 ${GEL_SPACING} ${GEL_SPACING_DBL}; - margin: 0rem; - - @media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN}) { - padding: 0 ${GEL_SPACING_DBL} ${GEL_SPACING_DBL}; - margin: 0 -0.2rem; - } - - @media (min-width: ${GEL_GROUP_3_SCREEN_WIDTH_MIN}) { - margin: 0 -0.8rem; - } - - @media (min-width: ${GEL_GROUP_3_SCREEN_WIDTH_MAX}) { - display: none; - } - - width: 100vw; - `} `; const LabelComponent = styled.strong` @@ -93,70 +68,12 @@ const LabelComponent = styled.strong` `} `; -const LabelComponentOJTopBar = styled(({ ariaLabel, ...props }) => ( - -))` - ${({ theme: { fontSizes } }) => fontSizes.brevier}; - ${({ theme: { fontVariants } }) => fontVariants.sansRegular}; - display: inline-block; - margin-bottom: ${GEL_SPACING_DBL}; - color: ${({ theme }) => - theme.isDarkUi ? theme.palette.GREY_2 : theme.palette.SHADOW}; - - ${({ dir }) => - ` - @media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING}; - } - @media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? `left` : `right`}: ${GEL_SPACING_DBL}; - } - @media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? `left` : `right`}: 0; - } - `} - - padding: 0 ${GEL_SPACING}; - - @media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN}) { - margin: 0rem; - } - - @media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN}) { - padding: 0 ${GEL_SPACING_DBL}; - margin: 0 -0.2rem; - } - - @media (min-width: ${GEL_GROUP_3_SCREEN_WIDTH_MIN}) { - margin: 0 -0.8rem; - } - - @media (min-width: ${GEL_GROUP_3_SCREEN_WIDTH_MAX}) { - display: none; - } - - display: flex; - align-items: center; - height: ${GEL_SPACING_QUAD}; - background: ${GREY_2}; - width: 100vw; -`; - -const ArticleLinksBlock = ({ - blocks, - blockGroupIndex = null, - experimentVariant = null, -}) => { +const ArticleLinksBlock = ({ blocks, blockGroupIndex = null }) => { const { script, service, dir, translations } = use(ServiceContext); const eventTrackingData = { componentName: `edoj${blockGroupIndex}`, format: 'CHD=edoj', - ...(experimentVariant && { - componentName: 'top-bar-oj', - sendOptimizelyEvents: true, - viewThreshold: 0, - }), }; const viewTracker = useViewTracker(eventTrackingData); @@ -193,30 +110,7 @@ const ArticleLinksBlock = ({ }), }; - return experimentVariant ? ( - <> - - {title} - - - - - - - - ) : ( + return ( {title && ( Date: Wed, 17 Dec 2025 16:58:47 +0000 Subject: [PATCH 009/100] remove experiment code from promo list --- .../ArticleLinksBlock/PromoList/index.jsx | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.jsx b/src/app/components/ArticleLinksBlock/PromoList/index.jsx index 88cec38b7d1..57747b83661 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.jsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.jsx @@ -41,12 +41,12 @@ const StyledList = styled.li` display: flex; flex-shrink: 0; - ${({ dir, experimentVariant }) => + ${({ dir }) => ` @media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN}){ margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING}; &:first-child { - margin-${dir === 'ltr' ? 'left' : 'right'}: ${experimentVariant && experimentVariant !== 'off' ? 0 : GEL_SPACING}; + margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING}; } &:last-child { margin-${dir === 'ltr' ? 'right' : 'left'}: ${GEL_SPACING}; @@ -56,7 +56,7 @@ const StyledList = styled.li` margin-${dir === 'ltr' ? `left` : `right`}: ${GEL_SPACING_DBL}; &:first-child { - margin-${dir === 'ltr' ? 'left' : 'right'}: ${experimentVariant && experimentVariant !== 'off' ? 0 : GEL_SPACING_DBL}; + margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING_DBL}; } } @media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN}){ @@ -79,19 +79,10 @@ const OperaStyledList = styled.li` margin-${dir === 'ltr' ? `left` : `right`}: 0;}`} `; -const PromoList = ({ - blocks, - experimentVariant, - viewTracker, - clickTracker, - a11yAttributes, -}) => { +const PromoList = ({ blocks, viewTracker, clickTracker, a11yAttributes }) => { const { dir } = use(ServiceContext); const isOperaMini = useOperaMiniDetection(); - const listBlocks = - experimentVariant === 'top-bar-most-read' - ? blocks.slice(0, 5) - : blocks.slice(0, 3); + const listBlocks = blocks.slice(0, 3); const ScrollPromo = isOperaMini ? OperaScrollPromo : StandardScrollPromo; const List = isOperaMini ? OperaStyledList : StyledList; @@ -110,13 +101,8 @@ const PromoList = ({ // eslint-disable-next-line react/no-array-index-key key={index} dir={dir} - experimentVariant={experimentVariant} > - + ); })} From d760e56f47781fd7be98cc36c8b1455763e3d569 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 17:06:27 +0000 Subject: [PATCH 010/100] remove unused code --- src/app/components/ArticleLinksBlock/index.jsx | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.jsx b/src/app/components/ArticleLinksBlock/index.jsx index bd8fbed8784..5fbaecf3850 100644 --- a/src/app/components/ArticleLinksBlock/index.jsx +++ b/src/app/components/ArticleLinksBlock/index.jsx @@ -18,7 +18,6 @@ import { GridItemMediumNoMargin } from '#components/Grid'; import useViewTracker from '#hooks/useViewTracker'; import useClickTrackerHandler from '#hooks/useClickTrackerHandler'; import idSanitiser from '#lib/utilities/idSanitiser'; -import { GREY_2 } from '#app/components/ThemeProvider/palette'; import { ServiceContext } from '../../contexts/ServiceContext'; import Promo from './Promo'; import PromoList from './PromoList'; @@ -34,18 +33,6 @@ const PromoWrapper = styled.div` } `; -const ScrollablePromoContainer = styled.div` - background: ${GREY_2}; - padding: ${GEL_SPACING}; - display: flex; - overflow-x: auto; - -ms-overflow-style: none; - scrollbar-width: none; - &::-webkit-scrollbar { - display: none; - } -`; - const LabelComponent = styled.strong` display: block; ${({ theme: { fontSizes } }) => fontSizes.doublePica}; From 501e3f4b3b2308e60297acb263571b110ec9a2a6 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 17 Dec 2025 17:08:25 +0000 Subject: [PATCH 011/100] remove experiment storybook examples --- .../ArticleLinksBlock/index.stories.jsx | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.stories.jsx b/src/app/components/ArticleLinksBlock/index.stories.jsx index b2292b06021..7105ccd6100 100644 --- a/src/app/components/ArticleLinksBlock/index.stories.jsx +++ b/src/app/components/ArticleLinksBlock/index.stories.jsx @@ -90,22 +90,3 @@ export const WithTimestamp = (_, { service }) => ( ); - -export const OJTopBarTopStories = (_, { service }) => ( - -); - -export const OJTopBarTopStoriesWithLiveLabel = (_, { service }) => ( - -); - -export const OJTopBarMostRead = (_, { service }) => ( - -); - -export const OJTopBarMostReadRTL = () => ( - -); From de75dff2b13ea1740e1a132ddbff80d0e99e5ddb Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 10:38:19 +0000 Subject: [PATCH 012/100] updated snapshots --- .../ArticleLinksBlock/__snapshots__/index.test.jsx.snap | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap index 93894e197a0..e8399300bbf 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing -exports[`ScrollablePromo Mid Page ScrollablePromo it should match a11y snapshot for list 1`] = ` +exports[`Article Links Block Mid Page Article Links Block it should match a11y snapshot for list 1`] = ` @media (max-width: 14.9375rem) { .emotion-0 { margin-left: 0%; @@ -365,7 +365,7 @@ exports[`ScrollablePromo Mid Page ScrollablePromo it should match a11y snapshot `; -exports[`ScrollablePromo Mid Page ScrollablePromo it should match a11y snapshot for list with no title 1`] = ` +exports[`Article Links Block Mid Page Article Links Block it should match a11y snapshot for list with no title 1`] = ` @media (max-width: 14.9375rem) { .emotion-0 { margin-left: 0%; @@ -596,7 +596,7 @@ exports[`ScrollablePromo Mid Page ScrollablePromo it should match a11y snapshot `; -exports[`ScrollablePromo Mid Page ScrollablePromo it should match a11y snapshot for single card 1`] = ` +exports[`Article Links Block Mid Page Article Links Block it should match a11y snapshot for single card 1`] = ` @media (max-width: 14.9375rem) { .emotion-0 { margin-left: 0%; @@ -878,7 +878,7 @@ exports[`ScrollablePromo Mid Page ScrollablePromo it should match a11y snapshot `; -exports[`ScrollablePromo Mid Page ScrollablePromo it should match snapshot when in dark ui mode 1`] = ` +exports[`Article Links Block Mid Page Article Links Block it should match snapshot when in dark ui mode 1`] = ` @media (max-width: 14.9375rem) { .emotion-0 { margin-left: 0%; From d10b52930897a7126957701cf76fbc38610ff3cd Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 10:58:36 +0000 Subject: [PATCH 013/100] updated a.jsx to typescript --- src/app/legacy/components/Promo/a.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/app/legacy/components/Promo/a.tsx diff --git a/src/app/legacy/components/Promo/a.tsx b/src/app/legacy/components/Promo/a.tsx new file mode 100644 index 00000000000..5c347e67d12 --- /dev/null +++ b/src/app/legacy/components/Promo/a.tsx @@ -0,0 +1,19 @@ +import styled from '@emotion/styled'; + +const A = styled.a(props => ({ + color: props.theme?.palette?.GREY_10, + textDecoration: 'none', + display: 'block', + '&:hover, &:focus': { textDecoration: 'underline' }, + '&:visited': { color: props.theme?.palette?.GREY_6 }, + '&:before': { + position: 'absolute', + bottom: 0, + top: 0, + left: 0, + right: 0, + content: '""', + }, +})); + +export default A; From 2c00a903be986c4d4e9722123d406a1aa5917881 Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 11:03:21 +0000 Subject: [PATCH 014/100] updated heading.jsx to typescript --- src/app/legacy/components/Promo/heading.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/legacy/components/Promo/heading.tsx diff --git a/src/app/legacy/components/Promo/heading.tsx b/src/app/legacy/components/Promo/heading.tsx new file mode 100644 index 00000000000..b6af756c0b9 --- /dev/null +++ b/src/app/legacy/components/Promo/heading.tsx @@ -0,0 +1,11 @@ +import styled from '@emotion/styled'; + +const Heading = styled.h2(props => ({ + ...props.theme?.fontVariants?.serifMedium, + ...props.theme?.fontSizes?.bodyCopy, + color: props.theme?.palette?.EBON, + marginTop: 0, + marginBottom: `${props.theme?.spacings?.FULL ?? 0}rem`, +})); + +export default Heading; From edcd91c7b145f8e6d0918f71591f3c4ad7e0624a Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 11:05:25 +0000 Subject: [PATCH 015/100] updated body.jsx to typescript --- src/app/legacy/components/Promo/body.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/app/legacy/components/Promo/body.tsx diff --git a/src/app/legacy/components/Promo/body.tsx b/src/app/legacy/components/Promo/body.tsx new file mode 100644 index 00000000000..1c6fecdbd8b --- /dev/null +++ b/src/app/legacy/components/Promo/body.tsx @@ -0,0 +1,9 @@ +import styled from '@emotion/styled'; + +const P = styled.p(props => ({ + ...props.theme?.fontVariants?.sansRegular, + ...props.theme?.fontSizes?.bodyCopy, + color: props.theme?.palette?.EBON, +})); + +export default P; From 93c14d52b9d95000c72c216522eb388211601497 Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 11:06:24 +0000 Subject: [PATCH 016/100] updated footer.jsx to typescript --- src/app/legacy/components/Promo/footer.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/app/legacy/components/Promo/footer.tsx diff --git a/src/app/legacy/components/Promo/footer.tsx b/src/app/legacy/components/Promo/footer.tsx new file mode 100644 index 00000000000..6699e0e6144 --- /dev/null +++ b/src/app/legacy/components/Promo/footer.tsx @@ -0,0 +1,9 @@ +import styled from '@emotion/styled'; + +const Footer = styled.footer(props => ({ + ...props.theme?.fontVariants?.sansRegular, + ...props.theme?.fontSizes?.brevier, + color: props.theme?.palette?.RHINO, +})); + +export default Footer; From 11e6062e9dba1c241a75d365adf574de14585439 Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 11:27:12 +0000 Subject: [PATCH 017/100] undid recent typescript conversion changes due to incorrect file location --- src/app/legacy/components/Promo/a.tsx | 19 ------------------- src/app/legacy/components/Promo/body.tsx | 9 --------- src/app/legacy/components/Promo/footer.tsx | 9 --------- src/app/legacy/components/Promo/heading.tsx | 11 ----------- 4 files changed, 48 deletions(-) delete mode 100644 src/app/legacy/components/Promo/a.tsx delete mode 100644 src/app/legacy/components/Promo/body.tsx delete mode 100644 src/app/legacy/components/Promo/footer.tsx delete mode 100644 src/app/legacy/components/Promo/heading.tsx diff --git a/src/app/legacy/components/Promo/a.tsx b/src/app/legacy/components/Promo/a.tsx deleted file mode 100644 index 5c347e67d12..00000000000 --- a/src/app/legacy/components/Promo/a.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import styled from '@emotion/styled'; - -const A = styled.a(props => ({ - color: props.theme?.palette?.GREY_10, - textDecoration: 'none', - display: 'block', - '&:hover, &:focus': { textDecoration: 'underline' }, - '&:visited': { color: props.theme?.palette?.GREY_6 }, - '&:before': { - position: 'absolute', - bottom: 0, - top: 0, - left: 0, - right: 0, - content: '""', - }, -})); - -export default A; diff --git a/src/app/legacy/components/Promo/body.tsx b/src/app/legacy/components/Promo/body.tsx deleted file mode 100644 index 1c6fecdbd8b..00000000000 --- a/src/app/legacy/components/Promo/body.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import styled from '@emotion/styled'; - -const P = styled.p(props => ({ - ...props.theme?.fontVariants?.sansRegular, - ...props.theme?.fontSizes?.bodyCopy, - color: props.theme?.palette?.EBON, -})); - -export default P; diff --git a/src/app/legacy/components/Promo/footer.tsx b/src/app/legacy/components/Promo/footer.tsx deleted file mode 100644 index 6699e0e6144..00000000000 --- a/src/app/legacy/components/Promo/footer.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import styled from '@emotion/styled'; - -const Footer = styled.footer(props => ({ - ...props.theme?.fontVariants?.sansRegular, - ...props.theme?.fontSizes?.brevier, - color: props.theme?.palette?.RHINO, -})); - -export default Footer; diff --git a/src/app/legacy/components/Promo/heading.tsx b/src/app/legacy/components/Promo/heading.tsx deleted file mode 100644 index b6af756c0b9..00000000000 --- a/src/app/legacy/components/Promo/heading.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import styled from '@emotion/styled'; - -const Heading = styled.h2(props => ({ - ...props.theme?.fontVariants?.serifMedium, - ...props.theme?.fontSizes?.bodyCopy, - color: props.theme?.palette?.EBON, - marginTop: 0, - marginBottom: `${props.theme?.spacings?.FULL ?? 0}rem`, -})); - -export default Heading; From 3b50ac81af2f5ed8cae4e88b0ca7dd1876218c8b Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 13:32:08 +0000 Subject: [PATCH 018/100] updated index file from jsx to tsx --- .../components/ArticleLinksBlock/index.tsx | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 src/app/components/ArticleLinksBlock/index.tsx diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx new file mode 100644 index 00000000000..4e79cc5072a --- /dev/null +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -0,0 +1,142 @@ +import { use } from 'react'; +import styled from '@emotion/styled'; +import path from 'ramda/src/path'; +import pathOr from 'ramda/src/pathOr'; +import isEmpty from 'ramda/src/isEmpty'; +import tail from 'ramda/src/tail'; +import { + GEL_SPACING, + GEL_SPACING_DBL, +} from '#psammead/gel-foundations/src/spacings'; +import { + GEL_GROUP_0_SCREEN_WIDTH_MIN, + GEL_GROUP_2_SCREEN_WIDTH_MIN, + GEL_GROUP_4_SCREEN_WIDTH_MIN, +} from '#psammead/gel-foundations/src/breakpoints'; +import { GridItemMediumNoMargin } from '#components/Grid'; +import useViewTracker from '#hooks/useViewTracker'; +import useClickTrackerHandler from '#hooks/useClickTrackerHandler'; +import idSanitiser from '#lib/utilities/idSanitiser'; +import { OptimoBlock } from '#app/models/types/optimo'; +import { ServiceContext } from '../../contexts/ServiceContext'; +import Promo from './Promo'; +import PromoList from './PromoList'; + +interface ArticleLinksBlockProps { + blocks: OptimoBlock[]; + blockGroupIndex?: number | null; +} + +const PromoWrapper = styled.div<{ dir: string }>(({ dir }) => ({ + [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: GEL_SPACING, + [`@media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN})`]: { + [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: GEL_SPACING_DBL, + }, + [`@media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN})`]: { + [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: 0, + }, +})); + +const LabelComponent = styled.strong<{ dir: string }>(({ theme, dir }) => ({ + display: 'block', + ...theme.fontSizes.doublePica, + ...theme.fontVariants.sansRegular, + marginBottom: GEL_SPACING_DBL, + color: theme.isDarkUi ? theme.palette.GREY_2 : theme.palette.SHADOW, + [`@media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN})`]: { + [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: GEL_SPACING, + }, + [`@media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN})`]: { + [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: GEL_SPACING_DBL, + }, + [`@media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN})`]: { + [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: 0, + }, +})); + +function ArticleLinksBlock({ + blocks, + blockGroupIndex = null, +}: ArticleLinksBlockProps) { + const { script, service, dir, translations } = use(ServiceContext); + + const eventTrackingData = { + componentName: `edoj${blockGroupIndex}`, + format: 'CHD=edoj', + }; + + const viewTracker = useViewTracker(eventTrackingData); + const clickTracker = useClickTrackerHandler(eventTrackingData); + + if (!blocks || isEmpty(blocks)) { + return null; + } + + const title = + blocks[0]?.type === 'title' + ? path( + [ + '0', + 'model', + 'blocks', + '0', + 'model', + 'blocks', + '0', + 'model', + 'text', + ], + blocks, + ) + : undefined; + + const blocksWithoutTitle = + blocks[0]?.type === 'title' ? tail(blocks) : blocks; + + const isSingleItem = blocksWithoutTitle.length === 1; + + const ariaLabel = title ? idSanitiser(title) : undefined; + + const a11yAttributes = { + as: 'section', + role: 'region', + ...(ariaLabel + ? { 'aria-labelledby': ariaLabel } + : { + 'aria-label': pathOr( + 'Related Content', + ['relatedContent'], + translations, + ), + }), + }; + + return ( + + {title && ( + + {title} + + )} + {isSingleItem ? ( + + + + ) : ( + + )} + + ); +} + +export default ArticleLinksBlock; From 9f2335e85714c70eba603d0fe21ea38ec63aa3d9 Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 14:01:10 +0000 Subject: [PATCH 019/100] added a11yAttributes prop and fixed reactNode issue --- src/app/components/ArticleLinksBlock/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 4e79cc5072a..28bf3115e82 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -113,7 +113,7 @@ function ArticleLinksBlock({ return ( - {title && ( + {typeof title === 'string' && title.length > 0 && ( )} From 9995ed132ca3c52082ccd71c875837cf9149200e Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 14:12:40 +0000 Subject: [PATCH 020/100] removed script and service --- src/app/components/ArticleLinksBlock/index.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 28bf3115e82..d5551914c34 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -58,7 +58,7 @@ function ArticleLinksBlock({ blocks, blockGroupIndex = null, }: ArticleLinksBlockProps) { - const { script, service, dir, translations } = use(ServiceContext); + const { dir, translations } = use(ServiceContext); const eventTrackingData = { componentName: `edoj${blockGroupIndex}`, @@ -117,8 +117,6 @@ function ArticleLinksBlock({ {title} From a4fbb02481f0ee35a1a5d5ffb8d6fbf4067efae0 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 18 Dec 2025 15:53:28 +0000 Subject: [PATCH 021/100] remove unused fixture imports --- src/app/components/ArticleLinksBlock/index.stories.jsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.stories.jsx b/src/app/components/ArticleLinksBlock/index.stories.jsx index 7105ccd6100..9098e953c66 100644 --- a/src/app/components/ArticleLinksBlock/index.stories.jsx +++ b/src/app/components/ArticleLinksBlock/index.stories.jsx @@ -10,10 +10,6 @@ import { twoLinksWithNoImages, truncatedTextInSingleLink, arabicText, - topStoriesBlocks, - topStoriesBlocksWithLiveItem, - mostReadBlocks, - mostReadBlocksRTL, } from './helpers/fixtureData'; const BackGround = styled.div` From 0eab5229cffb13cd4e4a62c6585646a66d1e75dc Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Thu, 18 Dec 2025 15:53:38 +0000 Subject: [PATCH 022/100] removed jsx file tsc supersedes --- .../components/ArticleLinksBlock/index.jsx | 128 ------------------ 1 file changed, 128 deletions(-) delete mode 100644 src/app/components/ArticleLinksBlock/index.jsx diff --git a/src/app/components/ArticleLinksBlock/index.jsx b/src/app/components/ArticleLinksBlock/index.jsx deleted file mode 100644 index 5fbaecf3850..00000000000 --- a/src/app/components/ArticleLinksBlock/index.jsx +++ /dev/null @@ -1,128 +0,0 @@ -import { use } from 'react'; -import { - GEL_SPACING, - GEL_SPACING_DBL, -} from '#psammead/gel-foundations/src/spacings'; - -import styled from '@emotion/styled'; -import path from 'ramda/src/path'; -import pathOr from 'ramda/src/pathOr'; -import isEmpty from 'ramda/src/isEmpty'; -import tail from 'ramda/src/tail'; -import { - GEL_GROUP_0_SCREEN_WIDTH_MIN, - GEL_GROUP_2_SCREEN_WIDTH_MIN, - GEL_GROUP_4_SCREEN_WIDTH_MIN, -} from '#psammead/gel-foundations/src/breakpoints'; -import { GridItemMediumNoMargin } from '#components/Grid'; -import useViewTracker from '#hooks/useViewTracker'; -import useClickTrackerHandler from '#hooks/useClickTrackerHandler'; -import idSanitiser from '#lib/utilities/idSanitiser'; -import { ServiceContext } from '../../contexts/ServiceContext'; -import Promo from './Promo'; -import PromoList from './PromoList'; - -const PromoWrapper = styled.div` - ${({ dir }) => `margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING};`} - @media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN}) { - ${({ dir }) => - `margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING_DBL};`} - } - @media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN}) { - ${({ dir }) => `margin-${dir === 'ltr' ? 'left' : 'right'}: 0;`} - } -`; - -const LabelComponent = styled.strong` - display: block; - ${({ theme: { fontSizes } }) => fontSizes.doublePica}; - ${({ theme: { fontVariants } }) => fontVariants.sansRegular}; - margin-bottom: ${GEL_SPACING_DBL}; - color: ${({ theme }) => - theme.isDarkUi ? theme.palette.GREY_2 : theme.palette.SHADOW}; - - ${({ dir }) => - ` - @media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING}; - } - @media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? `left` : `right`}: ${GEL_SPACING_DBL}; - } - @media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? `left` : `right`}: 0; - } -`} -`; - -const ArticleLinksBlock = ({ blocks, blockGroupIndex = null }) => { - const { script, service, dir, translations } = use(ServiceContext); - - const eventTrackingData = { - componentName: `edoj${blockGroupIndex}`, - format: 'CHD=edoj', - }; - - const viewTracker = useViewTracker(eventTrackingData); - const clickTracker = useClickTrackerHandler(eventTrackingData); - - if (!blocks || isEmpty(blocks)) { - return null; - } - - const title = - blocks[0].type === 'title' && - path( - ['0', 'model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'text'], - blocks, - ); - - const blocksWithoutTitle = blocks[0].type === 'title' ? tail(blocks) : blocks; - - const isSingleItem = blocksWithoutTitle.length === 1; - - const ariaLabel = title && idSanitiser(title); - - const a11yAttributes = { - as: 'section', - role: 'region', - ...(ariaLabel - ? { 'aria-labelledby': ariaLabel } - : { - 'aria-label': pathOr( - 'Related Content', - ['relatedContent'], - translations, - ), - }), - }; - - return ( - - {title && ( - - {title} - - )} - {isSingleItem ? ( - - - - ) : ( - - )} - - ); -}; - -export default ArticleLinksBlock; From f0a7e2d5f5ba0d2aafdb9d279fe9002479787bb2 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 18 Dec 2025 16:06:03 +0000 Subject: [PATCH 023/100] add metadata file --- .../ArticleLinksBlock/metadata.json | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/app/components/ArticleLinksBlock/metadata.json diff --git a/src/app/components/ArticleLinksBlock/metadata.json b/src/app/components/ArticleLinksBlock/metadata.json new file mode 100644 index 00000000000..1335762526c --- /dev/null +++ b/src/app/components/ArticleLinksBlock/metadata.json @@ -0,0 +1,29 @@ +{ + "alpha": false, + "lastUpdated": { + "day": 18, + "month": "December", + "year": 2025 + }, + "uxAccessibilityDoc": { + "done": false, + "reference": { + "url": "", + "label": "Screen Reader UX" + } + }, + "acceptanceCriteria": { + "done": false, + "reference": { + "url": "", + "label": "Accessibility Acceptance Criteria" + } + }, + "swarm": { + "done": false, + "reference": { + "url": "", + "label": "Accessibility Swarm Notes" + } + } +} From f37e4608000f3696adc27d8080683f8eabe2de0f Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Fri, 19 Dec 2025 11:15:14 +0000 Subject: [PATCH 024/100] add readme file --- src/app/components/ArticleLinksBlock/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/app/components/ArticleLinksBlock/README.md diff --git a/src/app/components/ArticleLinksBlock/README.md b/src/app/components/ArticleLinksBlock/README.md new file mode 100644 index 00000000000..e69de29bb2d From c2552f8ae3c662d5ff6a981e056e69d00ebbd286 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Fri, 19 Dec 2025 11:17:24 +0000 Subject: [PATCH 025/100] WIP change stories file to tsx --- .../ArticleLinksBlock/index.stories.jsx | 88 ------------------ .../ArticleLinksBlock/index.stories.tsx | 91 +++++++++++++++++++ 2 files changed, 91 insertions(+), 88 deletions(-) delete mode 100644 src/app/components/ArticleLinksBlock/index.stories.jsx create mode 100644 src/app/components/ArticleLinksBlock/index.stories.tsx diff --git a/src/app/components/ArticleLinksBlock/index.stories.jsx b/src/app/components/ArticleLinksBlock/index.stories.jsx deleted file mode 100644 index 9098e953c66..00000000000 --- a/src/app/components/ArticleLinksBlock/index.stories.jsx +++ /dev/null @@ -1,88 +0,0 @@ -import styled from '@emotion/styled'; -import { ServiceContextProvider } from '#contexts/ServiceContext'; -import ArticleLinksBlock from '.'; -import { - threeLinks, - oneLinkOnly, - oneLinkWithNoTitle, - oneLinkWithTimestamp, - moreThanThreeLinks, - twoLinksWithNoImages, - truncatedTextInSingleLink, - arabicText, -} from './helpers/fixtureData'; - -const BackGround = styled.div` - background-color: #f6f6f6; - padding: 2rem; -`; - -const ArticleLinksBlockComponent = ({ - data, - service, - experimentVariant = null, -}) => ( - - - -); - -export default { - title: 'Components/Article Links Block', - ArticleLinksBlockComponent, -}; - -export const ThreeLinks = (_, { service }) => ( - - - -); - -export const OnlyOneLink = (_, { service }) => ( - - - -); - -export const OneLinkWithNoTitle = (_, { service }) => ( - - - -); - -export const MoreThanThreeLinks = (_, { service }) => ( - - - -); - -export const NoImagesInData = (_, { service }) => ( - - - -); - -export const TruncatedTextInSingleLink = (_, { service }) => ( - - - -); - -export const ArabicText = () => ( - - - -); - -ArabicText.globals = { - service: { service: 'arabic' }, -}; - -export const WithTimestamp = (_, { service }) => ( - - - -); diff --git a/src/app/components/ArticleLinksBlock/index.stories.tsx b/src/app/components/ArticleLinksBlock/index.stories.tsx new file mode 100644 index 00000000000..b1c6b53b0ec --- /dev/null +++ b/src/app/components/ArticleLinksBlock/index.stories.tsx @@ -0,0 +1,91 @@ +import styled from '@emotion/styled'; +import { ServiceContextProvider } from '#contexts/ServiceContext'; +import ArticleLinksBlock from '.'; +import { + threeLinks, + oneLinkOnly, + oneLinkWithNoTitle, + oneLinkWithTimestamp, + moreThanThreeLinks, + twoLinksWithNoImages, + truncatedTextInSingleLink, + arabicText, +} from './helpers/fixtureData'; +import metadata from './metadata.json'; +import readme from './README.md'; +import { OptimoBlock } from '#app/models/types/optimo'; +import { StoryArgs } from '../../models/types/storybook'; + +const BackGround = styled.div` + background-color: #f6f6f6; + padding: 2rem; +`; + +interface Props { + blocks: OptimoBlock[]; +} + +const Component = ({ blocks }: Props) => { + return ; +}; + +export default { + title: 'Components/Article Links Block', + Component, + parameters: { + docs: { readme }, + metadata, + }, +}; + +export const ThreeLinks = (_: StoryArgs) => ( + + + +); + +export const OnlyOneLink = (_: StoryArgs) => ( + + + +); + +export const OneLinkWithNoTitle = (_: StoryArgs) => ( + + + +); + +export const MoreThanThreeLinks = (_: StoryArgs) => ( + + + +); + +export const NoImagesInData = (_: StoryArgs) => ( + + + +); + +export const TruncatedTextInSingleLink = (_: StoryArgs) => ( + + + +); + +export const ArabicText = (_: StoryArgs) => ( + + + +); + +ArabicText.globals = { + service: { service: 'arabic' }, +}; + +export const WithTimestamp = (_: StoryArgs) => ( + + + +); From dc22ca76ac39ab12c30db294ac182b0cb790aae7 Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Fri, 19 Dec 2025 12:07:50 +0000 Subject: [PATCH 026/100] updated snapshots --- .../ArticleLinksBlock/__snapshots__/index.test.jsx.snap | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap index e8399300bbf..c108291318b 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.jsx.snap @@ -310,10 +310,11 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s > Show all links (no images) -
  • -
+ `; From 176d95f2a6cc62ba4209263901e2bfc03dc7a703 Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Fri, 19 Dec 2025 15:14:49 +0000 Subject: [PATCH 027/100] updaated promo index.jsx to tsx [copilot] --- .../Promo/{index.jsx => index.tsx} | 120 +++++++++--------- 1 file changed, 59 insertions(+), 61 deletions(-) rename src/app/components/ArticleLinksBlock/Promo/{index.jsx => index.tsx} (50%) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.jsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx similarity index 50% rename from src/app/components/ArticleLinksBlock/Promo/index.jsx rename to src/app/components/ArticleLinksBlock/Promo/index.tsx index c28a16b14d6..f977e50b5f6 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.jsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -18,66 +18,64 @@ import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import PromoTimestamp from '#components/Promo/timestamp'; import { ServiceContext } from '../../../contexts/ServiceContext'; -const StyledLink = styled(Link)` - ${({ theme: { fontSizes } }) => fontSizes.pica}; - ${({ theme: { fontVariants } }) => fontVariants.serifBold}; - width: 100%; - text-decoration: none; +interface PromoProps { + block: Record; + clickTracker?: Record; +} - overflow-x: hidden; - overflow-y: hidden; - -webkit-line-clamp: 4; - -webkit-box-orient: vertical; - display: -webkit-box; +const StyledLink = styled(Link)(({ theme }) => ({ + ...theme.fontSizes.pica, + ...theme.fontVariants.serifBold, + width: '100%', + textDecoration: 'none', + overflowX: 'hidden', + overflowY: 'hidden', + WebkitLineClamp: 4, + WebkitBoxOrient: 'vertical', + display: '-webkit-box', + color: theme.isDarkUi ? theme.palette.GREY_10 : theme.palette.GREY_8, + '&:hover, &:focus': { + textDecoration: 'underline', + }, + '&:visited': { + color: theme.palette.GREY_6, + }, +})); - &:hover, - &:focus { - text-decoration: underline; - } +const PromoBox = styled.div(({ theme }) => ({ + position: 'relative', + backgroundColor: theme.isDarkUi ? theme.palette.GREY_3 : theme.palette.WHITE, + padding: GEL_SPACING_DBL, + marginBottom: GEL_SPACING_TRPL, + height: 'auto', + [`@media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN})`]: { + width: '14.8125rem', + }, + [`@media (min-width: ${GEL_GROUP_3_SCREEN_WIDTH_MIN})`]: { + width: '11.125rem', + }, + [`@media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN})`]: { + width: '12.6875rem', + }, +})); - color: ${({ theme }) => - theme.isDarkUi ? theme.palette.GREY_10 : theme.palette.GREY_8}; - &:visited { - color: ${props => props.theme.palette.GREY_6}; - } -`; +const OperaPromoBox = styled.div(({ theme }) => ({ + position: 'relative', + backgroundColor: theme.isDarkUi ? theme.palette.GREY_3 : theme.palette.WHITE, + padding: GEL_SPACING_DBL, + marginBottom: GEL_SPACING_DBL, + width: `calc(100% - ${GEL_SPACING})`, + [`@media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN})`]: { + width: `calc(100% - ${GEL_SPACING_DBL})`, + }, +})); -const PromoBox = styled.div` - position: relative; - background-color: ${({ theme }) => - theme.isDarkUi ? theme.palette.GREY_3 : theme.palette.WHITE}; - padding: ${GEL_SPACING_DBL}; - margin-bottom: ${GEL_SPACING_TRPL}; - height: auto; - @media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN}) { - width: 14.8125rem; - } - @media (min-width: ${GEL_GROUP_3_SCREEN_WIDTH_MIN}) { - width: 11.125rem; - } - @media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN}) { - width: 12.6875rem; - } -`; +const TimeStamp = styled(PromoTimestamp)(({ theme }) => ({ + marginTop: GEL_SPACING, + color: theme.isDarkUi ? theme.palette.GREY_6 : undefined, +})); -const OperaPromoBox = styled.div` - position: relative; - background-color: ${({ theme }) => - theme.isDarkUi ? theme.palette.GREY_3 : theme.palette.WHITE}; - padding: ${GEL_SPACING_DBL}; - margin-bottom: ${GEL_SPACING_DBL}; - width: calc(100% - ${GEL_SPACING}); - @media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN}) { - width: calc(100% - ${GEL_SPACING_DBL}); - } -`; - -const TimeStamp = styled(PromoTimestamp)` - margin-top: ${GEL_SPACING}; - color: ${({ theme }) => theme.isDarkUi && theme.palette.GREY_6}; -`; - -const Promo = ({ block, clickTracker }) => { +function Promo({ block, clickTracker }: PromoProps) { const { script, service, serviceDatetimeLocale } = use(ServiceContext); const textBlock = filterForBlockType(block?.model?.blocks || {}, 'text'); @@ -88,17 +86,17 @@ const Promo = ({ block, clickTracker }) => { const timestamp = path( ['model', 'blocks', '0', 'model', 'timestamp'], aresLinkBlock, - ); + ) as number | undefined; const href = - path( + (path( ['model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'locator'], textBlock, - ) || ''; + ) as string) || ''; const title = - path( + (path( ['model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'text'], textBlock, - ) || ''; + ) as string) || ''; const isOperaMini = useOperaMiniDetection(); @@ -121,6 +119,6 @@ const Promo = ({ block, clickTracker }) => { )} ); -}; +} export default Promo; From 612845debad0dddda9bdd61006176406c87bbe30 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 08:41:54 +0000 Subject: [PATCH 028/100] replace path and pathOr with optional chaining --- .../components/ArticleLinksBlock/index.tsx | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index d5551914c34..e80746d7e82 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -74,20 +74,9 @@ function ArticleLinksBlock({ const title = blocks[0]?.type === 'title' - ? path( - [ - '0', - 'model', - 'blocks', - '0', - 'model', - 'blocks', - '0', - 'model', - 'text', - ], - blocks, - ) + ? // @ts-expect-error - deeply nested + (blocks[0]?.model?.blocks?.[0].model?.blocks?.[0]?.model?.text ?? + undefined) : undefined; const blocksWithoutTitle = @@ -103,11 +92,7 @@ function ArticleLinksBlock({ ...(ariaLabel ? { 'aria-labelledby': ariaLabel } : { - 'aria-label': pathOr( - 'Related Content', - ['relatedContent'], - translations, - ), + 'aria-label': translations?.relatedContent ?? 'Related Content', }), }; From 342ff409be69de30652fdf8fc4619f38f5c1bb4f Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 09:04:19 +0000 Subject: [PATCH 029/100] update PromoProps and remove service and script --- .../ArticleLinksBlock/Promo/index.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index f977e50b5f6..0ff9e288069 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -16,11 +16,14 @@ import { import filterForBlockType from '#lib/utilities/blockHandlers'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import PromoTimestamp from '#components/Promo/timestamp'; +import { OptimoBlock } from '#app/models/types/optimo'; +import { EventTrackingMetadata } from '#app/models/types/eventTracking'; +import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; import { ServiceContext } from '../../../contexts/ServiceContext'; interface PromoProps { - block: Record; - clickTracker?: Record; + block: OptimoBlock; + eventTrackingData?: EventTrackingMetadata; } const StyledLink = styled(Link)(({ theme }) => ({ @@ -75,8 +78,9 @@ const TimeStamp = styled(PromoTimestamp)(({ theme }) => ({ color: theme.isDarkUi ? theme.palette.GREY_6 : undefined, })); -function Promo({ block, clickTracker }: PromoProps) { - const { script, service, serviceDatetimeLocale } = use(ServiceContext); +function Promo({ block, eventTrackingData }: PromoProps) { + const { serviceDatetimeLocale } = use(ServiceContext); + const clickTrackerHandler = useClickTrackerHandler(eventTrackingData); const textBlock = filterForBlockType(block?.model?.blocks || {}, 'text'); const aresLinkBlock = filterForBlockType( @@ -104,12 +108,7 @@ function Promo({ block, clickTracker }: PromoProps) { return ( - + {title} {timestamp && ( From 46ac9233b8418296c7dadef101885e5bb87dc33d Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 09:20:12 +0000 Subject: [PATCH 030/100] replace path with optional chaining --- .../ArticleLinksBlock/Promo/index.tsx | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index 0ff9e288069..aca3c61878c 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -87,20 +87,13 @@ function Promo({ block, eventTrackingData }: PromoProps) { block?.model?.blocks || {}, 'aresLink', ); - const timestamp = path( - ['model', 'blocks', '0', 'model', 'timestamp'], - aresLinkBlock, - ) as number | undefined; + const timestamp = + aresLinkBlock?.model?.blocks?.[0]?.model?.timestamp ?? undefined; + const href = - (path( - ['model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'locator'], - textBlock, - ) as string) || ''; + textBlock?.model?.blocks?.[0]?.model?.blocks?.[0]?.model?.locator ?? ''; const title = - (path( - ['model', 'blocks', '0', 'model', 'blocks', '0', 'model', 'text'], - textBlock, - ) as string) || ''; + textBlock?.model?.blocks?.[0]?.model?.blocks?.[0]?.model?.text ?? ''; const isOperaMini = useOperaMiniDetection(); From 0d25fdd371ed94bdeb2f0ca5bce326e1b7d2304e Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 09:27:31 +0000 Subject: [PATCH 031/100] fix type errors --- src/app/components/ArticleLinksBlock/Promo/index.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index aca3c61878c..b126477aaeb 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -82,9 +82,12 @@ function Promo({ block, eventTrackingData }: PromoProps) { const { serviceDatetimeLocale } = use(ServiceContext); const clickTrackerHandler = useClickTrackerHandler(eventTrackingData); - const textBlock = filterForBlockType(block?.model?.blocks || {}, 'text'); + const textBlock = filterForBlockType( + (block?.model as { blocks?: Record })?.blocks || {}, + 'text', + ); const aresLinkBlock = filterForBlockType( - block?.model?.blocks || {}, + (block?.model as { blocks?: Record })?.blocks || {}, 'aresLink', ); const timestamp = From b0c950e727d5a032d390a2476b9598df1486e100 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 09:28:27 +0000 Subject: [PATCH 032/100] remove ramda imports --- src/app/components/ArticleLinksBlock/Promo/index.tsx | 1 - src/app/components/ArticleLinksBlock/index.tsx | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index b126477aaeb..1163d02f120 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -1,6 +1,5 @@ import { use } from 'react'; import styled from '@emotion/styled'; -import path from 'ramda/src/path'; import { Link } from '#psammead/psammead-story-promo/src'; import { GEL_SPACING, diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index e80746d7e82..cf4507ae549 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -1,7 +1,5 @@ import { use } from 'react'; import styled from '@emotion/styled'; -import path from 'ramda/src/path'; -import pathOr from 'ramda/src/pathOr'; import isEmpty from 'ramda/src/isEmpty'; import tail from 'ramda/src/tail'; import { From cb15ae0e99e6aff17fcd0a8a3415d34318fdbfad Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 11:15:47 +0000 Subject: [PATCH 033/100] change promoList to tsx and update types --- .../PromoList/{index.jsx => index.tsx} | 20 ++++++++++--------- .../components/ArticleLinksBlock/index.tsx | 8 +++----- 2 files changed, 14 insertions(+), 14 deletions(-) rename src/app/components/ArticleLinksBlock/PromoList/{index.jsx => index.tsx} (86%) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.jsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx similarity index 86% rename from src/app/components/ArticleLinksBlock/PromoList/index.jsx rename to src/app/components/ArticleLinksBlock/PromoList/index.tsx index 57747b83661..1e66c73c42e 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.jsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -10,6 +10,8 @@ import { GEL_GROUP_4_SCREEN_WIDTH_MIN, } from '#psammead/gel-foundations/src/breakpoints'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; +import { OptimoBlock } from '#app/models/types/optimo'; +import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import { ServiceContext } from '../../../contexts/ServiceContext'; import Promo from '../Promo'; @@ -79,7 +81,13 @@ const OperaStyledList = styled.li` margin-${dir === 'ltr' ? `left` : `right`}: 0;}`} `; -const PromoList = ({ blocks, viewTracker, clickTracker, a11yAttributes }) => { +interface PromoListProps { + blocks: OptimoBlock[]; + id?: string; + eventTrackingData?: EventTrackingMetadata; +} + +const PromoList = ({ blocks, eventTrackingData }: PromoListProps) => { const { dir } = use(ServiceContext); const isOperaMini = useOperaMiniDetection(); const listBlocks = blocks.slice(0, 3); @@ -88,13 +96,7 @@ const PromoList = ({ blocks, viewTracker, clickTracker, a11yAttributes }) => { const List = isOperaMini ? OperaStyledList : StyledList; return ( - + {listBlocks.map((block, index) => { return ( { key={index} dir={dir} > - + ); })} diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index cf4507ae549..9a74e28f390 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -64,7 +64,7 @@ function ArticleLinksBlock({ }; const viewTracker = useViewTracker(eventTrackingData); - const clickTracker = useClickTrackerHandler(eventTrackingData); + const clickTrackerHandler = useClickTrackerHandler(eventTrackingData); if (!blocks || isEmpty(blocks)) { return null; @@ -107,14 +107,12 @@ function ArticleLinksBlock({ )} {isSingleItem ? ( - + ) : ( )} From 9e7d6560d347aa6e31829106e43d615c5450402c Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 13:54:27 +0000 Subject: [PATCH 034/100] Revert "change promoList to tsx and update types" This reverts commit cb15ae0e99e6aff17fcd0a8a3415d34318fdbfad. --- .../PromoList/{index.tsx => index.jsx} | 20 +++++++++---------- .../components/ArticleLinksBlock/index.tsx | 8 +++++--- 2 files changed, 14 insertions(+), 14 deletions(-) rename src/app/components/ArticleLinksBlock/PromoList/{index.tsx => index.jsx} (86%) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.jsx similarity index 86% rename from src/app/components/ArticleLinksBlock/PromoList/index.tsx rename to src/app/components/ArticleLinksBlock/PromoList/index.jsx index 1e66c73c42e..57747b83661 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.jsx @@ -10,8 +10,6 @@ import { GEL_GROUP_4_SCREEN_WIDTH_MIN, } from '#psammead/gel-foundations/src/breakpoints'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; -import { OptimoBlock } from '#app/models/types/optimo'; -import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import { ServiceContext } from '../../../contexts/ServiceContext'; import Promo from '../Promo'; @@ -81,13 +79,7 @@ const OperaStyledList = styled.li` margin-${dir === 'ltr' ? `left` : `right`}: 0;}`} `; -interface PromoListProps { - blocks: OptimoBlock[]; - id?: string; - eventTrackingData?: EventTrackingMetadata; -} - -const PromoList = ({ blocks, eventTrackingData }: PromoListProps) => { +const PromoList = ({ blocks, viewTracker, clickTracker, a11yAttributes }) => { const { dir } = use(ServiceContext); const isOperaMini = useOperaMiniDetection(); const listBlocks = blocks.slice(0, 3); @@ -96,7 +88,13 @@ const PromoList = ({ blocks, eventTrackingData }: PromoListProps) => { const List = isOperaMini ? OperaStyledList : StyledList; return ( - + {listBlocks.map((block, index) => { return ( { key={index} dir={dir} > - + ); })} diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 9a74e28f390..cf4507ae549 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -64,7 +64,7 @@ function ArticleLinksBlock({ }; const viewTracker = useViewTracker(eventTrackingData); - const clickTrackerHandler = useClickTrackerHandler(eventTrackingData); + const clickTracker = useClickTrackerHandler(eventTrackingData); if (!blocks || isEmpty(blocks)) { return null; @@ -107,12 +107,14 @@ function ArticleLinksBlock({ )} {isSingleItem ? ( - + ) : ( )} From b0478fbfc9156acc7f8895ef9b2dbea5de1ee3b0 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 16:02:19 +0000 Subject: [PATCH 035/100] update PromoList --- .../PromoList/{index.jsx => index.tsx} | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) rename src/app/components/ArticleLinksBlock/PromoList/{index.jsx => index.tsx} (87%) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.jsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx similarity index 87% rename from src/app/components/ArticleLinksBlock/PromoList/index.jsx rename to src/app/components/ArticleLinksBlock/PromoList/index.tsx index 57747b83661..f0b838bffb3 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.jsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -10,6 +10,8 @@ import { GEL_GROUP_4_SCREEN_WIDTH_MIN, } from '#psammead/gel-foundations/src/breakpoints'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; +import { EventTrackingMetadata } from '#app/models/types/eventTracking'; +import { OptimoBlock } from '#app/models/types/optimo'; import { ServiceContext } from '../../../contexts/ServiceContext'; import Promo from '../Promo'; @@ -79,7 +81,16 @@ const OperaStyledList = styled.li` margin-${dir === 'ltr' ? `left` : `right`}: 0;}`} `; -const PromoList = ({ blocks, viewTracker, clickTracker, a11yAttributes }) => { +interface PromoListProps { + blocks: OptimoBlock[]; + eventTrackingData?: EventTrackingMetadata; +} + +const PromoList = ({ + blocks, + eventTrackingData, + // viewTracker, +}: PromoListProps) => { const { dir } = use(ServiceContext); const isOperaMini = useOperaMiniDetection(); const listBlocks = blocks.slice(0, 3); @@ -92,8 +103,8 @@ const PromoList = ({ blocks, viewTracker, clickTracker, a11yAttributes }) => { dir={dir} role="list" isOperaMini={isOperaMini} - {...viewTracker} - {...a11yAttributes} + // {...viewTracker} + // {...a11yAttributes} > {listBlocks.map((block, index) => { return ( @@ -102,7 +113,7 @@ const PromoList = ({ blocks, viewTracker, clickTracker, a11yAttributes }) => { key={index} dir={dir} > - + ); })} From a551af9c74e91ae31d0fae2b3c7af83f55021177 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 16:11:05 +0000 Subject: [PATCH 036/100] update Promo test file --- .../Promo/{index.test.jsx => index.test.tsx} | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename src/app/components/ArticleLinksBlock/Promo/{index.test.jsx => index.test.tsx} (90%) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.test.jsx b/src/app/components/ArticleLinksBlock/Promo/index.test.tsx similarity index 90% rename from src/app/components/ArticleLinksBlock/Promo/index.test.jsx rename to src/app/components/ArticleLinksBlock/Promo/index.test.tsx index 1f524583abf..c182248fd4f 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.test.jsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.test.tsx @@ -5,7 +5,7 @@ import { ServiceContextProvider } from '../../../contexts/ServiceContext'; const ArticleLinksBlock = ({ block }) => ( - {}} /> + ); @@ -32,7 +32,8 @@ describe('Article Links Block', () => { const { queryByRole } = render( , ); - expect(queryByRole('link').href).toEqual('https://www.bbc.com/mundo'); + const link = queryByRole('link') as HTMLAnchorElement; + expect(link?.href).toEqual('https://www.bbc.com/mundo'); }); it('should render timestamp if timestamp is available', () => { From 1b55e5325131d2eba8d4136dcb997d0402fb8cd2 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 17:20:22 +0000 Subject: [PATCH 037/100] test file update --- .../ArticleLinksBlock/{index.test.jsx => index.test.tsx} | 0 src/app/components/ArticleLinksBlock/index.tsx | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/app/components/ArticleLinksBlock/{index.test.jsx => index.test.tsx} (100%) diff --git a/src/app/components/ArticleLinksBlock/index.test.jsx b/src/app/components/ArticleLinksBlock/index.test.tsx similarity index 100% rename from src/app/components/ArticleLinksBlock/index.test.jsx rename to src/app/components/ArticleLinksBlock/index.test.tsx diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index cf4507ae549..33ea74d15b3 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -107,12 +107,12 @@ function ArticleLinksBlock({ )} {isSingleItem ? ( - + ) : ( From 4059a6d6f71675a58d4c2ecde5a0998a4cde0059 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 23 Dec 2025 17:24:47 +0000 Subject: [PATCH 038/100] convert styles to emotion and delete styled components --- .../ArticleLinksBlock/index.styles.tsx | 64 +++++++++++++++++++ .../components/ArticleLinksBlock/index.tsx | 47 ++------------ 2 files changed, 70 insertions(+), 41 deletions(-) create mode 100644 src/app/components/ArticleLinksBlock/index.styles.tsx diff --git a/src/app/components/ArticleLinksBlock/index.styles.tsx b/src/app/components/ArticleLinksBlock/index.styles.tsx new file mode 100644 index 00000000000..9cd06e02cd8 --- /dev/null +++ b/src/app/components/ArticleLinksBlock/index.styles.tsx @@ -0,0 +1,64 @@ +import pixelsToRem from '#app/utilities/pixelsToRem'; +import { css, Theme } from '@emotion/react'; + +export default { + promoContainer: ({ palette, mq, spacings }: Theme) => + css({ + background: palette.GREY_2, + padding: `0 ${spacings.FULL}rem ${spacings.DOUBLE}rem`, + margin: 0, + display: 'flex', + overflowX: 'auto', + width: '100vw', + '-ms-overflow-style': 'none', + scrollbarWidth: 'none', + '&::-webkit-scrollbar': { + display: 'none', + }, + [mq.GROUP_2_MIN_WIDTH]: { + padding: `0 ${spacings.DOUBLE}rem ${spacings.DOUBLE}rem`, + margin: '0 -0.2rem', + }, + [mq.GROUP_3_MIN_WIDTH]: { + padding: `0 ${spacings.DOUBLE}rem ${spacings.DOUBLE}rem`, + }, + + [mq.FORCED_COLOURS]: { + border: `solid ${pixelsToRem(3)}rem transparent`, + borderTop: 'transparent', + }, + }), + labelComponent: ({ + isDarkUi, + fontSizes, + fontVariants, + mq, + palette, + spacings, + }: Theme) => + css({ + ...fontSizes.brevier, + ...fontVariants.sansRegular, + display: 'flex', + alignItems: 'center', + backgroundColor: palette.GREY_2, + width: '100vw', + height: `${spacings.QUADRUPLE}rem`, + color: isDarkUi ? palette.GREY_2 : palette.SHADOW, + padding: `0 ${spacings.FULL}rem`, + [mq.FORCED_COLOURS]: { + border: `solid ${pixelsToRem(3)}rem transparent`, + borderBottom: 'transparent', + }, + + [mq.GROUP_0_MAX_WIDTH]: { + marginInlineStart: `${spacings.FULL}rem`, + margin: 0, + }, + [mq.GROUP_2_MIN_WIDTH]: { + marginInlineStart: `${spacings.DOUBLE}rem`, + padding: `0 ${spacings.DOUBLE}rem`, + margin: '0 -0.2rem', + }, + }), +}; diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 33ea74d15b3..b784f33e271 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -1,16 +1,6 @@ import { use } from 'react'; -import styled from '@emotion/styled'; import isEmpty from 'ramda/src/isEmpty'; import tail from 'ramda/src/tail'; -import { - GEL_SPACING, - GEL_SPACING_DBL, -} from '#psammead/gel-foundations/src/spacings'; -import { - GEL_GROUP_0_SCREEN_WIDTH_MIN, - GEL_GROUP_2_SCREEN_WIDTH_MIN, - GEL_GROUP_4_SCREEN_WIDTH_MIN, -} from '#psammead/gel-foundations/src/breakpoints'; import { GridItemMediumNoMargin } from '#components/Grid'; import useViewTracker from '#hooks/useViewTracker'; import useClickTrackerHandler from '#hooks/useClickTrackerHandler'; @@ -19,39 +9,13 @@ import { OptimoBlock } from '#app/models/types/optimo'; import { ServiceContext } from '../../contexts/ServiceContext'; import Promo from './Promo'; import PromoList from './PromoList'; +import styles from './index.styles'; interface ArticleLinksBlockProps { blocks: OptimoBlock[]; blockGroupIndex?: number | null; } -const PromoWrapper = styled.div<{ dir: string }>(({ dir }) => ({ - [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: GEL_SPACING, - [`@media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN})`]: { - [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: GEL_SPACING_DBL, - }, - [`@media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN})`]: { - [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: 0, - }, -})); - -const LabelComponent = styled.strong<{ dir: string }>(({ theme, dir }) => ({ - display: 'block', - ...theme.fontSizes.doublePica, - ...theme.fontVariants.sansRegular, - marginBottom: GEL_SPACING_DBL, - color: theme.isDarkUi ? theme.palette.GREY_2 : theme.palette.SHADOW, - [`@media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN})`]: { - [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: GEL_SPACING, - }, - [`@media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN})`]: { - [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: GEL_SPACING_DBL, - }, - [`@media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN})`]: { - [`margin${dir === 'ltr' ? 'Left' : 'Right'}`]: 0, - }, -})); - function ArticleLinksBlock({ blocks, blockGroupIndex = null, @@ -97,18 +61,19 @@ function ArticleLinksBlock({ return ( {typeof title === 'string' && title.length > 0 && ( - {title} - + )} {isSingleItem ? ( - +
- +
) : ( Date: Wed, 24 Dec 2025 11:10:39 +0000 Subject: [PATCH 039/100] update styles for Promo --- .../ArticleLinksBlock/Promo/index.styles.tsx | 57 +++++++++++++ .../ArticleLinksBlock/Promo/index.tsx | 83 +++---------------- 2 files changed, 68 insertions(+), 72 deletions(-) create mode 100644 src/app/components/ArticleLinksBlock/Promo/index.styles.tsx diff --git a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx new file mode 100644 index 00000000000..9b0706d6dcc --- /dev/null +++ b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx @@ -0,0 +1,57 @@ +import { css, Theme } from '@emotion/react'; + +export default { + link: ({ fontSizes, fontVariants, isDarkUi, palette }: Theme) => + css({ + ...fontSizes.pica, + ...fontVariants.serifBold, + display: 'webkit-box', + width: '100%', + textDecoration: 'none', + overflowX: 'hidden', + overflowY: 'hidden', + WebkitLineClamp: 4, + WebkitBoxOrient: 'vertical', + '&:hover, &:focus': { + textDecoration: 'underline', + }, + color: isDarkUi ? palette.GREY_10 : palette.GREY_8, + '&:visited': { + color: palette.GREY_6, + }, + }), + promoBox: ({ isDarkUi, mq, palette, spacings }: Theme) => + css({ + position: 'relative', + backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, + padding: `${spacings.DOUBLE}rem`, + marginBottom: `${spacings.TRIPLE}rem`, + height: 'auto', + display: 'block', + [mq.GROUP_0_MAX_WIDTH]: { + width: `14.8125rem`, + }, + [mq.GROUP_3_MIN_WIDTH]: { + width: `11.125rem`, + }, + [mq.GROUP_4_MIN_WIDTH]: { + width: `12.6875rem`, + }, + }), + operaPromoBox: ({ isDarkUi, mq, palette, spacings }: Theme) => + css({ + position: 'relative', + backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, + padding: `${spacings.DOUBLE}rem`, + marginBottom: `${spacings.DOUBLE}rem`, + width: `calc(100% - ${spacings.FULL}rem)`, + [mq.GROUP_2_MIN_WIDTH]: { + width: `calc(50% - ${spacings.DOUBLE}rem)`, + }, + }), + timestamp: ({ isDarkUi, palette, spacings }: Theme) => + css({ + marginTop: `${spacings.FULL}rem`, + color: isDarkUi ? palette.GREY_6 : undefined, + }), +}; diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index 1163d02f120..f6a172d6c9e 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -1,17 +1,4 @@ import { use } from 'react'; -import styled from '@emotion/styled'; -import { Link } from '#psammead/psammead-story-promo/src'; -import { - GEL_SPACING, - GEL_SPACING_DBL, - GEL_SPACING_TRPL, -} from '#psammead/gel-foundations/src/spacings'; -import { - GEL_GROUP_0_SCREEN_WIDTH_MIN, - GEL_GROUP_2_SCREEN_WIDTH_MIN, - GEL_GROUP_3_SCREEN_WIDTH_MIN, - GEL_GROUP_4_SCREEN_WIDTH_MIN, -} from '#psammead/gel-foundations/src/breakpoints'; import filterForBlockType from '#lib/utilities/blockHandlers'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import PromoTimestamp from '#components/Promo/timestamp'; @@ -19,64 +6,13 @@ import { OptimoBlock } from '#app/models/types/optimo'; import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; import { ServiceContext } from '../../../contexts/ServiceContext'; +import styles from './index.styles'; interface PromoProps { block: OptimoBlock; eventTrackingData?: EventTrackingMetadata; } -const StyledLink = styled(Link)(({ theme }) => ({ - ...theme.fontSizes.pica, - ...theme.fontVariants.serifBold, - width: '100%', - textDecoration: 'none', - overflowX: 'hidden', - overflowY: 'hidden', - WebkitLineClamp: 4, - WebkitBoxOrient: 'vertical', - display: '-webkit-box', - color: theme.isDarkUi ? theme.palette.GREY_10 : theme.palette.GREY_8, - '&:hover, &:focus': { - textDecoration: 'underline', - }, - '&:visited': { - color: theme.palette.GREY_6, - }, -})); - -const PromoBox = styled.div(({ theme }) => ({ - position: 'relative', - backgroundColor: theme.isDarkUi ? theme.palette.GREY_3 : theme.palette.WHITE, - padding: GEL_SPACING_DBL, - marginBottom: GEL_SPACING_TRPL, - height: 'auto', - [`@media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN})`]: { - width: '14.8125rem', - }, - [`@media (min-width: ${GEL_GROUP_3_SCREEN_WIDTH_MIN})`]: { - width: '11.125rem', - }, - [`@media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN})`]: { - width: '12.6875rem', - }, -})); - -const OperaPromoBox = styled.div(({ theme }) => ({ - position: 'relative', - backgroundColor: theme.isDarkUi ? theme.palette.GREY_3 : theme.palette.WHITE, - padding: GEL_SPACING_DBL, - marginBottom: GEL_SPACING_DBL, - width: `calc(100% - ${GEL_SPACING})`, - [`@media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN})`]: { - width: `calc(100% - ${GEL_SPACING_DBL})`, - }, -})); - -const TimeStamp = styled(PromoTimestamp)(({ theme }) => ({ - marginTop: GEL_SPACING, - color: theme.isDarkUi ? theme.palette.GREY_6 : undefined, -})); - function Promo({ block, eventTrackingData }: PromoProps) { const { serviceDatetimeLocale } = use(ServiceContext); const clickTrackerHandler = useClickTrackerHandler(eventTrackingData); @@ -99,19 +35,22 @@ function Promo({ block, eventTrackingData }: PromoProps) { const isOperaMini = useOperaMiniDetection(); - const WrapperPromoBox = isOperaMini ? OperaPromoBox : PromoBox; + const promoBoxStyles = isOperaMini ? styles.operaPromoBox : styles.promoBox; return ( - - +
+ {title} - + {timestamp && ( - + {timestamp} - + )} - +
); } From 37016de9e25ffbb1f5c60799c263d06bcfb6ee5d Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 24 Dec 2025 11:39:08 +0000 Subject: [PATCH 040/100] update references in e2e tests --- .../atiAnalytics/assertions/scrollablePromo.js | 12 ++++++------ .../atiAnalytics/assertions/scrollablePromo.ts | 14 +++++++------- .../specialFeatures/atiAnalytics/helpers/index.ts | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.js b/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.js index bb09787a460..a5caa7914e5 100644 --- a/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.js +++ b/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.js @@ -1,7 +1,7 @@ import { interceptATIAnalyticsBeacons, COMPONENTS } from '../helpers'; import { assertATIComponentClickEvent, assertATIComponentViewEvent } from '.'; -const { SCROLLABLE_PROMO } = COMPONENTS; +const { ARTICLE_LINKS_BLOCK } = COMPONENTS; export const assertScrollablePromoComponentView = ({ pageIdentifier, @@ -15,12 +15,12 @@ export const assertScrollablePromoComponentView = ({ interceptATIAnalyticsBeacons(); cy.visit(path); - cy.get('[data-e2e="scrollable-promos"]').first().scrollIntoView({ + cy.get('[data-e2e="article-links-block"]').first().scrollIntoView({ duration: 1000, }); assertATIComponentViewEvent({ - component: SCROLLABLE_PROMO, + component: ARTICLE_LINKS_BLOCK, pageIdentifier, contentType, useReverb, @@ -42,15 +42,15 @@ export const assertScrollablePromoComponentClick = ({ interceptATIAnalyticsBeacons(); cy.visit(path); - cy.get('[data-e2e="scrollable-promos"]').first().scrollIntoView({ + cy.get('[data-e2e="article-links-block"]').first().scrollIntoView({ duration: 1000, }); // Click on first item - cy.get('[data-e2e="scrollable-promos"]').find('a').first().click(); + cy.get('[data-e2e="article-links-block"]').find('a').first().click(); assertATIComponentClickEvent({ - component: SCROLLABLE_PROMO, + component: ARTICLE_LINKS_BLOCK, pageIdentifier, contentType, useReverb, diff --git a/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.ts b/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.ts index f8e6a8f259c..94eff227609 100644 --- a/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.ts +++ b/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.ts @@ -6,7 +6,7 @@ import { } from '../../../../../../cypress/e2e/specialFeatures/atiAnalytics/assertions'; import { AtiAssertionFnProps } from './type'; -const { SCROLLABLE_PROMO } = COMPONENTS; +const { ARTICLE_LINKS_BLOCK } = COMPONENTS; export const assertScrollablePromoComponentView = ({ pageIdentifier, @@ -21,15 +21,15 @@ export const assertScrollablePromoComponentView = ({ cy.visit(path); // This duplicate line of code has been added intentionally to get cypress to scroll to the bottom. - cy.get('[data-e2e="scrollable-promos"]').first().scrollIntoView({ + cy.get('[data-e2e="article-links-block"]').first().scrollIntoView({ duration: 1000, }); - cy.get('[data-e2e="scrollable-promos"]').first().scrollIntoView({ + cy.get('[data-e2e="article-links-block"]').first().scrollIntoView({ duration: 1000, }); assertATIComponentViewEvent({ - component: SCROLLABLE_PROMO, + component: ARTICLE_LINKS_BLOCK, pageIdentifier, contentType, useReverb, @@ -51,15 +51,15 @@ export const assertScrollablePromoComponentClick = ({ interceptATIAnalyticsBeacons(); cy.visit(path); - cy.get('[data-e2e="scrollable-promos"]').first().scrollIntoView({ + cy.get('[data-e2e="article-links-block"]').first().scrollIntoView({ duration: 1000, }); // Click on first item - cy.get('[data-e2e="scrollable-promos"]').find('a').first().click(); + cy.get('[data-e2e="article-links-block"]').find('a').first().click(); assertATIComponentClickEvent({ - component: SCROLLABLE_PROMO, + component: ARTICLE_LINKS_BLOCK, pageIdentifier, contentType, useReverb, diff --git a/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/helpers/index.ts b/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/helpers/index.ts index c4c1ca0ebe3..504e4d56e5b 100644 --- a/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/helpers/index.ts +++ b/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/helpers/index.ts @@ -29,7 +29,7 @@ const RECENT_AUDIO_EPISODES = 'episodes-audio'; const PODCAST_LINKS = 'third-party'; const LATEST_MEDIA = 'latest'; const RECOMMENDATIONS = 'midarticle-mostread'; -const SCROLLABLE_PROMO = 'edoj'; +const ARTICLE_LINKS_BLOCK = 'edoj'; const BILLBOARD = 'billboard'; const SOCIAL_EMBED = 'social-consent-banner'; const LIVE_MEDIA = 'live-header-media'; @@ -57,7 +57,7 @@ export const COMPONENTS = { RELATED_CONTENT, RELATED_TOPICS, SCROLLABLE_NAVIGATION, - SCROLLABLE_PROMO, + ARTICLE_LINKS_BLOCK, SHARE, SOCIAL_EMBED, TOP_STORIES, From 3c66a10fb7e79056e726f5454c334bfd4bae6b58 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 24 Dec 2025 11:44:34 +0000 Subject: [PATCH 041/100] update references in e2e tests --- cypress/e2e/specialFeatures/atiAnalytics/helpers/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/e2e/specialFeatures/atiAnalytics/helpers/index.js b/cypress/e2e/specialFeatures/atiAnalytics/helpers/index.js index 63067605dc1..aee132a87d3 100644 --- a/cypress/e2e/specialFeatures/atiAnalytics/helpers/index.js +++ b/cypress/e2e/specialFeatures/atiAnalytics/helpers/index.js @@ -28,7 +28,7 @@ const RECENT_AUDIO_EPISODES = 'episodes-audio'; const PODCAST_LINKS = 'third-party'; const LATEST_MEDIA = 'latest'; const RECOMMENDATIONS = 'midarticle-mostread'; -const SCROLLABLE_PROMO = 'edoj'; +const ARTICLE_LINKS_BLOCK = 'edoj'; const BILLBOARD = 'billboard'; const SOCIAL_EMBED = 'social-consent-banner'; const LIVE_MEDIA = 'live-header-media'; @@ -54,7 +54,7 @@ export const COMPONENTS = { RELATED_CONTENT, RELATED_TOPICS, SCROLLABLE_NAVIGATION, - SCROLLABLE_PROMO, + ARTICLE_LINKS_BLOCK, SHARE, SOCIAL_EMBED, TOP_STORIES, From 77bcd2eea4bbd69258994e630819b93f16547668 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 30 Dec 2025 12:59:37 +0000 Subject: [PATCH 042/100] convert styles and fix margin issue on promoList --- .../PromoList/index.styles.tsx | 84 ++++++++++++++ .../ArticleLinksBlock/PromoList/index.tsx | 108 +++--------------- .../components/ArticleLinksBlock/index.tsx | 2 +- 3 files changed, 104 insertions(+), 90 deletions(-) create mode 100644 src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx new file mode 100644 index 00000000000..e84e9380167 --- /dev/null +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -0,0 +1,84 @@ +import pixelsToRem from '#app/utilities/pixelsToRem'; +import { css, Theme } from '@emotion/react'; + +export default { + standardScrollPromo: ({ mq, spacings }: Theme) => + css({ + listStyle: 'none', + paddingInlineStart: '0', + margin: '0', + display: 'flex', + overflowX: 'scroll', + scrollBehavior: 'auto', + WebkitOverflowScrolling: 'touch', + // Hide scrollbar + scrollbarWidth: 'none', + msOverflowStyle: 'none', + '&::-webkit-scrollbar': { + display: 'none', + }, + '& > li + li': { + marginInlineStart: `${spacings.FULL}rem`, + }, + [mq.GROUP_2_MIN_WIDTH]: { + '& > li:not(:first-of-type)': { + marginInlineStart: `${spacings.DOUBLE}rem`, + }, + }, + }), + operaScrollPromo: () => + css({ + listStyle: 'none', + paddingInlineStart: '0', + margin: '0', + }), + list: ({ mq, spacings }: Theme) => + css({ + display: 'flex', + flexShrink: 0, + [mq.FORCED_COLOURS]: { + border: `solid ${pixelsToRem(3)}rem transparent`, + }, + + [mq.GROUP_0_MAX_WIDTH]: { + '&:first-of-type': { + marginInlineStart: `${spacings.FULL}rem`, + }, + '&:last-of-type': { + marginInlineEnd: `${spacings.FULL}rem`, + }, + }, + + [mq.GROUP_2_MIN_WIDTH]: { + '&:first-of-type': { + marginInlineStart: `${spacings.DOUBLE}rem`, + }, + }, + + [mq.GROUP_3_MIN_WIDTH]: { + '&:first-of-type': { + marginInlineStart: `${spacings.DOUBLE}rem`, + }, + }, + + [mq.GROUP_4_MIN_WIDTH]: { + '&:first-of-type': { + marginInlineStart: 0, + }, + }, + }), + operaStyledList: ({ mq, spacings }: Theme) => + css({ + [mq.GROUP_0_MAX_WIDTH]: { + marginInlineStart: `${spacings.FULL}rem`, + }, + + [mq.GROUP_2_MIN_WIDTH]: { + marginInlineStart: `${spacings.DOUBLE}rem`, + }, + + [mq.GROUP_4_MIN_WIDTH]: { + marginInlineStart: 0, + }, + }), +}; diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index f0b838bffb3..94f2474fd39 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -1,85 +1,10 @@ import { use } from 'react'; -import styled from '@emotion/styled'; -import { - GEL_SPACING, - GEL_SPACING_DBL, -} from '#psammead/gel-foundations/src/spacings'; -import { - GEL_GROUP_0_SCREEN_WIDTH_MIN, - GEL_GROUP_2_SCREEN_WIDTH_MIN, - GEL_GROUP_4_SCREEN_WIDTH_MIN, -} from '#psammead/gel-foundations/src/breakpoints'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import { OptimoBlock } from '#app/models/types/optimo'; import { ServiceContext } from '../../../contexts/ServiceContext'; import Promo from '../Promo'; - -const StandardScrollPromo = styled.ul` - list-style: none; - ${({ dir }) => `padding-${dir === 'ltr' ? 'left' : 'right'}: 0;`} - margin: 0; - display: flex; - overflow-x: scroll; - /* Avoid using smooth scrolling as it causes accessibility issues */ - scroll-behavior: auto; - -webkit-overflow-scrolling: touch; - - /* Hide scrollbar */ - scrollbar-width: none; - -ms-overflow-style: none; - &::-webkit-scrollbar { - display: none; - } -`; - -const OperaScrollPromo = styled.ul` - list-style: none; - ${({ dir }) => `padding-${dir === 'ltr' ? 'left' : 'right'}: 0;`} - margin: 0; -`; - -const StyledList = styled.li` - display: flex; - flex-shrink: 0; - - ${({ dir }) => - ` - @media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING}; - &:first-child { - margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING}; - } - &:last-child { - margin-${dir === 'ltr' ? 'right' : 'left'}: ${GEL_SPACING}; - } - } - @media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? `left` : `right`}: ${GEL_SPACING_DBL}; - - &:first-child { - margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING_DBL}; - } - } - @media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? `left` : `right`}: ${GEL_SPACING_DBL}; - &:first-child { - margin-${dir === 'ltr' ? 'left' : 'right'}: 0; - } - } - `} -`; - -const OperaStyledList = styled.li` - ${({ dir }) => `@media (min-width: ${GEL_GROUP_0_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? 'left' : 'right'}: ${GEL_SPACING}; - } - @media (min-width: ${GEL_GROUP_2_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? `left` : `right`}: ${GEL_SPACING_DBL}; - } - @media (min-width: ${GEL_GROUP_4_SCREEN_WIDTH_MIN}){ - margin-${dir === 'ltr' ? `left` : `right`}: 0;}`} -`; +import styles from './index.styles'; interface PromoListProps { blocks: OptimoBlock[]; @@ -95,29 +20,34 @@ const PromoList = ({ const isOperaMini = useOperaMiniDetection(); const listBlocks = blocks.slice(0, 3); - const ScrollPromo = isOperaMini ? OperaScrollPromo : StandardScrollPromo; - const List = isOperaMini ? OperaStyledList : StyledList; + const scrollablePromoStyles = isOperaMini + ? styles.operaScrollPromo + : styles.standardScrollPromo; + + const listStyles = isOperaMini ? styles.operaStyledList : styles.list; return ( - + // +
    {listBlocks.map((block, index) => { return ( - - + ); })} - +
+ //
); }; diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index b784f33e271..5e584d63452 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -59,7 +59,7 @@ function ArticleLinksBlock({ }; return ( - + {typeof title === 'string' && title.length > 0 && ( Date: Tue, 30 Dec 2025 13:54:56 +0000 Subject: [PATCH 043/100] stack items --- src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index e84e9380167..71be5e4d81b 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -8,6 +8,7 @@ export default { paddingInlineStart: '0', margin: '0', display: 'flex', + flexDirection: 'column', overflowX: 'scroll', scrollBehavior: 'auto', WebkitOverflowScrolling: 'touch', From db9137582dfebd63c48be356da0cc142d37d2577 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 30 Dec 2025 14:20:38 +0000 Subject: [PATCH 044/100] remove first list item margins as no longer required --- .../ArticleLinksBlock/PromoList/index.styles.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index 71be5e4d81b..703abd1bbd9 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -2,7 +2,7 @@ import pixelsToRem from '#app/utilities/pixelsToRem'; import { css, Theme } from '@emotion/react'; export default { - standardScrollPromo: ({ mq, spacings }: Theme) => + standardScrollPromo: () => css({ listStyle: 'none', paddingInlineStart: '0', @@ -18,14 +18,6 @@ export default { '&::-webkit-scrollbar': { display: 'none', }, - '& > li + li': { - marginInlineStart: `${spacings.FULL}rem`, - }, - [mq.GROUP_2_MIN_WIDTH]: { - '& > li:not(:first-of-type)': { - marginInlineStart: `${spacings.DOUBLE}rem`, - }, - }, }), operaScrollPromo: () => css({ From 8b7a53d50b696a3896245ffdb1fdec051ee96c1f Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 30 Dec 2025 14:40:51 +0000 Subject: [PATCH 045/100] change width and adjust margins between items --- .../ArticleLinksBlock/Promo/index.styles.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx index 9b0706d6dcc..7b113c8f7a7 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx @@ -1,3 +1,4 @@ +import pixelsToRem from '#app/utilities/pixelsToRem'; import { css, Theme } from '@emotion/react'; export default { @@ -25,18 +26,19 @@ export default { position: 'relative', backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, padding: `${spacings.DOUBLE}rem`, - marginBottom: `${spacings.TRIPLE}rem`, + marginBottom: `${spacings.FULL}rem`, height: 'auto', display: 'block', - [mq.GROUP_0_MAX_WIDTH]: { - width: `14.8125rem`, - }, - [mq.GROUP_3_MIN_WIDTH]: { - width: `11.125rem`, - }, - [mq.GROUP_4_MIN_WIDTH]: { - width: `12.6875rem`, - }, + width: '100%', + // [mq.GROUP_0_MAX_WIDTH]: { + // width: `14.8125rem`, + // }, + // [mq.GROUP_3_MIN_WIDTH]: { + // width: `11.125rem`, + // }, + // [mq.GROUP_4_MIN_WIDTH]: { + // width: '100%', + // }, }), operaPromoBox: ({ isDarkUi, mq, palette, spacings }: Theme) => css({ From 1cc5d47b5ff738287c42c10c95efb470e731b7ff Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 30 Dec 2025 15:57:51 +0000 Subject: [PATCH 046/100] implement chevron --- .../components/ArticleLinksBlock/Promo/index.styles.tsx | 8 ++++++++ src/app/components/ArticleLinksBlock/Promo/index.tsx | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx index 7b113c8f7a7..ad2210b8f2d 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx @@ -26,6 +26,7 @@ export default { position: 'relative', backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, padding: `${spacings.DOUBLE}rem`, + paddingInlineEnd: `${pixelsToRem(38)}rem`, marginBottom: `${spacings.FULL}rem`, height: 'auto', display: 'block', @@ -56,4 +57,11 @@ export default { marginTop: `${spacings.FULL}rem`, color: isDarkUi ? palette.GREY_6 : undefined, }), + chevron: () => + css({ + position: 'absolute', + top: '50%', + transform: 'translateY(-50%)', + insetInlineEnd: `${pixelsToRem(12)}rem`, + }), }; diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index f6a172d6c9e..7230381d3a7 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -5,6 +5,7 @@ import PromoTimestamp from '#components/Promo/timestamp'; import { OptimoBlock } from '#app/models/types/optimo'; import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; +import { Chevron, ChevronOrientation } from '#app/components/icons'; import { ServiceContext } from '../../../contexts/ServiceContext'; import styles from './index.styles'; @@ -14,7 +15,7 @@ interface PromoProps { } function Promo({ block, eventTrackingData }: PromoProps) { - const { serviceDatetimeLocale } = use(ServiceContext); + const { serviceDatetimeLocale, dir } = use(ServiceContext); const clickTrackerHandler = useClickTrackerHandler(eventTrackingData); const textBlock = filterForBlockType( @@ -41,6 +42,11 @@ function Promo({ block, eventTrackingData }: PromoProps) {
{title} + {timestamp && ( Date: Tue, 30 Dec 2025 16:47:43 +0000 Subject: [PATCH 047/100] update margin properties at all breakpoints --- .../PromoList/index.styles.tsx | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index 703abd1bbd9..99c3314f9d3 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -29,49 +29,35 @@ export default { css({ display: 'flex', flexShrink: 0, + marginInline: `${spacings.FULL}rem`, [mq.FORCED_COLOURS]: { border: `solid ${pixelsToRem(3)}rem transparent`, }, - [mq.GROUP_0_MAX_WIDTH]: { - '&:first-of-type': { - marginInlineStart: `${spacings.FULL}rem`, - }, - '&:last-of-type': { - marginInlineEnd: `${spacings.FULL}rem`, - }, - }, - [mq.GROUP_2_MIN_WIDTH]: { - '&:first-of-type': { - marginInlineStart: `${spacings.DOUBLE}rem`, - }, + marginInline: `${spacings.DOUBLE}rem`, }, [mq.GROUP_3_MIN_WIDTH]: { - '&:first-of-type': { - marginInlineStart: `${spacings.DOUBLE}rem`, - }, + marginInline: `${spacings.DOUBLE}rem`, }, [mq.GROUP_4_MIN_WIDTH]: { - '&:first-of-type': { - marginInlineStart: 0, - }, + marginInline: 0, }, }), operaStyledList: ({ mq, spacings }: Theme) => css({ [mq.GROUP_0_MAX_WIDTH]: { - marginInlineStart: `${spacings.FULL}rem`, + marginInline: `${spacings.FULL}rem`, }, [mq.GROUP_2_MIN_WIDTH]: { - marginInlineStart: `${spacings.DOUBLE}rem`, + marginInline: `${spacings.DOUBLE}rem`, }, [mq.GROUP_4_MIN_WIDTH]: { - marginInlineStart: 0, + marginInline: 0, }, }), }; From 88254a53d4fa8301c0fc69d1642b9e8cc956e863 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 30 Dec 2025 17:33:31 +0000 Subject: [PATCH 048/100] remove scrollable css and update variable names --- .../ArticleLinksBlock/Promo/index.styles.tsx | 13 ++----------- .../PromoList/index.styles.tsx | 17 ++++++----------- .../ArticleLinksBlock/PromoList/index.tsx | 6 ++---- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx index ad2210b8f2d..40acd651b55 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx @@ -21,25 +21,16 @@ export default { color: palette.GREY_6, }, }), - promoBox: ({ isDarkUi, mq, palette, spacings }: Theme) => + promoBox: ({ isDarkUi, palette, spacings }: Theme) => css({ position: 'relative', backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, padding: `${spacings.DOUBLE}rem`, paddingInlineEnd: `${pixelsToRem(38)}rem`, - marginBottom: `${spacings.FULL}rem`, + gap: `${spacings.FULL}rem`, height: 'auto', display: 'block', width: '100%', - // [mq.GROUP_0_MAX_WIDTH]: { - // width: `14.8125rem`, - // }, - // [mq.GROUP_3_MIN_WIDTH]: { - // width: `11.125rem`, - // }, - // [mq.GROUP_4_MIN_WIDTH]: { - // width: '100%', - // }, }), operaPromoBox: ({ isDarkUi, mq, palette, spacings }: Theme) => css({ diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index 99c3314f9d3..b49fc6bae69 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -2,24 +2,16 @@ import pixelsToRem from '#app/utilities/pixelsToRem'; import { css, Theme } from '@emotion/react'; export default { - standardScrollPromo: () => + standardPromo: ({ spacings }: Theme) => css({ listStyle: 'none', paddingInlineStart: '0', margin: '0', display: 'flex', flexDirection: 'column', - overflowX: 'scroll', - scrollBehavior: 'auto', - WebkitOverflowScrolling: 'touch', - // Hide scrollbar - scrollbarWidth: 'none', - msOverflowStyle: 'none', - '&::-webkit-scrollbar': { - display: 'none', - }, + gap: `${spacings.FULL}rem`, }), - operaScrollPromo: () => + operaPromo: () => css({ listStyle: 'none', paddingInlineStart: '0', @@ -30,6 +22,9 @@ export default { display: 'flex', flexShrink: 0, marginInline: `${spacings.FULL}rem`, + ':last-of-type': { + marginBottom: `${spacings.TRIPLE}rem`, + }, [mq.FORCED_COLOURS]: { border: `solid ${pixelsToRem(3)}rem transparent`, }, diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index 94f2474fd39..176bd5e31af 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -20,9 +20,7 @@ const PromoList = ({ const isOperaMini = useOperaMiniDetection(); const listBlocks = blocks.slice(0, 3); - const scrollablePromoStyles = isOperaMini - ? styles.operaScrollPromo - : styles.standardScrollPromo; + const promoStyles = isOperaMini ? styles.operaPromo : styles.standardPromo; const listStyles = isOperaMini ? styles.operaStyledList : styles.list; @@ -34,7 +32,7 @@ const PromoList = ({ // // {...viewTracker} // // {...a11yAttributes} // > -
    +
      {listBlocks.map((block, index) => { return (
    • Date: Tue, 30 Dec 2025 17:46:37 +0000 Subject: [PATCH 049/100] remove ScrollPromo and replace with div --- .../ArticleLinksBlock/PromoList/index.tsx | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index 94f2474fd39..fb80101300c 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -27,27 +27,27 @@ const PromoList = ({ const listStyles = isOperaMini ? styles.operaStyledList : styles.list; return ( - // -
        - {listBlocks.map((block, index) => { - return ( -
      • - -
      • - ); - })} -
      - //
      +
      +
        + {listBlocks.map((block, index) => { + return ( +
      • + +
      • + ); + })} +
      +
      ); }; From d10cd150aee04a7484a81a76975dd91407604165 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 31 Dec 2025 08:45:04 +0000 Subject: [PATCH 050/100] fix stories file --- .../ArticleLinksBlock/index.stories.tsx | 97 +++++++++++-------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.stories.tsx b/src/app/components/ArticleLinksBlock/index.stories.tsx index b1c6b53b0ec..b44a69f8b23 100644 --- a/src/app/components/ArticleLinksBlock/index.stories.tsx +++ b/src/app/components/ArticleLinksBlock/index.stories.tsx @@ -14,20 +14,24 @@ import { import metadata from './metadata.json'; import readme from './README.md'; import { OptimoBlock } from '#app/models/types/optimo'; -import { StoryArgs } from '../../models/types/storybook'; - -const BackGround = styled.div` - background-color: #f6f6f6; - padding: 2rem; -`; +import { StoryArgs, StoryProps } from '../../models/types/storybook'; interface Props { blocks: OptimoBlock[]; } -const Component = ({ blocks }: Props) => { - return ; -}; +const Component = ({ blocks, service }: Props & StoryProps) => ( + +
      + +
      +
      +); export default { title: 'Components/Article Links Block', @@ -38,54 +42,65 @@ export default { }, }; -export const ThreeLinks = (_: StoryArgs) => ( - - - +export const ThreeLinks = (_: StoryArgs, { service, variant }: StoryProps) => ( + ); -export const OnlyOneLink = (_: StoryArgs) => ( - - - +export const OnlyOneLink = (_: StoryArgs, { service, variant }: StoryProps) => ( + ); -export const OneLinkWithNoTitle = (_: StoryArgs) => ( - - - +export const OneLinkWithNoTitle = ( + _: StoryArgs, + { service, variant }: StoryProps, +) => ( + ); -export const MoreThanThreeLinks = (_: StoryArgs) => ( - - - +export const MoreThanThreeLinks = ( + _: StoryArgs, + { service, variant }: StoryProps, +) => ( + ); -export const NoImagesInData = (_: StoryArgs) => ( - - - +export const NoImagesInData = ( + _: StoryArgs, + { service, variant }: StoryProps, +) => ( + ); -export const TruncatedTextInSingleLink = (_: StoryArgs) => ( - - - +export const TruncatedTextInSingleLink = ( + _: StoryArgs, + { service, variant }: StoryProps, +) => ( + ); -export const ArabicText = (_: StoryArgs) => ( - - - +export const ArabicText = (_: StoryArgs, { variant }: StoryProps) => ( + ); ArabicText.globals = { service: { service: 'arabic' }, }; -export const WithTimestamp = (_: StoryArgs) => ( - - - +export const WithTimestamp = ( + _: StoryArgs, + { service, variant }: StoryProps, +) => ( + ); From 74e44ee6f88028c78e02a344b10d71e43d5b1b02 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 31 Dec 2025 08:52:43 +0000 Subject: [PATCH 051/100] remove import --- src/app/components/ArticleLinksBlock/index.stories.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/index.stories.tsx b/src/app/components/ArticleLinksBlock/index.stories.tsx index b44a69f8b23..b8f80c36ec3 100644 --- a/src/app/components/ArticleLinksBlock/index.stories.tsx +++ b/src/app/components/ArticleLinksBlock/index.stories.tsx @@ -1,4 +1,3 @@ -import styled from '@emotion/styled'; import { ServiceContextProvider } from '#contexts/ServiceContext'; import ArticleLinksBlock from '.'; import { From b9d29c2bd288a62ad0974df58dc14df335e93f77 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 31 Dec 2025 12:13:19 +0000 Subject: [PATCH 052/100] name change --- src/app/components/ArticleLinksBlock/PromoList/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index b1b4ca63fdf..dac46a2e665 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -26,7 +26,7 @@ const PromoList = ({ return (
      Date: Wed, 31 Dec 2025 12:58:02 +0000 Subject: [PATCH 053/100] remove role=list --- .../ArticleLinksBlock/PromoList/index.tsx | 16 +- ...ndex.test.jsx.snap => index.test.tsx.snap} | 617 ++++++++++-------- 2 files changed, 337 insertions(+), 296 deletions(-) rename src/app/components/ArticleLinksBlock/__snapshots__/{index.test.jsx.snap => index.test.tsx.snap} (68%) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index fb80101300c..65f82131f93 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -11,11 +11,7 @@ interface PromoListProps { eventTrackingData?: EventTrackingMetadata; } -const PromoList = ({ - blocks, - eventTrackingData, - // viewTracker, -}: PromoListProps) => { +const PromoList = ({ blocks, eventTrackingData }: PromoListProps) => { const { dir } = use(ServiceContext); const isOperaMini = useOperaMiniDetection(); const listBlocks = blocks.slice(0, 3); @@ -27,14 +23,8 @@ const PromoList = ({ const listStyles = isOperaMini ? styles.operaStyledList : styles.list; return ( -
      -
        +
        +
          {listBlocks.map((block, index) => { return (
        • li+li { + -webkit-margin-start: 0.5rem; + margin-inline-start: 0.5rem; +} + +@media (min-width: 25rem) { + .emotion-3>li:not(:first-of-type) { + -webkit-margin-start: 1rem; + margin-inline-start: 1rem; + } +} + +@media screen and (forced-colors: active) { + .emotion-3 { + border: solid 0.1875rem transparent; + } +} + +@media (max-width: 14.9375rem) { + .emotion-3:first-of-type { + -webkit-margin-start: 0.5rem; + margin-inline-start: 0.5rem; + } + + .emotion-3:last-of-type { + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; + } +} + +@media (min-width: 25rem) { + .emotion-3:first-of-type { + -webkit-margin-start: 1rem; + margin-inline-start: 1rem; + } +} + +@media (min-width: 37.5rem) { + .emotion-3:first-of-type { + -webkit-margin-start: 1rem; + margin-inline-start: 1rem; + } +} + +@media (min-width: 63rem) { + .emotion-3:first-of-type { + -webkit-margin-start: 0; + margin-inline-start: 0; + } +} + +.emotion-4 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -165,78 +240,79 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s flex-shrink: 0; } -@media (min-width: 0rem) { - .emotion-6 { - margin-left: 0.5rem; +@media screen and (forced-colors: active) { + .emotion-4 { + border: solid 0.1875rem transparent; } +} - .emotion-6:first-child { - margin-left: 0.5rem; +@media (max-width: 14.9375rem) { + .emotion-4:first-of-type { + -webkit-margin-start: 0.5rem; + margin-inline-start: 0.5rem; } - .emotion-6:last-child { - margin-right: 0.5rem; + .emotion-4:last-of-type { + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; } } @media (min-width: 25rem) { - .emotion-6 { - margin-left: 1rem; + .emotion-4:first-of-type { + -webkit-margin-start: 1rem; + margin-inline-start: 1rem; } +} - .emotion-6:first-child { - margin-left: 1rem; +@media (min-width: 37.5rem) { + .emotion-4:first-of-type { + -webkit-margin-start: 1rem; + margin-inline-start: 1rem; } } @media (min-width: 63rem) { - .emotion-6 { - margin-left: 1rem; - } - - .emotion-6:first-child { - margin-left: 0; + .emotion-4:first-of-type { + -webkit-margin-start: 0; + margin-inline-start: 0; } } -.emotion-8 { +.emotion-5 { position: relative; background-color: #FFFFFF; padding: 1rem; margin-bottom: 1.5rem; height: auto; + display: block; } -@media (min-width: 0rem) { - .emotion-8 { +@media (max-width: 14.9375rem) { + .emotion-5 { width: 14.8125rem; } } @media (min-width: 37.5rem) { - .emotion-8 { + .emotion-5 { width: 11.125rem; } } @media (min-width: 63rem) { - .emotion-8 { + .emotion-5 { width: 12.6875rem; } } -.emotion-10 { - position: static; - color: #222222; - -webkit-text-decoration: none; - text-decoration: none; - overflow-wrap: break-word; - display: inline-block; +.emotion-6 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; font-style: normal; font-weight: 700; + display: webkit-box; width: 100%; -webkit-text-decoration: none; text-decoration: none; @@ -244,53 +320,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s overflow-y: hidden; -webkit-line-clamp: 4; -webkit-box-orient: vertical; - display: -webkit-box; color: #202224; } -.emotion-10:before { - bottom: 0; - content: ''; - left: 0; - overflow: hidden; - position: absolute; - right: 0; - top: 0; - white-space: nowrap; - z-index: 1; -} - -.emotion-10:hover, -.emotion-10:focus { - -webkit-text-decoration: underline; - text-decoration: underline; -} - -.emotion-10:visited { - color: #6E6E73; -} - @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-10 { + .emotion-6 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-10 { + .emotion-6 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-10:hover, -.emotion-10:focus { +.emotion-6:hover, +.emotion-6:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-10:visited { +.emotion-6:visited { color: #545658; } @@ -298,70 +351,67 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s
          Show all links (no images) -
          -
        • -
          +
        • - - Show headline - -
        - -
      • -
        + Show headline + +
        +
      • +
      • - - Link with Headline - -
      -
    • -
    • -
      + Link with Headline + +
      +
    • +
    • - - Brasil homepage - -
- - + + Brasil homepage + + + + + `; @@ -460,59 +510,77 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } .emotion-2 { - margin-left: 0.5rem; + background: #F6F6F6; + padding: 0 0.5rem 1rem; + margin: 0; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + overflow-x: auto; + width: 100vw; + -ms-overflow-style: none; + scrollbar-width: none; +} + +.emotion-2::-webkit-scrollbar { + display: none; } @media (min-width: 25rem) { .emotion-2 { - margin-left: 1rem; + padding: 0 1rem 1rem; + margin: 0 -0.2rem; } } -@media (min-width: 63rem) { +@media (min-width: 37.5rem) { .emotion-2 { - margin-left: 0; + padding: 0 1rem 1rem; } } -.emotion-4 { +@media screen and (forced-colors: active) { + .emotion-2 { + border: solid 0.1875rem transparent; + border-top: transparent; + } +} + +.emotion-3 { position: relative; background-color: #FFFFFF; padding: 1rem; margin-bottom: 1.5rem; height: auto; + display: block; } -@media (min-width: 0rem) { - .emotion-4 { +@media (max-width: 14.9375rem) { + .emotion-3 { width: 14.8125rem; } } @media (min-width: 37.5rem) { - .emotion-4 { + .emotion-3 { width: 11.125rem; } } @media (min-width: 63rem) { - .emotion-4 { + .emotion-3 { width: 12.6875rem; } } -.emotion-6 { - position: static; - color: #222222; - -webkit-text-decoration: none; - text-decoration: none; - overflow-wrap: break-word; - display: inline-block; +.emotion-4 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; font-style: normal; font-weight: 700; + display: webkit-box; width: 100%; -webkit-text-decoration: none; text-decoration: none; @@ -520,53 +588,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s overflow-y: hidden; -webkit-line-clamp: 4; -webkit-box-orient: vertical; - display: -webkit-box; color: #202224; } -.emotion-6:before { - bottom: 0; - content: ''; - left: 0; - overflow: hidden; - position: absolute; - right: 0; - top: 0; - white-space: nowrap; - z-index: 1; -} - -.emotion-6:hover, -.emotion-6:focus { - -webkit-text-decoration: underline; - text-decoration: underline; -} - -.emotion-6:visited { - color: #6E6E73; -} - @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-6 { + .emotion-4 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-6 { + .emotion-4 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-6:hover, -.emotion-6:focus { +.emotion-4:hover, +.emotion-4:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-6:visited { +.emotion-4:visited { color: #545658; } @@ -574,19 +619,19 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s
Single link @@ -691,102 +736,136 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } .emotion-2 { - display: block; - font-size: 1.125rem; - line-height: 1.375rem; + font-size: 0.875rem; + line-height: 1.125rem; font-family: ReithSans,Helvetica,Arial,sans-serif; font-style: normal; font-weight: 400; - margin-bottom: 1rem; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + background-color: #F6F6F6; + width: 100vw; + height: 2rem; color: #3F3F42; + padding: 0 0.5rem; } @media (min-width: 20rem) and (max-width: 37.4375rem) { .emotion-2 { - font-size: 1.25rem; - line-height: 1.5rem; + font-size: 0.875rem; + line-height: 1.125rem; } } @media (min-width: 37.5rem) { .emotion-2 { - font-size: 1.5rem; - line-height: 1.75rem; + font-size: 0.8125rem; + line-height: 1rem; } } -@media (min-width: 0rem) { +@media screen and (forced-colors: active) { .emotion-2 { - margin-left: 0.5rem; + border: solid 0.1875rem transparent; + border-bottom: transparent; } } -@media (min-width: 25rem) { +@media (max-width: 14.9375rem) { .emotion-2 { - margin-left: 1rem; + -webkit-margin-start: 0.5rem; + margin-inline-start: 0.5rem; + margin: 0; } } -@media (min-width: 63rem) { +@media (min-width: 25rem) { .emotion-2 { - margin-left: 0; + -webkit-margin-start: 1rem; + margin-inline-start: 1rem; + padding: 0 1rem; + margin: 0 -0.2rem; } } -.emotion-4 { - margin-left: 0.5rem; +.emotion-3 { + background: #F6F6F6; + padding: 0 0.5rem 1rem; + margin: 0; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + overflow-x: auto; + width: 100vw; + -ms-overflow-style: none; + scrollbar-width: none; +} + +.emotion-3::-webkit-scrollbar { + display: none; } @media (min-width: 25rem) { - .emotion-4 { - margin-left: 1rem; + .emotion-3 { + padding: 0 1rem 1rem; + margin: 0 -0.2rem; } } -@media (min-width: 63rem) { - .emotion-4 { - margin-left: 0; +@media (min-width: 37.5rem) { + .emotion-3 { + padding: 0 1rem 1rem; } } -.emotion-6 { +@media screen and (forced-colors: active) { + .emotion-3 { + border: solid 0.1875rem transparent; + border-top: transparent; + } +} + +.emotion-4 { position: relative; background-color: #FFFFFF; padding: 1rem; margin-bottom: 1.5rem; height: auto; + display: block; } -@media (min-width: 0rem) { - .emotion-6 { +@media (max-width: 14.9375rem) { + .emotion-4 { width: 14.8125rem; } } @media (min-width: 37.5rem) { - .emotion-6 { + .emotion-4 { width: 11.125rem; } } @media (min-width: 63rem) { - .emotion-6 { + .emotion-4 { width: 12.6875rem; } } -.emotion-8 { - position: static; - color: #222222; - -webkit-text-decoration: none; - text-decoration: none; - overflow-wrap: break-word; - display: inline-block; +.emotion-5 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; font-style: normal; font-weight: 700; + display: webkit-box; width: 100%; -webkit-text-decoration: none; text-decoration: none; @@ -794,53 +873,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s overflow-y: hidden; -webkit-line-clamp: 4; -webkit-box-orient: vertical; - display: -webkit-box; color: #202224; } -.emotion-8:before { - bottom: 0; - content: ''; - left: 0; - overflow: hidden; - position: absolute; - right: 0; - top: 0; - white-space: nowrap; - z-index: 1; -} - -.emotion-8:hover, -.emotion-8:focus { - -webkit-text-decoration: underline; - text-decoration: underline; -} - -.emotion-8:visited { - color: #6E6E73; -} - @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-8 { + .emotion-5 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-8 { + .emotion-5 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-8:hover, -.emotion-8:focus { +.emotion-5:hover, +.emotion-5:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-8:visited { +.emotion-5:visited { color: #545658; } @@ -848,12 +904,12 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s
Single link @@ -973,59 +1029,77 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh } .emotion-2 { - margin-left: 0.5rem; + background: #F6F6F6; + padding: 0 0.5rem 1rem; + margin: 0; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + overflow-x: auto; + width: 100vw; + -ms-overflow-style: none; + scrollbar-width: none; +} + +.emotion-2::-webkit-scrollbar { + display: none; } @media (min-width: 25rem) { .emotion-2 { - margin-left: 1rem; + padding: 0 1rem 1rem; + margin: 0 -0.2rem; } } -@media (min-width: 63rem) { +@media (min-width: 37.5rem) { .emotion-2 { - margin-left: 0; + padding: 0 1rem 1rem; } } -.emotion-4 { +@media screen and (forced-colors: active) { + .emotion-2 { + border: solid 0.1875rem transparent; + border-top: transparent; + } +} + +.emotion-3 { position: relative; background-color: #E6E8EA; padding: 1rem; margin-bottom: 1.5rem; height: auto; + display: block; } -@media (min-width: 0rem) { - .emotion-4 { +@media (max-width: 14.9375rem) { + .emotion-3 { width: 14.8125rem; } } @media (min-width: 37.5rem) { - .emotion-4 { + .emotion-3 { width: 11.125rem; } } @media (min-width: 63rem) { - .emotion-4 { + .emotion-3 { width: 12.6875rem; } } -.emotion-6 { - position: static; - color: #222222; - -webkit-text-decoration: none; - text-decoration: none; - overflow-wrap: break-word; - display: inline-block; +.emotion-4 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; font-style: normal; font-weight: 700; + display: webkit-box; width: 100%; -webkit-text-decoration: none; text-decoration: none; @@ -1033,53 +1107,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh overflow-y: hidden; -webkit-line-clamp: 4; -webkit-box-orient: vertical; - display: -webkit-box; color: #141414; } -.emotion-6:before { - bottom: 0; - content: ''; - left: 0; - overflow: hidden; - position: absolute; - right: 0; - top: 0; - white-space: nowrap; - z-index: 1; -} - -.emotion-6:hover, -.emotion-6:focus { - -webkit-text-decoration: underline; - text-decoration: underline; -} - -.emotion-6:visited { - color: #6E6E73; -} - @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-6 { + .emotion-4 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-6 { + .emotion-4 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-6:hover, -.emotion-6:focus { +.emotion-4:hover, +.emotion-4:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-6:visited { +.emotion-4:visited { color: #545658; } @@ -1087,19 +1138,19 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh
Single link From b2e085ad627d1b2a36a1501c9c118bfd7cc0fed7 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 31 Dec 2025 13:05:43 +0000 Subject: [PATCH 054/100] resolving conflict --- src/app/components/ArticleLinksBlock/PromoList/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index 313140f6544..67eeab46a31 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -21,7 +21,7 @@ const PromoList = ({ blocks, eventTrackingData }: PromoListProps) => { const listStyles = isOperaMini ? styles.operaStyledList : styles.list; return ( -
+
    {listBlocks.map((block, index) => { return ( From 4fbf40179c48fd34c370bf0130531cda0cdcde15 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 31 Dec 2025 13:24:26 +0000 Subject: [PATCH 055/100] fix styling error after merge --- .../ArticleLinksBlock/PromoList/index.styles.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index b49fc6bae69..ce6581ba934 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -4,12 +4,14 @@ import { css, Theme } from '@emotion/react'; export default { standardPromo: ({ spacings }: Theme) => css({ - listStyle: 'none', - paddingInlineStart: '0', - margin: '0', - display: 'flex', - flexDirection: 'column', - gap: `${spacings.FULL}rem`, + '& ul': { + listStyle: 'none', + paddingInlineStart: '0', + margin: '0', + display: 'flex', + flexDirection: 'column', + gap: `${spacings.FULL}rem`, + }, }), operaPromo: () => css({ From 7947fa9b99f0030a50267cd675d93511282b7330 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 31 Dec 2025 14:47:22 +0000 Subject: [PATCH 056/100] fix margin issue and delete leftover scroll css --- .../components/ArticleLinksBlock/Promo/index.styles.tsx | 1 - .../ArticleLinksBlock/PromoList/index.styles.tsx | 9 ++++++--- src/app/components/ArticleLinksBlock/index.styles.tsx | 9 ++------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx index 40acd651b55..5238016e733 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx @@ -27,7 +27,6 @@ export default { backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, padding: `${spacings.DOUBLE}rem`, paddingInlineEnd: `${pixelsToRem(38)}rem`, - gap: `${spacings.FULL}rem`, height: 'auto', display: 'block', width: '100%', diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index ce6581ba934..ac0c7f08f80 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -11,6 +11,9 @@ export default { display: 'flex', flexDirection: 'column', gap: `${spacings.FULL}rem`, + // wordWrap: 'break-word', + // overflowWrap: 'break-word', + width: '100%', }, }), operaPromo: () => @@ -23,7 +26,7 @@ export default { css({ display: 'flex', flexShrink: 0, - marginInline: `${spacings.FULL}rem`, + marginInline: `${spacings.HALF}rem`, ':last-of-type': { marginBottom: `${spacings.TRIPLE}rem`, }, @@ -32,11 +35,11 @@ export default { }, [mq.GROUP_2_MIN_WIDTH]: { - marginInline: `${spacings.DOUBLE}rem`, + marginInline: `${spacings.FULL}rem`, }, [mq.GROUP_3_MIN_WIDTH]: { - marginInline: `${spacings.DOUBLE}rem`, + marginInline: `${spacings.FULL}rem`, }, [mq.GROUP_4_MIN_WIDTH]: { diff --git a/src/app/components/ArticleLinksBlock/index.styles.tsx b/src/app/components/ArticleLinksBlock/index.styles.tsx index 9cd06e02cd8..510e65a7a26 100644 --- a/src/app/components/ArticleLinksBlock/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/index.styles.tsx @@ -10,11 +10,6 @@ export default { display: 'flex', overflowX: 'auto', width: '100vw', - '-ms-overflow-style': 'none', - scrollbarWidth: 'none', - '&::-webkit-scrollbar': { - display: 'none', - }, [mq.GROUP_2_MIN_WIDTH]: { padding: `0 ${spacings.DOUBLE}rem ${spacings.DOUBLE}rem`, margin: '0 -0.2rem', @@ -52,11 +47,11 @@ export default { }, [mq.GROUP_0_MAX_WIDTH]: { - marginInlineStart: `${spacings.FULL}rem`, + marginInline: `${spacings.FULL}rem`, margin: 0, }, [mq.GROUP_2_MIN_WIDTH]: { - marginInlineStart: `${spacings.DOUBLE}rem`, + marginInline: `${spacings.DOUBLE}rem`, padding: `0 ${spacings.DOUBLE}rem`, margin: '0 -0.2rem', }, From b3944178425d3447175966b4e7ad7a009272c511 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 6 Jan 2026 09:12:32 +0000 Subject: [PATCH 057/100] change to arrow function --- src/app/components/ArticleLinksBlock/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 5e584d63452..b74ac738481 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -16,10 +16,10 @@ interface ArticleLinksBlockProps { blockGroupIndex?: number | null; } -function ArticleLinksBlock({ +const ArticleLinksBlock = ({ blocks, blockGroupIndex = null, -}: ArticleLinksBlockProps) { +}: ArticleLinksBlockProps) => { const { dir, translations } = use(ServiceContext); const eventTrackingData = { @@ -84,6 +84,6 @@ function ArticleLinksBlock({ )} ); -} +}; export default ArticleLinksBlock; From e9ce557b67a56d3e3f4fd674db89966f114ae58d Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Tue, 6 Jan 2026 13:31:36 +0000 Subject: [PATCH 058/100] removed clickTracker --- src/app/components/ArticleLinksBlock/index.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index b74ac738481..958532e694c 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -28,7 +28,6 @@ const ArticleLinksBlock = ({ }; const viewTracker = useViewTracker(eventTrackingData); - const clickTracker = useClickTrackerHandler(eventTrackingData); if (!blocks || isEmpty(blocks)) { return null; @@ -72,13 +71,12 @@ const ArticleLinksBlock = ({ )} {isSingleItem ? (
    - +
    ) : ( )} From f66612acb4947a337b50cad1773c31cf107b74d5 Mon Sep 17 00:00:00 2001 From: Nabeel Khan Date: Tue, 6 Jan 2026 13:32:18 +0000 Subject: [PATCH 059/100] removed import --- src/app/components/ArticleLinksBlock/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 958532e694c..4df850a7632 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -3,7 +3,6 @@ import isEmpty from 'ramda/src/isEmpty'; import tail from 'ramda/src/tail'; import { GridItemMediumNoMargin } from '#components/Grid'; import useViewTracker from '#hooks/useViewTracker'; -import useClickTrackerHandler from '#hooks/useClickTrackerHandler'; import idSanitiser from '#lib/utilities/idSanitiser'; import { OptimoBlock } from '#app/models/types/optimo'; import { ServiceContext } from '../../contexts/ServiceContext'; From aca55a25301ce7f3fa5228e7ff44c0480fd52189 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Tue, 6 Jan 2026 13:56:02 +0000 Subject: [PATCH 060/100] pass clickTracker prop --- src/app/components/ArticleLinksBlock/Promo/index.tsx | 9 ++++----- src/app/components/ArticleLinksBlock/index.tsx | 4 +++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index f6a172d6c9e..af3152b9e4c 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -10,12 +10,11 @@ import styles from './index.styles'; interface PromoProps { block: OptimoBlock; - eventTrackingData?: EventTrackingMetadata; + clickTracker?: ReturnType; } -function Promo({ block, eventTrackingData }: PromoProps) { +const Promo = ({ block }: PromoProps) => { const { serviceDatetimeLocale } = use(ServiceContext); - const clickTrackerHandler = useClickTrackerHandler(eventTrackingData); const textBlock = filterForBlockType( (block?.model as { blocks?: Record })?.blocks || {}, @@ -39,7 +38,7 @@ function Promo({ block, eventTrackingData }: PromoProps) { return (
    - + {title} {timestamp && ( @@ -52,6 +51,6 @@ function Promo({ block, eventTrackingData }: PromoProps) { )}
    ); -} +}; export default Promo; diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 4df850a7632..778295ae1b9 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -5,6 +5,7 @@ import { GridItemMediumNoMargin } from '#components/Grid'; import useViewTracker from '#hooks/useViewTracker'; import idSanitiser from '#lib/utilities/idSanitiser'; import { OptimoBlock } from '#app/models/types/optimo'; +import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; import { ServiceContext } from '../../contexts/ServiceContext'; import Promo from './Promo'; import PromoList from './PromoList'; @@ -27,6 +28,7 @@ const ArticleLinksBlock = ({ }; const viewTracker = useViewTracker(eventTrackingData); + const clickTracker = useClickTrackerHandler(eventTrackingData); if (!blocks || isEmpty(blocks)) { return null; @@ -70,7 +72,7 @@ const ArticleLinksBlock = ({ )} {isSingleItem ? (
    - +
    ) : ( Date: Wed, 7 Jan 2026 11:13:54 +0000 Subject: [PATCH 061/100] remove operaMini detection hook --- .../PromoList/index.styles.tsx | 35 +++++++++---------- .../ArticleLinksBlock/PromoList/index.tsx | 15 +++----- .../components/ArticleLinksBlock/index.tsx | 1 + 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index e84e9380167..86cf867fef2 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -1,8 +1,9 @@ +import { OPERA_MINI_CLASSNAME } from '#app/lib/utilities/addOperaMiniClassScript'; import pixelsToRem from '#app/utilities/pixelsToRem'; import { css, Theme } from '@emotion/react'; export default { - standardScrollPromo: ({ mq, spacings }: Theme) => + promo: ({ mq, spacings }: Theme) => css({ listStyle: 'none', paddingInlineStart: '0', @@ -25,12 +26,11 @@ export default { marginInlineStart: `${spacings.DOUBLE}rem`, }, }, - }), - operaScrollPromo: () => - css({ - listStyle: 'none', - paddingInlineStart: '0', - margin: '0', + [`.${OPERA_MINI_CLASSNAME} &`]: { + listStyle: 'none', + paddingInlineStart: '0', + margin: '0', + }, }), list: ({ mq, spacings }: Theme) => css({ @@ -66,19 +66,18 @@ export default { marginInlineStart: 0, }, }, - }), - operaStyledList: ({ mq, spacings }: Theme) => - css({ - [mq.GROUP_0_MAX_WIDTH]: { - marginInlineStart: `${spacings.FULL}rem`, - }, + [`.${OPERA_MINI_CLASSNAME} &`]: { + [mq.GROUP_0_MAX_WIDTH]: { + marginInlineStart: `${spacings.FULL}rem`, + }, - [mq.GROUP_2_MIN_WIDTH]: { - marginInlineStart: `${spacings.DOUBLE}rem`, - }, + [mq.GROUP_2_MIN_WIDTH]: { + marginInlineStart: `${spacings.DOUBLE}rem`, + }, - [mq.GROUP_4_MIN_WIDTH]: { - marginInlineStart: 0, + [mq.GROUP_4_MIN_WIDTH]: { + marginInlineStart: 0, + }, }, }), }; diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index 65f82131f93..ad07c01db2d 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -11,28 +11,21 @@ interface PromoListProps { eventTrackingData?: EventTrackingMetadata; } -const PromoList = ({ blocks, eventTrackingData }: PromoListProps) => { +const PromoList = ({ blocks }: PromoListProps) => { const { dir } = use(ServiceContext); - const isOperaMini = useOperaMiniDetection(); const listBlocks = blocks.slice(0, 3); - const scrollablePromoStyles = isOperaMini - ? styles.operaScrollPromo - : styles.standardScrollPromo; - - const listStyles = isOperaMini ? styles.operaStyledList : styles.list; - return ( -
    +
      {listBlocks.map((block, index) => { return (
    • - +
    • ); })} diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 778295ae1b9..dd0884a6781 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -79,6 +79,7 @@ const ArticleLinksBlock = ({ blocks={blocksWithoutTitle} {...viewTracker} a11yAttributes={a11yAttributes} + eventTrackingData={eventTrackingData} /> )} From f38dc3dd91fd0831e9078d391c57208299816f38 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 11:28:47 +0000 Subject: [PATCH 062/100] remove unused import --- src/app/components/ArticleLinksBlock/Promo/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index af3152b9e4c..64388b426c6 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -3,7 +3,6 @@ import filterForBlockType from '#lib/utilities/blockHandlers'; import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import PromoTimestamp from '#components/Promo/timestamp'; import { OptimoBlock } from '#app/models/types/optimo'; -import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; import { ServiceContext } from '../../../contexts/ServiceContext'; import styles from './index.styles'; From 60e0eaef89c61d6c3b0c154936743db57e9dac61 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 11:30:03 +0000 Subject: [PATCH 063/100] remove unused import --- src/app/components/ArticleLinksBlock/PromoList/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index ad07c01db2d..859b5638749 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -1,5 +1,4 @@ import { use } from 'react'; -import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import { OptimoBlock } from '#app/models/types/optimo'; import { ServiceContext } from '../../../contexts/ServiceContext'; From 9458196c208eff117280a5e4e6f73bca953a4f99 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 11:42:48 +0000 Subject: [PATCH 064/100] add viewTracker as a prop and pass at top level --- src/app/components/ArticleLinksBlock/PromoList/index.tsx | 2 ++ src/app/components/ArticleLinksBlock/index.tsx | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index 859b5638749..2c8e1d3720d 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -1,6 +1,7 @@ import { use } from 'react'; import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import { OptimoBlock } from '#app/models/types/optimo'; +import { ViewTracker } from '#app/lib/analyticsUtils/types'; import { ServiceContext } from '../../../contexts/ServiceContext'; import Promo from '../Promo'; import styles from './index.styles'; @@ -8,6 +9,7 @@ import styles from './index.styles'; interface PromoListProps { blocks: OptimoBlock[]; eventTrackingData?: EventTrackingMetadata; + viewTracker?: ViewTracker; } const PromoList = ({ blocks }: PromoListProps) => { diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index dd0884a6781..4202c47753d 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -77,8 +77,8 @@ const ArticleLinksBlock = ({ ) : ( )} From 53969f0e2c1f2e6a29d68019cde899e313b450c8 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 13:41:18 +0000 Subject: [PATCH 065/100] update bundle size --- scripts/bundleSize/bundleSizeConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bundleSize/bundleSizeConfig.js b/scripts/bundleSize/bundleSizeConfig.js index 5da04936708..08bfad7b6c9 100644 --- a/scripts/bundleSize/bundleSizeConfig.js +++ b/scripts/bundleSize/bundleSizeConfig.js @@ -10,4 +10,4 @@ export const VARIANCE = 5; export const MIN_SIZE = 926; -export const MAX_SIZE = 1312; +export const MAX_SIZE = 1306; From 121aa225569b893ae08fd5794f071625e793d2df Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 13:49:12 +0000 Subject: [PATCH 066/100] update snapshot --- .../__snapshots__/index.test.tsx.snap | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index 312bf54fc57..f641f5eed37 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -191,6 +191,13 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } } +.is-opera-mini .emotion-3 { + list-style: none; + -webkit-padding-start: 0; + padding-inline-start: 0; + margin: 0; +} + @media screen and (forced-colors: active) { .emotion-3 { border: solid 0.1875rem transparent; @@ -230,6 +237,27 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } } +@media (max-width: 14.9375rem) { + .is-opera-mini .emotion-3 { + -webkit-margin-start: 0.5rem; + margin-inline-start: 0.5rem; + } +} + +@media (min-width: 25rem) { + .is-opera-mini .emotion-3 { + -webkit-margin-start: 1rem; + margin-inline-start: 1rem; + } +} + +@media (min-width: 63rem) { + .is-opera-mini .emotion-3 { + -webkit-margin-start: 0; + margin-inline-start: 0; + } +} + .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -279,6 +307,27 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } } +@media (max-width: 14.9375rem) { + .is-opera-mini .emotion-4 { + -webkit-margin-start: 0.5rem; + margin-inline-start: 0.5rem; + } +} + +@media (min-width: 25rem) { + .is-opera-mini .emotion-4 { + -webkit-margin-start: 1rem; + margin-inline-start: 1rem; + } +} + +@media (min-width: 63rem) { + .is-opera-mini .emotion-4 { + -webkit-margin-start: 0; + margin-inline-start: 0; + } +} + .emotion-5 { position: relative; background-color: #FFFFFF; From 2aa6e15245c16dfdc4ef8fc26faa0a2b23901548 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 16:09:39 +0000 Subject: [PATCH 067/100] addressing comments --- src/app/components/ArticleLinksBlock/Promo/index.tsx | 4 ++-- src/app/components/ArticleLinksBlock/PromoList/index.tsx | 8 +++++--- src/app/components/ArticleLinksBlock/index.tsx | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index 64388b426c6..17801774fe0 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -12,7 +12,7 @@ interface PromoProps { clickTracker?: ReturnType; } -const Promo = ({ block }: PromoProps) => { +const Promo = ({ block, clickTracker }: PromoProps) => { const { serviceDatetimeLocale } = use(ServiceContext); const textBlock = filterForBlockType( @@ -37,7 +37,7 @@ const Promo = ({ block }: PromoProps) => { return (
      - + {title} {timestamp && ( diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index 2c8e1d3720d..799014f77fd 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -2,6 +2,7 @@ import { use } from 'react'; import { EventTrackingMetadata } from '#app/models/types/eventTracking'; import { OptimoBlock } from '#app/models/types/optimo'; import { ViewTracker } from '#app/lib/analyticsUtils/types'; +import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; import { ServiceContext } from '../../../contexts/ServiceContext'; import Promo from '../Promo'; import styles from './index.styles'; @@ -10,14 +11,15 @@ interface PromoListProps { blocks: OptimoBlock[]; eventTrackingData?: EventTrackingMetadata; viewTracker?: ViewTracker; + clickTracker?: ReturnType; } -const PromoList = ({ blocks }: PromoListProps) => { +const PromoList = ({ blocks, viewTracker, clickTracker }: PromoListProps) => { const { dir } = use(ServiceContext); const listBlocks = blocks.slice(0, 3); return ( -
      +
        {listBlocks.map((block, index) => { return ( @@ -26,7 +28,7 @@ const PromoList = ({ blocks }: PromoListProps) => { // eslint-disable-next-line react/no-array-index-key key={index} > - + ); })} diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 4202c47753d..883bb08f5ff 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -78,6 +78,7 @@ const ArticleLinksBlock = ({ From b6107dcb7890dacd9dc22449e4992e976b82f389 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 17:43:10 +0000 Subject: [PATCH 068/100] change name of css class --- src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index 733f793a3df..17013a191f7 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -3,7 +3,7 @@ import pixelsToRem from '#app/utilities/pixelsToRem'; import { css, Theme } from '@emotion/react'; export default { - standardPromo: ({ spacings }: Theme) => + promo: ({ spacings }: Theme) => css({ '& ul': { listStyle: 'none', From 95ff1528d802230f09edd6c9d068e17e65bd8faa Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 17:44:38 +0000 Subject: [PATCH 069/100] reinstate dir for chevron --- src/app/components/ArticleLinksBlock/Promo/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index a3668238664..45206cd5723 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -14,7 +14,7 @@ interface PromoProps { } const Promo = ({ block, clickTracker }: PromoProps) => { - const { serviceDatetimeLocale } = use(ServiceContext); + const { serviceDatetimeLocale, dir } = use(ServiceContext); const textBlock = filterForBlockType( (block?.model as { blocks?: Record })?.blocks || {}, From b31742151d6bd083570f9d9222edd0364dcc8a43 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 17:57:35 +0000 Subject: [PATCH 070/100] update snapshots --- .../__snapshots__/index.test.tsx.snap | 353 +++++++++--------- 1 file changed, 170 insertions(+), 183 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index f641f5eed37..ee2fabffd85 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -137,35 +137,20 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s @media (max-width: 14.9375rem) { .emotion-2 { - -webkit-margin-start: 0.5rem; - margin-inline-start: 0.5rem; + margin-inline: 0.5rem; margin: 0; } } @media (min-width: 25rem) { .emotion-2 { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; + margin-inline: 1rem; padding: 0 1rem; margin: 0 -0.2rem; } } .emotion-3 { - list-style: none; - -webkit-padding-start: 0; - padding-inline-start: 0; - margin: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - overflow-x: scroll; - scroll-behavior: auto; - -webkit-overflow-scrolling: touch; - scrollbar-width: none; - -ms-overflow-style: none; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -173,22 +158,23 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; + margin-inline: 0.25rem; } -.emotion-3::-webkit-scrollbar { - display: none; -} - -.emotion-3>li+li { - -webkit-margin-start: 0.5rem; - margin-inline-start: 0.5rem; -} - -@media (min-width: 25rem) { - .emotion-3>li:not(:first-of-type) { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; - } +.emotion-3 ul { + list-style: none; + -webkit-padding-start: 0; + padding-inline-start: 0; + margin: 0; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: 0.5rem; + width: 100%; } .is-opera-mini .emotion-3 { @@ -198,63 +184,49 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s margin: 0; } +.emotion-3:last-of-type { + margin-bottom: 1.5rem; +} + @media screen and (forced-colors: active) { .emotion-3 { border: solid 0.1875rem transparent; } } -@media (max-width: 14.9375rem) { - .emotion-3:first-of-type { - -webkit-margin-start: 0.5rem; - margin-inline-start: 0.5rem; - } - - .emotion-3:last-of-type { - -webkit-margin-end: 0.5rem; - margin-inline-end: 0.5rem; - } -} - @media (min-width: 25rem) { - .emotion-3:first-of-type { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; + .emotion-3 { + margin-inline: 0.5rem; } } @media (min-width: 37.5rem) { - .emotion-3:first-of-type { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; + .emotion-3 { + margin-inline: 0.5rem; } } @media (min-width: 63rem) { - .emotion-3:first-of-type { - -webkit-margin-start: 0; - margin-inline-start: 0; + .emotion-3 { + margin-inline: 0; } } @media (max-width: 14.9375rem) { .is-opera-mini .emotion-3 { - -webkit-margin-start: 0.5rem; - margin-inline-start: 0.5rem; + margin-inline: 0.5rem; } } @media (min-width: 25rem) { .is-opera-mini .emotion-3 { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; + margin-inline: 1rem; } } @media (min-width: 63rem) { .is-opera-mini .emotion-3 { - -webkit-margin-start: 0; - margin-inline-start: 0; + margin-inline: 0; } } @@ -266,6 +238,11 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; + margin-inline: 0.25rem; +} + +.emotion-4:last-of-type { + margin-bottom: 1.5rem; } @media screen and (forced-colors: active) { @@ -274,57 +251,39 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } } -@media (max-width: 14.9375rem) { - .emotion-4:first-of-type { - -webkit-margin-start: 0.5rem; - margin-inline-start: 0.5rem; - } - - .emotion-4:last-of-type { - -webkit-margin-end: 0.5rem; - margin-inline-end: 0.5rem; - } -} - @media (min-width: 25rem) { - .emotion-4:first-of-type { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; + .emotion-4 { + margin-inline: 0.5rem; } } @media (min-width: 37.5rem) { - .emotion-4:first-of-type { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; + .emotion-4 { + margin-inline: 0.5rem; } } @media (min-width: 63rem) { - .emotion-4:first-of-type { - -webkit-margin-start: 0; - margin-inline-start: 0; + .emotion-4 { + margin-inline: 0; } } @media (max-width: 14.9375rem) { .is-opera-mini .emotion-4 { - -webkit-margin-start: 0.5rem; - margin-inline-start: 0.5rem; + margin-inline: 0.5rem; } } @media (min-width: 25rem) { .is-opera-mini .emotion-4 { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; + margin-inline: 1rem; } } @media (min-width: 63rem) { .is-opera-mini .emotion-4 { - -webkit-margin-start: 0; - margin-inline-start: 0; + margin-inline: 0; } } @@ -332,27 +291,11 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s position: relative; background-color: #FFFFFF; padding: 1rem; - margin-bottom: 1.5rem; + -webkit-padding-end: 2.375rem; + padding-inline-end: 2.375rem; height: auto; display: block; -} - -@media (max-width: 14.9375rem) { - .emotion-5 { - width: 14.8125rem; - } -} - -@media (min-width: 37.5rem) { - .emotion-5 { - width: 11.125rem; - } -} - -@media (min-width: 63rem) { - .emotion-5 { - width: 12.6875rem; - } + width: 100%; } .emotion-6 { @@ -396,6 +339,16 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s color: #545658; } +.emotion-7 { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + inset-inline-end: 0.75rem; +} +
        Show headline +
        @@ -442,6 +407,18 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s href="https://www.bbc.com/mundo" > Link with Headline +
      @@ -456,6 +433,18 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s href="https://www.bbc.com/brasil" > Brasil homepage +
      @@ -568,12 +557,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s display: flex; overflow-x: auto; width: 100vw; - -ms-overflow-style: none; - scrollbar-width: none; -} - -.emotion-2::-webkit-scrollbar { - display: none; } @media (min-width: 25rem) { @@ -600,27 +583,11 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s position: relative; background-color: #FFFFFF; padding: 1rem; - margin-bottom: 1.5rem; + -webkit-padding-end: 2.375rem; + padding-inline-end: 2.375rem; height: auto; display: block; -} - -@media (max-width: 14.9375rem) { - .emotion-3 { - width: 14.8125rem; - } -} - -@media (min-width: 37.5rem) { - .emotion-3 { - width: 11.125rem; - } -} - -@media (min-width: 63rem) { - .emotion-3 { - width: 12.6875rem; - } + width: 100%; } .emotion-4 { @@ -664,6 +631,16 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s color: #545658; } +.emotion-5 { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + inset-inline-end: 0.75rem; +} +
      Single link +
      @@ -828,16 +817,14 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s @media (max-width: 14.9375rem) { .emotion-2 { - -webkit-margin-start: 0.5rem; - margin-inline-start: 0.5rem; + margin-inline: 0.5rem; margin: 0; } } @media (min-width: 25rem) { .emotion-2 { - -webkit-margin-start: 1rem; - margin-inline-start: 1rem; + margin-inline: 1rem; padding: 0 1rem; margin: 0 -0.2rem; } @@ -853,12 +840,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s display: flex; overflow-x: auto; width: 100vw; - -ms-overflow-style: none; - scrollbar-width: none; -} - -.emotion-3::-webkit-scrollbar { - display: none; } @media (min-width: 25rem) { @@ -885,27 +866,11 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s position: relative; background-color: #FFFFFF; padding: 1rem; - margin-bottom: 1.5rem; + -webkit-padding-end: 2.375rem; + padding-inline-end: 2.375rem; height: auto; display: block; -} - -@media (max-width: 14.9375rem) { - .emotion-4 { - width: 14.8125rem; - } -} - -@media (min-width: 37.5rem) { - .emotion-4 { - width: 11.125rem; - } -} - -@media (min-width: 63rem) { - .emotion-4 { - width: 12.6875rem; - } + width: 100%; } .emotion-5 { @@ -949,6 +914,16 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s color: #545658; } +.emotion-6 { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + inset-inline-end: 0.75rem; +} +
      Single link +
    @@ -1087,12 +1074,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh display: flex; overflow-x: auto; width: 100vw; - -ms-overflow-style: none; - scrollbar-width: none; -} - -.emotion-2::-webkit-scrollbar { - display: none; } @media (min-width: 25rem) { @@ -1119,27 +1100,11 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh position: relative; background-color: #E6E8EA; padding: 1rem; - margin-bottom: 1.5rem; + -webkit-padding-end: 2.375rem; + padding-inline-end: 2.375rem; height: auto; display: block; -} - -@media (max-width: 14.9375rem) { - .emotion-3 { - width: 14.8125rem; - } -} - -@media (min-width: 37.5rem) { - .emotion-3 { - width: 11.125rem; - } -} - -@media (min-width: 63rem) { - .emotion-3 { - width: 12.6875rem; - } + width: 100%; } .emotion-4 { @@ -1183,6 +1148,16 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh color: #545658; } +.emotion-5 { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + inset-inline-end: 0.75rem; +} +
    Single link +
    From 9e628bf87685db7a0a76b99cffcd37ccb82cd81c Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 18:18:16 +0000 Subject: [PATCH 071/100] remove grid component --- src/app/components/ArticleLinksBlock/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 883bb08f5ff..b8018bbc2d5 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -59,7 +59,7 @@ const ArticleLinksBlock = ({ }; return ( - +
    {typeof title === 'string' && title.length > 0 && ( )} - +
    ); }; From 1d5139a0337d167eef293169476015739673e364 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Wed, 7 Jan 2026 18:18:35 +0000 Subject: [PATCH 072/100] remove grid import --- src/app/components/ArticleLinksBlock/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index b8018bbc2d5..766966e4c88 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -1,7 +1,6 @@ import { use } from 'react'; import isEmpty from 'ramda/src/isEmpty'; import tail from 'ramda/src/tail'; -import { GridItemMediumNoMargin } from '#components/Grid'; import useViewTracker from '#hooks/useViewTracker'; import idSanitiser from '#lib/utilities/idSanitiser'; import { OptimoBlock } from '#app/models/types/optimo'; From 2a82ba437370e2e5a24c86be65f4abeebff0a0ac Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 08:51:51 +0000 Subject: [PATCH 073/100] snapshot updates --- .../__snapshots__/index.test.tsx.snap | 602 ++++-------------- 1 file changed, 115 insertions(+), 487 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index ee2fabffd85..413128cb5c7 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -1,99 +1,7 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`Article Links Block Mid Page Article Links Block it should match a11y snapshot for list 1`] = ` -@media (max-width: 14.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 15rem) and (max-width: 24.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 25rem) and (max-width: 37.4375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 37.5rem) and (max-width: 62.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 63rem) and (max-width: 79.9375rem) { - .emotion-0 { - margin-left: 20%; - } -} - -@media (min-width: 80rem) { - .emotion-0 { - margin-left: 40%; - } -} - -@supports (display: grid) { - .emotion-0 { - display: block; - width: initial; - margin: 0; - } - - @media (max-width: 14.9375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 15rem) and (max-width: 24.9375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 25rem) and (max-width: 37.4375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 37.5rem) and (max-width: 62.9375rem) { - .emotion-0 { - grid-template-columns: repeat(5, 1fr); - grid-column-end: span 5; - grid-column-start: 1; - } - } - - @media (min-width: 63rem) and (max-width: 79.9375rem) { - .emotion-0 { - grid-template-columns: repeat(5, 1fr); - grid-column-end: span 5; - grid-column-start: 2; - } - } - - @media (min-width: 80rem) { - .emotion-0 { - grid-template-columns: repeat(10, 1fr); - grid-column-end: span 10; - grid-column-start: 5; - } - } -} - -.emotion-2 { +.emotion-0 { font-size: 0.875rem; line-height: 1.125rem; font-family: ReithSans,Helvetica,Arial,sans-serif; @@ -115,42 +23,42 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-2 { + .emotion-0 { font-size: 0.875rem; line-height: 1.125rem; } } @media (min-width: 37.5rem) { - .emotion-2 { + .emotion-0 { font-size: 0.8125rem; line-height: 1rem; } } @media screen and (forced-colors: active) { - .emotion-2 { + .emotion-0 { border: solid 0.1875rem transparent; border-bottom: transparent; } } @media (max-width: 14.9375rem) { - .emotion-2 { + .emotion-0 { margin-inline: 0.5rem; margin: 0; } } @media (min-width: 25rem) { - .emotion-2 { + .emotion-0 { margin-inline: 1rem; padding: 0 1rem; margin: 0 -0.2rem; } } -.emotion-3 { +.emotion-1 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -161,7 +69,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s margin-inline: 0.25rem; } -.emotion-3 ul { +.emotion-1 ul { list-style: none; -webkit-padding-start: 0; padding-inline-start: 0; @@ -177,60 +85,60 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.is-opera-mini .emotion-3 { +.is-opera-mini .emotion-1 { list-style: none; -webkit-padding-start: 0; padding-inline-start: 0; margin: 0; } -.emotion-3:last-of-type { +.emotion-1:last-of-type { margin-bottom: 1.5rem; } @media screen and (forced-colors: active) { - .emotion-3 { + .emotion-1 { border: solid 0.1875rem transparent; } } @media (min-width: 25rem) { - .emotion-3 { + .emotion-1 { margin-inline: 0.5rem; } } @media (min-width: 37.5rem) { - .emotion-3 { + .emotion-1 { margin-inline: 0.5rem; } } @media (min-width: 63rem) { - .emotion-3 { + .emotion-1 { margin-inline: 0; } } @media (max-width: 14.9375rem) { - .is-opera-mini .emotion-3 { + .is-opera-mini .emotion-1 { margin-inline: 0.5rem; } } @media (min-width: 25rem) { - .is-opera-mini .emotion-3 { + .is-opera-mini .emotion-1 { margin-inline: 1rem; } } @media (min-width: 63rem) { - .is-opera-mini .emotion-3 { + .is-opera-mini .emotion-1 { margin-inline: 0; } } -.emotion-4 { +.emotion-2 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -241,53 +149,53 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s margin-inline: 0.25rem; } -.emotion-4:last-of-type { +.emotion-2:last-of-type { margin-bottom: 1.5rem; } @media screen and (forced-colors: active) { - .emotion-4 { + .emotion-2 { border: solid 0.1875rem transparent; } } @media (min-width: 25rem) { - .emotion-4 { + .emotion-2 { margin-inline: 0.5rem; } } @media (min-width: 37.5rem) { - .emotion-4 { + .emotion-2 { margin-inline: 0.5rem; } } @media (min-width: 63rem) { - .emotion-4 { + .emotion-2 { margin-inline: 0; } } @media (max-width: 14.9375rem) { - .is-opera-mini .emotion-4 { + .is-opera-mini .emotion-2 { margin-inline: 0.5rem; } } @media (min-width: 25rem) { - .is-opera-mini .emotion-4 { + .is-opera-mini .emotion-2 { margin-inline: 1rem; } } @media (min-width: 63rem) { - .is-opera-mini .emotion-4 { + .is-opera-mini .emotion-2 { margin-inline: 0; } } -.emotion-5 { +.emotion-3 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -298,7 +206,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.emotion-6 { +.emotion-4 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; @@ -316,30 +224,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-6 { + .emotion-4 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-6 { + .emotion-4 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-6:hover, -.emotion-6:focus { +.emotion-4:hover, +.emotion-4:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-6:visited { +.emotion-4:visited { color: #545658; } -.emotion-7 { +.emotion-5 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -350,15 +258,14 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s }
`; exports[`Article Links Block Mid Page Article Links Block it should match a11y snapshot for list with no title 1`] = ` -@media (max-width: 14.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 15rem) and (max-width: 24.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 25rem) and (max-width: 37.4375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 37.5rem) and (max-width: 62.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 63rem) and (max-width: 79.9375rem) { - .emotion-0 { - margin-left: 20%; - } -} - -@media (min-width: 80rem) { - .emotion-0 { - margin-left: 40%; - } -} - -@supports (display: grid) { - .emotion-0 { - display: block; - width: initial; - margin: 0; - } - - @media (max-width: 14.9375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 15rem) and (max-width: 24.9375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 25rem) and (max-width: 37.4375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 37.5rem) and (max-width: 62.9375rem) { - .emotion-0 { - grid-template-columns: repeat(5, 1fr); - grid-column-end: span 5; - grid-column-start: 1; - } - } - - @media (min-width: 63rem) and (max-width: 79.9375rem) { - .emotion-0 { - grid-template-columns: repeat(5, 1fr); - grid-column-end: span 5; - grid-column-start: 2; - } - } - - @media (min-width: 80rem) { - .emotion-0 { - grid-template-columns: repeat(10, 1fr); - grid-column-end: span 10; - grid-column-start: 5; - } - } -} - -.emotion-2 { +.emotion-0 { background: #F6F6F6; padding: 0 0.5rem 1rem; margin: 0; @@ -560,26 +375,26 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 25rem) { - .emotion-2 { + .emotion-0 { padding: 0 1rem 1rem; margin: 0 -0.2rem; } } @media (min-width: 37.5rem) { - .emotion-2 { + .emotion-0 { padding: 0 1rem 1rem; } } @media screen and (forced-colors: active) { - .emotion-2 { + .emotion-0 { border: solid 0.1875rem transparent; border-top: transparent; } } -.emotion-3 { +.emotion-1 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -590,7 +405,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.emotion-4 { +.emotion-2 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; @@ -608,30 +423,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-4 { + .emotion-2 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-4 { + .emotion-2 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-4:hover, -.emotion-4:focus { +.emotion-2:hover, +.emotion-2:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-4:visited { +.emotion-2:visited { color: #545658; } -.emotion-5 { +.emotion-3 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -642,28 +457,27 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s }
`; exports[`Article Links Block Mid Page Article Links Block it should match a11y snapshot for single card 1`] = ` -@media (max-width: 14.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 15rem) and (max-width: 24.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 25rem) and (max-width: 37.4375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 37.5rem) and (max-width: 62.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 63rem) and (max-width: 79.9375rem) { - .emotion-0 { - margin-left: 20%; - } -} - -@media (min-width: 80rem) { - .emotion-0 { - margin-left: 40%; - } -} - -@supports (display: grid) { - .emotion-0 { - display: block; - width: initial; - margin: 0; - } - - @media (max-width: 14.9375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 15rem) and (max-width: 24.9375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 25rem) and (max-width: 37.4375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 37.5rem) and (max-width: 62.9375rem) { - .emotion-0 { - grid-template-columns: repeat(5, 1fr); - grid-column-end: span 5; - grid-column-start: 1; - } - } - - @media (min-width: 63rem) and (max-width: 79.9375rem) { - .emotion-0 { - grid-template-columns: repeat(5, 1fr); - grid-column-end: span 5; - grid-column-start: 2; - } - } - - @media (min-width: 80rem) { - .emotion-0 { - grid-template-columns: repeat(10, 1fr); - grid-column-end: span 10; - grid-column-start: 5; - } - } -} - -.emotion-2 { +.emotion-0 { font-size: 0.875rem; line-height: 1.125rem; font-family: ReithSans,Helvetica,Arial,sans-serif; @@ -795,42 +517,42 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-2 { + .emotion-0 { font-size: 0.875rem; line-height: 1.125rem; } } @media (min-width: 37.5rem) { - .emotion-2 { + .emotion-0 { font-size: 0.8125rem; line-height: 1rem; } } @media screen and (forced-colors: active) { - .emotion-2 { + .emotion-0 { border: solid 0.1875rem transparent; border-bottom: transparent; } } @media (max-width: 14.9375rem) { - .emotion-2 { + .emotion-0 { margin-inline: 0.5rem; margin: 0; } } @media (min-width: 25rem) { - .emotion-2 { + .emotion-0 { margin-inline: 1rem; padding: 0 1rem; margin: 0 -0.2rem; } } -.emotion-3 { +.emotion-1 { background: #F6F6F6; padding: 0 0.5rem 1rem; margin: 0; @@ -843,26 +565,26 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 25rem) { - .emotion-3 { + .emotion-1 { padding: 0 1rem 1rem; margin: 0 -0.2rem; } } @media (min-width: 37.5rem) { - .emotion-3 { + .emotion-1 { padding: 0 1rem 1rem; } } @media screen and (forced-colors: active) { - .emotion-3 { + .emotion-1 { border: solid 0.1875rem transparent; border-top: transparent; } } -.emotion-4 { +.emotion-2 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -873,7 +595,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.emotion-5 { +.emotion-3 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; @@ -891,30 +613,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-5 { + .emotion-3 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-5 { + .emotion-3 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-5:hover, -.emotion-5:focus { +.emotion-3:hover, +.emotion-3:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-5:visited { +.emotion-3:visited { color: #545658; } -.emotion-6 { +.emotion-4 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -925,15 +647,14 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s }
`; exports[`Article Links Block Mid Page Article Links Block it should match snapshot when in dark ui mode 1`] = ` -@media (max-width: 14.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 15rem) and (max-width: 24.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 25rem) and (max-width: 37.4375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 37.5rem) and (max-width: 62.9375rem) { - .emotion-0 { - margin-left: 0%; - } -} - -@media (min-width: 63rem) and (max-width: 79.9375rem) { - .emotion-0 { - margin-left: 20%; - } -} - -@media (min-width: 80rem) { - .emotion-0 { - margin-left: 40%; - } -} - -@supports (display: grid) { - .emotion-0 { - display: block; - width: initial; - margin: 0; - } - - @media (max-width: 14.9375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 15rem) and (max-width: 24.9375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 25rem) and (max-width: 37.4375rem) { - .emotion-0 { - grid-template-columns: repeat(6, 1fr); - grid-column-end: span 6; - grid-column-start: 1; - } - } - - @media (min-width: 37.5rem) and (max-width: 62.9375rem) { - .emotion-0 { - grid-template-columns: repeat(5, 1fr); - grid-column-end: span 5; - grid-column-start: 1; - } - } - - @media (min-width: 63rem) and (max-width: 79.9375rem) { - .emotion-0 { - grid-template-columns: repeat(5, 1fr); - grid-column-end: span 5; - grid-column-start: 2; - } - } - - @media (min-width: 80rem) { - .emotion-0 { - grid-template-columns: repeat(10, 1fr); - grid-column-end: span 10; - grid-column-start: 5; - } - } -} - -.emotion-2 { +.emotion-0 { background: #F6F6F6; padding: 0 0.5rem 1rem; margin: 0; @@ -1077,26 +706,26 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh } @media (min-width: 25rem) { - .emotion-2 { + .emotion-0 { padding: 0 1rem 1rem; margin: 0 -0.2rem; } } @media (min-width: 37.5rem) { - .emotion-2 { + .emotion-0 { padding: 0 1rem 1rem; } } @media screen and (forced-colors: active) { - .emotion-2 { + .emotion-0 { border: solid 0.1875rem transparent; border-top: transparent; } } -.emotion-3 { +.emotion-1 { position: relative; background-color: #E6E8EA; padding: 1rem; @@ -1107,7 +736,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh width: 100%; } -.emotion-4 { +.emotion-2 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; @@ -1125,30 +754,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-4 { + .emotion-2 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-4 { + .emotion-2 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-4:hover, -.emotion-4:focus { +.emotion-2:hover, +.emotion-2:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-4:visited { +.emotion-2:visited { color: #545658; } -.emotion-5 { +.emotion-3 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -1159,28 +788,27 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh }
`; From 318d8543e9049a871819e65015ff0548ee2ae078 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 09:19:38 +0000 Subject: [PATCH 074/100] fix width issue with label and container --- .../components/ArticleLinksBlock/PromoList/index.styles.tsx | 2 -- src/app/components/ArticleLinksBlock/index.styles.tsx | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index 17013a191f7..f2422082ce1 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -12,8 +12,6 @@ export default { display: 'flex', flexDirection: 'column', gap: `${spacings.FULL}rem`, - // wordWrap: 'break-word', - // overflowWrap: 'break-word', width: '100%', }, [`.${OPERA_MINI_CLASSNAME} &`]: { diff --git a/src/app/components/ArticleLinksBlock/index.styles.tsx b/src/app/components/ArticleLinksBlock/index.styles.tsx index 510e65a7a26..565738a76dc 100644 --- a/src/app/components/ArticleLinksBlock/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/index.styles.tsx @@ -9,7 +9,7 @@ export default { margin: 0, display: 'flex', overflowX: 'auto', - width: '100vw', + width: '100%', [mq.GROUP_2_MIN_WIDTH]: { padding: `0 ${spacings.DOUBLE}rem ${spacings.DOUBLE}rem`, margin: '0 -0.2rem', @@ -37,7 +37,7 @@ export default { display: 'flex', alignItems: 'center', backgroundColor: palette.GREY_2, - width: '100vw', + width: '100%', height: `${spacings.QUADRUPLE}rem`, color: isDarkUi ? palette.GREY_2 : palette.SHADOW, padding: `0 ${spacings.FULL}rem`, From 08a1ea52c4e3d0bd7d6d3e5da38f21b8e4226701 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 09:28:23 +0000 Subject: [PATCH 075/100] snapshots --- .../__snapshots__/index.test.tsx.snap | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index 413128cb5c7..089803a8493 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -16,7 +16,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s -ms-flex-align: center; align-items: center; background-color: #F6F6F6; - width: 100vw; + width: 100%; height: 2rem; color: #3F3F42; padding: 0 0.5rem; @@ -371,7 +371,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s display: -ms-flexbox; display: flex; overflow-x: auto; - width: 100vw; + width: 100%; } @media (min-width: 25rem) { @@ -510,7 +510,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s -ms-flex-align: center; align-items: center; background-color: #F6F6F6; - width: 100vw; + width: 100%; height: 2rem; color: #3F3F42; padding: 0 0.5rem; @@ -561,7 +561,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s display: -ms-flexbox; display: flex; overflow-x: auto; - width: 100vw; + width: 100%; } @media (min-width: 25rem) { @@ -702,7 +702,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh display: -ms-flexbox; display: flex; overflow-x: auto; - width: 100vw; + width: 100%; } @media (min-width: 25rem) { From b85c383aa447d9da768dbd2795119633bf94c8ba Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 10:13:23 +0000 Subject: [PATCH 076/100] fix forced colours issue and adjust margin sizes --- .../PromoList/index.styles.tsx | 6 +- .../ArticleLinksBlock/PromoList/index.tsx | 2 +- .../__snapshots__/index.test.tsx.snap | 84 +------------------ .../ArticleLinksBlock/index.styles.tsx | 5 -- 4 files changed, 7 insertions(+), 90 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx index f2422082ce1..b8cb3cb9c83 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.styles.tsx @@ -24,7 +24,7 @@ export default { css({ display: 'flex', flexShrink: 0, - marginInline: `${spacings.HALF}rem`, + marginInline: `${spacings.FULL}rem`, ':last-of-type': { marginBottom: `${spacings.TRIPLE}rem`, }, @@ -33,11 +33,11 @@ export default { }, [mq.GROUP_2_MIN_WIDTH]: { - marginInline: `${spacings.FULL}rem`, + marginInline: `${spacings.DOUBLE}rem`, }, [mq.GROUP_3_MIN_WIDTH]: { - marginInline: `${spacings.FULL}rem`, + marginInline: `${spacings.DOUBLE}rem`, }, [mq.GROUP_4_MIN_WIDTH]: { diff --git a/src/app/components/ArticleLinksBlock/PromoList/index.tsx b/src/app/components/ArticleLinksBlock/PromoList/index.tsx index 799014f77fd..3cb11dd616f 100644 --- a/src/app/components/ArticleLinksBlock/PromoList/index.tsx +++ b/src/app/components/ArticleLinksBlock/PromoList/index.tsx @@ -19,7 +19,7 @@ const PromoList = ({ blocks, viewTracker, clickTracker }: PromoListProps) => { const listBlocks = blocks.slice(0, 3); return ( -
+
    {listBlocks.map((block, index) => { return ( diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index 089803a8493..a5a0d19fed3 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -58,17 +58,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } } -.emotion-1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-shrink: 0; - -ms-flex-negative: 0; - flex-shrink: 0; - margin-inline: 0.25rem; -} - .emotion-1 ul { list-style: none; -webkit-padding-start: 0; @@ -92,52 +81,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s margin: 0; } -.emotion-1:last-of-type { - margin-bottom: 1.5rem; -} - -@media screen and (forced-colors: active) { - .emotion-1 { - border: solid 0.1875rem transparent; - } -} - -@media (min-width: 25rem) { - .emotion-1 { - margin-inline: 0.5rem; - } -} - -@media (min-width: 37.5rem) { - .emotion-1 { - margin-inline: 0.5rem; - } -} - -@media (min-width: 63rem) { - .emotion-1 { - margin-inline: 0; - } -} - -@media (max-width: 14.9375rem) { - .is-opera-mini .emotion-1 { - margin-inline: 0.5rem; - } -} - -@media (min-width: 25rem) { - .is-opera-mini .emotion-1 { - margin-inline: 1rem; - } -} - -@media (min-width: 63rem) { - .is-opera-mini .emotion-1 { - margin-inline: 0; - } -} - .emotion-2 { display: -webkit-box; display: -webkit-flex; @@ -146,7 +89,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; - margin-inline: 0.25rem; + margin-inline: 0.5rem; } .emotion-2:last-of-type { @@ -161,13 +104,13 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s @media (min-width: 25rem) { .emotion-2 { - margin-inline: 0.5rem; + margin-inline: 1rem; } } @media (min-width: 37.5rem) { .emotion-2 { - margin-inline: 0.5rem; + margin-inline: 1rem; } } @@ -387,13 +330,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } } -@media screen and (forced-colors: active) { - .emotion-0 { - border: solid 0.1875rem transparent; - border-top: transparent; - } -} - .emotion-1 { position: relative; background-color: #FFFFFF; @@ -577,13 +513,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } } -@media screen and (forced-colors: active) { - .emotion-1 { - border: solid 0.1875rem transparent; - border-top: transparent; - } -} - .emotion-2 { position: relative; background-color: #FFFFFF; @@ -718,13 +647,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh } } -@media screen and (forced-colors: active) { - .emotion-0 { - border: solid 0.1875rem transparent; - border-top: transparent; - } -} - .emotion-1 { position: relative; background-color: #E6E8EA; diff --git a/src/app/components/ArticleLinksBlock/index.styles.tsx b/src/app/components/ArticleLinksBlock/index.styles.tsx index 565738a76dc..14633b0236f 100644 --- a/src/app/components/ArticleLinksBlock/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/index.styles.tsx @@ -17,11 +17,6 @@ export default { [mq.GROUP_3_MIN_WIDTH]: { padding: `0 ${spacings.DOUBLE}rem ${spacings.DOUBLE}rem`, }, - - [mq.FORCED_COLOURS]: { - border: `solid ${pixelsToRem(3)}rem transparent`, - borderTop: 'transparent', - }, }), labelComponent: ({ isDarkUi, From f0faa173c21e141f64852b87710b3aaaafe317a7 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 12:06:01 +0000 Subject: [PATCH 077/100] remove a11yattributes from Promolist --- src/app/components/ArticleLinksBlock/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 766966e4c88..e0cb93bae5d 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -78,7 +78,6 @@ const ArticleLinksBlock = ({ blocks={blocksWithoutTitle} viewTracker={viewTracker} clickTracker={clickTracker} - {...a11yAttributes} eventTrackingData={eventTrackingData} /> )} From 8b45d17511207d56e5e7f4715bffe1c4c86cd5f4 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 12:07:55 +0000 Subject: [PATCH 078/100] change div to section and remove as prop --- src/app/components/ArticleLinksBlock/index.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index e0cb93bae5d..b1c1247a30f 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -48,7 +48,6 @@ const ArticleLinksBlock = ({ const ariaLabel = title ? idSanitiser(title) : undefined; const a11yAttributes = { - as: 'section', role: 'region', ...(ariaLabel ? { 'aria-labelledby': ariaLabel } @@ -58,7 +57,7 @@ const ArticleLinksBlock = ({ }; return ( -
    +
    {typeof title === 'string' && title.length > 0 && ( )} -
    +
); }; From 87d55d484349d3440739c1796372c58c9df28058 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 12:16:19 +0000 Subject: [PATCH 079/100] snapshots --- .../__snapshots__/index.test.tsx.snap | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index a5a0d19fed3..c33cce98964 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -201,9 +201,8 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s }
-
@@ -300,7 +299,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s
-
+
`; @@ -393,9 +392,8 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } -
+
`; @@ -576,9 +574,8 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s }
-
@@ -617,7 +614,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s
- + `; @@ -710,9 +707,8 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh }
-
@@ -743,6 +739,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh
- + `; From 188bc939755a3572fa4159d775e94f08dd3082ff Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 13:25:51 +0000 Subject: [PATCH 080/100] update file name --- .../assertions/{scrollablePromo.ts => articleLinksBlock.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/{scrollablePromo.ts => articleLinksBlock.ts} (100%) diff --git a/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.ts b/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/articleLinksBlock.ts similarity index 100% rename from ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/scrollablePromo.ts rename to ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/articleLinksBlock.ts From 2c95208ed41740eafb09f417b8e997f039b0e987 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 13:28:35 +0000 Subject: [PATCH 081/100] update import path and component test names --- ws-nextjs-app/cypress/e2e/articlePage/index.cy.ts | 10 +++++----- .../atiAnalytics/assertions/articleLinksBlock.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ws-nextjs-app/cypress/e2e/articlePage/index.cy.ts b/ws-nextjs-app/cypress/e2e/articlePage/index.cy.ts index 7183bf2233d..45117465dae 100644 --- a/ws-nextjs-app/cypress/e2e/articlePage/index.cy.ts +++ b/ws-nextjs-app/cypress/e2e/articlePage/index.cy.ts @@ -58,9 +58,9 @@ import { assertSocialEmbedComponentView, } from '../specialFeatures/atiAnalytics/assertions/socialEmbed'; import { - assertScrollablePromoComponentClick, - assertScrollablePromoComponentView, -} from '../specialFeatures/atiAnalytics/assertions/scrollablePromo'; + assertArticleLinksBlockComponentClick, + assertArticleLinksBlockComponentView, +} from '../specialFeatures/atiAnalytics/assertions/articleLinksBlock'; import getPathWithSuffix from '../../support/helpers/getPathWithSuffix'; import { assertLiteSiteSummaryComponentToMainSiteClick } from '../specialFeatures/atiAnalytics/assertions/liteSiteSummary'; @@ -381,8 +381,8 @@ const atiAnalyticsTestSuites = [ assertRelatedContentComponentClick, assertTopStoriesComponentView, assertTopStoriesComponentClick, - assertScrollablePromoComponentClick, - assertScrollablePromoComponentView, + assertArticleLinksBlockComponentClick, + assertArticleLinksBlockComponentView, ], }, { diff --git a/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/articleLinksBlock.ts b/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/articleLinksBlock.ts index 94eff227609..84efb0072c1 100644 --- a/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/articleLinksBlock.ts +++ b/ws-nextjs-app/cypress/e2e/specialFeatures/atiAnalytics/assertions/articleLinksBlock.ts @@ -8,7 +8,7 @@ import { AtiAssertionFnProps } from './type'; const { ARTICLE_LINKS_BLOCK } = COMPONENTS; -export const assertScrollablePromoComponentView = ({ +export const assertArticleLinksBlockComponentView = ({ pageIdentifier, contentType, useReverb, @@ -39,7 +39,7 @@ export const assertScrollablePromoComponentView = ({ }); }; -export const assertScrollablePromoComponentClick = ({ +export const assertArticleLinksBlockComponentClick = ({ pageIdentifier, contentType, useReverb, From 291d44b4d837bce0c29043a3cdbad710d993f737 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 13:29:16 +0000 Subject: [PATCH 082/100] remove dir --- src/app/components/ArticleLinksBlock/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index b1c1247a30f..0555a233e45 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -63,7 +63,6 @@ const ArticleLinksBlock = ({ css={styles.labelComponent} id={ariaLabel} data-testid="eoj-recommendations-heading" - dir={dir} > {title}
From 8f091497fd984e99b5f9a05257010dc52d52be42 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 13:42:55 +0000 Subject: [PATCH 083/100] remove operamini detection hook and update styles to use opera mini class --- .../ArticleLinksBlock/Promo/index.styles.tsx | 22 +++++++++---------- .../ArticleLinksBlock/Promo/index.tsx | 6 +---- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx index 5238016e733..90690852b65 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx @@ -1,3 +1,4 @@ +import { OPERA_MINI_CLASSNAME } from '#app/lib/utilities/addOperaMiniClassScript'; import pixelsToRem from '#app/utilities/pixelsToRem'; import { css, Theme } from '@emotion/react'; @@ -21,7 +22,7 @@ export default { color: palette.GREY_6, }, }), - promoBox: ({ isDarkUi, palette, spacings }: Theme) => + promoBox: ({ isDarkUi, mq, palette, spacings }: Theme) => css({ position: 'relative', backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, @@ -30,16 +31,15 @@ export default { height: 'auto', display: 'block', width: '100%', - }), - operaPromoBox: ({ isDarkUi, mq, palette, spacings }: Theme) => - css({ - position: 'relative', - backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, - padding: `${spacings.DOUBLE}rem`, - marginBottom: `${spacings.DOUBLE}rem`, - width: `calc(100% - ${spacings.FULL}rem)`, - [mq.GROUP_2_MIN_WIDTH]: { - width: `calc(50% - ${spacings.DOUBLE}rem)`, + [`.${OPERA_MINI_CLASSNAME} &`]: { + position: 'relative', + backgroundColor: isDarkUi ? palette.GREY_3 : palette.WHITE, + padding: `${spacings.DOUBLE}rem`, + marginBottom: `${spacings.DOUBLE}rem`, + width: `calc(100% - ${spacings.FULL}rem)`, + [mq.GROUP_2_MIN_WIDTH]: { + width: `calc(50% - ${spacings.DOUBLE}rem)`, + }, }, }), timestamp: ({ isDarkUi, palette, spacings }: Theme) => diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index 45206cd5723..e878b845822 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -32,12 +32,8 @@ const Promo = ({ block, clickTracker }: PromoProps) => { const title = textBlock?.model?.blocks?.[0]?.model?.blocks?.[0]?.model?.text ?? ''; - const isOperaMini = useOperaMiniDetection(); - - const promoBoxStyles = isOperaMini ? styles.operaPromoBox : styles.promoBox; - return ( -
+
{title} Date: Thu, 8 Jan 2026 13:46:50 +0000 Subject: [PATCH 084/100] snapshots --- .../__snapshots__/index.test.tsx.snap | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index c33cce98964..63d31042fcb 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -149,6 +149,20 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } +.is-opera-mini .emotion-3 { + position: relative; + background-color: #FFFFFF; + padding: 1rem; + margin-bottom: 1rem; + width: calc(100% - 0.5rem); +} + +@media (min-width: 25rem) { + .is-opera-mini .emotion-3 { + width: calc(50% - 1rem); + } +} + .emotion-4 { font-size: 0.9375rem; line-height: 1.25rem; @@ -209,7 +223,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s Show all links (no images) @@ -340,6 +353,20 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } +.is-opera-mini .emotion-1 { + position: relative; + background-color: #FFFFFF; + padding: 1rem; + margin-bottom: 1rem; + width: calc(100% - 0.5rem); +} + +@media (min-width: 25rem) { + .is-opera-mini .emotion-1 { + width: calc(50% - 1rem); + } +} + .emotion-2 { font-size: 0.9375rem; line-height: 1.25rem; @@ -522,6 +549,20 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } +.is-opera-mini .emotion-2 { + position: relative; + background-color: #FFFFFF; + padding: 1rem; + margin-bottom: 1rem; + width: calc(100% - 0.5rem); +} + +@media (min-width: 25rem) { + .is-opera-mini .emotion-2 { + width: calc(50% - 1rem); + } +} + .emotion-3 { font-size: 0.9375rem; line-height: 1.25rem; @@ -582,7 +623,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s Single link @@ -655,6 +695,20 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh width: 100%; } +.is-opera-mini .emotion-1 { + position: relative; + background-color: #E6E8EA; + padding: 1rem; + margin-bottom: 1rem; + width: calc(100% - 0.5rem); +} + +@media (min-width: 25rem) { + .is-opera-mini .emotion-1 { + width: calc(50% - 1rem); + } +} + .emotion-2 { font-size: 0.9375rem; line-height: 1.25rem; From 43542d1bb0d303b9e4c98845574c74d80c57653c Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 13:55:34 +0000 Subject: [PATCH 085/100] rogue import --- src/app/components/ArticleLinksBlock/Promo/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.tsx b/src/app/components/ArticleLinksBlock/Promo/index.tsx index e878b845822..9676918d455 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.tsx @@ -1,6 +1,5 @@ import { use } from 'react'; import filterForBlockType from '#lib/utilities/blockHandlers'; -import useOperaMiniDetection from '#hooks/useOperaMiniDetection'; import PromoTimestamp from '#components/Promo/timestamp'; import { OptimoBlock } from '#app/models/types/optimo'; import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; From 95d3d0f387a0a7135234d546460cbbfbfd594d94 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 15:01:20 +0000 Subject: [PATCH 086/100] reinstate dir and delete missed code from stories file --- src/app/components/ArticleLinksBlock/index.stories.tsx | 4 ---- src/app/components/ArticleLinksBlock/index.tsx | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.stories.tsx b/src/app/components/ArticleLinksBlock/index.stories.tsx index b8f80c36ec3..611f90734de 100644 --- a/src/app/components/ArticleLinksBlock/index.stories.tsx +++ b/src/app/components/ArticleLinksBlock/index.stories.tsx @@ -89,10 +89,6 @@ export const ArabicText = (_: StoryArgs, { variant }: StoryProps) => ( ); -ArabicText.globals = { - service: { service: 'arabic' }, -}; - export const WithTimestamp = ( _: StoryArgs, { service, variant }: StoryProps, diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 0555a233e45..b1c1247a30f 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -63,6 +63,7 @@ const ArticleLinksBlock = ({ css={styles.labelComponent} id={ariaLabel} data-testid="eoj-recommendations-heading" + dir={dir} > {title} From e47e3156f1a2ce3f80739cefd3573d5ee502044e Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Thu, 8 Jan 2026 15:10:22 +0000 Subject: [PATCH 087/100] snapshots again --- .../ArticleLinksBlock/__snapshots__/index.test.tsx.snap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index 63d31042fcb..8332304d74f 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -223,6 +223,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s Show all links (no images) @@ -623,6 +624,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s Single link From 39f5c890136a408fb564e3e57679fcd95c6c2a21 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Fri, 9 Jan 2026 09:28:47 +0000 Subject: [PATCH 088/100] add skip link button --- .../components/ArticleLinksBlock/index.tsx | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index b1c1247a30f..651153a73b2 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -5,6 +5,7 @@ import useViewTracker from '#hooks/useViewTracker'; import idSanitiser from '#lib/utilities/idSanitiser'; import { OptimoBlock } from '#app/models/types/optimo'; import useClickTrackerHandler from '#app/hooks/useClickTrackerHandler'; +import SkipLinkWrapper from '#app/legacy/components/SkipLinkWrapper'; import { ServiceContext } from '../../contexts/ServiceContext'; import Promo from './Promo'; import PromoList from './PromoList'; @@ -19,7 +20,7 @@ const ArticleLinksBlock = ({ blocks, blockGroupIndex = null, }: ArticleLinksBlockProps) => { - const { dir, translations } = use(ServiceContext); + const { dir, translations, recommendations, service } = use(ServiceContext); const eventTrackingData = { componentName: `edoj${blockGroupIndex}`, @@ -56,18 +57,38 @@ const ArticleLinksBlock = ({ }), }; + const { skipLink } = recommendations || {}; + + const { text, endTextVisuallyHidden } = skipLink || { + text: 'Skip content and continue reading', + endTextVisuallyHidden: 'End of content', + }; + + const terms = { '%title%': title || 'content' }; + + const endTextId = `end-of-article-links-block`; + + const skipLinkProps = { + endTextId, + terms, + text: text.replace('%title%', terms['%title%']), + endTextVisuallyHidden, + }; + return (
- {typeof title === 'string' && title.length > 0 && ( - - {title} - - )} + + {typeof title === 'string' && title.length > 0 && ( + + {title} + + )} + {isSingleItem ? (
From bbd582bca89f8c8ec8a3b3431fe02bca41df1aa1 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Fri, 9 Jan 2026 10:26:28 +0000 Subject: [PATCH 089/100] small tweak to fix focus box --- src/app/components/ArticleLinksBlock/Promo/index.styles.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx index 90690852b65..c0f7446da12 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx @@ -7,8 +7,7 @@ export default { css({ ...fontSizes.pica, ...fontVariants.serifBold, - display: 'webkit-box', - width: '100%', + display: 'inline-block', textDecoration: 'none', overflowX: 'hidden', overflowY: 'hidden', From e3d2ba6c265a200e0e555601fb7eff97c39f0534 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Fri, 9 Jan 2026 11:49:46 +0000 Subject: [PATCH 090/100] update bundle threshhold --- scripts/bundleSize/bundleSizeConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bundleSize/bundleSizeConfig.js b/scripts/bundleSize/bundleSizeConfig.js index f739f087d5d..309ec3f9d0b 100644 --- a/scripts/bundleSize/bundleSizeConfig.js +++ b/scripts/bundleSize/bundleSizeConfig.js @@ -9,5 +9,5 @@ export const VARIANCE = 5; -export const MIN_SIZE = 922; +export const MIN_SIZE = 921; export const MAX_SIZE = 1292; From 5ac405998a4d061fec31fb7e096d46a159ca3e1e Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Fri, 9 Jan 2026 11:59:48 +0000 Subject: [PATCH 091/100] snapshots again --- .../__snapshots__/index.test.tsx.snap | 534 ++++++++++++++---- 1 file changed, 419 insertions(+), 115 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index 8332304d74f..e9af54b7136 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -2,6 +2,55 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y snapshot for list 1`] = ` .emotion-0 { + position: relative; +} + +.emotion-2 { + font-family: ReithSans,Helvetica,Arial,sans-serif; + font-style: normal; + font-weight: 700; + font-size: 0.875rem; + line-height: 1.125rem; + background-color: #FFFFFF; + border: 0.125rem solid #222222; + color: #222222; + display: block; + left: 0; + line-height: 1; + padding: 0.75rem; + position: absolute; + -webkit-text-decoration: none; + text-decoration: none; + top: 0; + z-index: 10; +} + +@media (min-width: 20rem) and (max-width: 37.4375rem) { + .emotion-2 { + font-size: 0.875rem; + line-height: 1.125rem; + } +} + +@media (min-width: 37.5rem) { + .emotion-2 { + font-size: 0.8125rem; + line-height: 1rem; + } +} + +.emotion-2:not(:focus):not(:active) { + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + clip: rect(1px, 1px, 1px, 1px); + height: 1px; + overflow: hidden; + position: absolute; + width: 1px; + margin: 0; +} + +.emotion-4 { font-size: 0.875rem; line-height: 1.125rem; font-family: ReithSans,Helvetica,Arial,sans-serif; @@ -23,42 +72,53 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-0 { + .emotion-4 { font-size: 0.875rem; line-height: 1.125rem; } } @media (min-width: 37.5rem) { - .emotion-0 { + .emotion-4 { font-size: 0.8125rem; line-height: 1rem; } } @media screen and (forced-colors: active) { - .emotion-0 { + .emotion-4 { border: solid 0.1875rem transparent; border-bottom: transparent; } } @media (max-width: 14.9375rem) { - .emotion-0 { + .emotion-4 { margin-inline: 0.5rem; margin: 0; } } @media (min-width: 25rem) { - .emotion-0 { + .emotion-4 { margin-inline: 1rem; padding: 0 1rem; margin: 0 -0.2rem; } } -.emotion-1 ul { +.emotion-5 { + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + clip: rect(1px, 1px, 1px, 1px); + height: 1px; + overflow: hidden; + position: absolute; + width: 1px; + margin: 0; +} + +.emotion-7 ul { list-style: none; -webkit-padding-start: 0; padding-inline-start: 0; @@ -74,14 +134,14 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.is-opera-mini .emotion-1 { +.is-opera-mini .emotion-7 { list-style: none; -webkit-padding-start: 0; padding-inline-start: 0; margin: 0; } -.emotion-2 { +.emotion-8 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -92,53 +152,53 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s margin-inline: 0.5rem; } -.emotion-2:last-of-type { +.emotion-8:last-of-type { margin-bottom: 1.5rem; } @media screen and (forced-colors: active) { - .emotion-2 { + .emotion-8 { border: solid 0.1875rem transparent; } } @media (min-width: 25rem) { - .emotion-2 { + .emotion-8 { margin-inline: 1rem; } } @media (min-width: 37.5rem) { - .emotion-2 { + .emotion-8 { margin-inline: 1rem; } } @media (min-width: 63rem) { - .emotion-2 { + .emotion-8 { margin-inline: 0; } } @media (max-width: 14.9375rem) { - .is-opera-mini .emotion-2 { + .is-opera-mini .emotion-8 { margin-inline: 0.5rem; } } @media (min-width: 25rem) { - .is-opera-mini .emotion-2 { + .is-opera-mini .emotion-8 { margin-inline: 1rem; } } @media (min-width: 63rem) { - .is-opera-mini .emotion-2 { + .is-opera-mini .emotion-8 { margin-inline: 0; } } -.emotion-3 { +.emotion-9 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -149,7 +209,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.is-opera-mini .emotion-3 { +.is-opera-mini .emotion-9 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -158,19 +218,18 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 25rem) { - .is-opera-mini .emotion-3 { + .is-opera-mini .emotion-9 { width: calc(50% - 1rem); } } -.emotion-4 { +.emotion-10 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; font-style: normal; font-weight: 700; - display: webkit-box; - width: 100%; + display: inline-block; -webkit-text-decoration: none; text-decoration: none; overflow-x: hidden; @@ -181,30 +240,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-4 { + .emotion-10 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-4 { + .emotion-10 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-4:hover, -.emotion-4:focus { +.emotion-10:hover, +.emotion-10:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-4:visited { +.emotion-10:visited { color: #545658; } -.emotion-5 { +.emotion-11 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -220,33 +279,50 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s data-e2e="article-links-block" role="region" > - - Show all links (no images) - + + Skip content and continue reading + + + Show all links (no images) + +

+ End of content +

+
From a747926775359ee191ce3e596743f8d8139c509a Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Fri, 9 Jan 2026 14:45:40 +0000 Subject: [PATCH 096/100] rename files from js to ts --- src/app/components/ArticleLinksBlock/{fixtures.js => fixtures.ts} | 0 .../ArticleLinksBlock/helpers/{fixtureData.js => fixtureData.ts} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/app/components/ArticleLinksBlock/{fixtures.js => fixtures.ts} (100%) rename src/app/components/ArticleLinksBlock/helpers/{fixtureData.js => fixtureData.ts} (100%) diff --git a/src/app/components/ArticleLinksBlock/fixtures.js b/src/app/components/ArticleLinksBlock/fixtures.ts similarity index 100% rename from src/app/components/ArticleLinksBlock/fixtures.js rename to src/app/components/ArticleLinksBlock/fixtures.ts diff --git a/src/app/components/ArticleLinksBlock/helpers/fixtureData.js b/src/app/components/ArticleLinksBlock/helpers/fixtureData.ts similarity index 100% rename from src/app/components/ArticleLinksBlock/helpers/fixtureData.js rename to src/app/components/ArticleLinksBlock/helpers/fixtureData.ts From c12ccc73a06959283390a3d44289850a7beb7690 Mon Sep 17 00:00:00 2001 From: Louise Archibald Date: Fri, 9 Jan 2026 17:50:31 +0000 Subject: [PATCH 097/100] tweak to skip link --- .../components/ArticleLinksBlock/index.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 2fc73fb7474..993aaea0635 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -87,18 +87,18 @@ const ArticleLinksBlock = ({ {title} )} + {isSingleItem ? ( +
+ +
+ ) : ( + + )} - {isSingleItem ? ( -
- -
- ) : ( - - )} ); }; From 9fab77305b666bfbb6544a80cf9fbd6681071bad Mon Sep 17 00:00:00 2001 From: Aaron Moore Date: Mon, 12 Jan 2026 10:02:11 +0000 Subject: [PATCH 098/100] Update index.test.tsx.snap --- .../__snapshots__/index.test.tsx.snap | 526 +++++++++--------- 1 file changed, 263 insertions(+), 263 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index 51b2fa0ff3b..2453fc83a72 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -107,18 +107,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } } -.emotion-5 { - -webkit-clip-path: inset(100%); - clip-path: inset(100%); - clip: rect(1px, 1px, 1px, 1px); - height: 1px; - overflow: hidden; - position: absolute; - width: 1px; - margin: 0; -} - -.emotion-7 ul { +.emotion-5 ul { list-style: none; -webkit-padding-start: 0; padding-inline-start: 0; @@ -134,14 +123,14 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.is-opera-mini .emotion-7 { +.is-opera-mini .emotion-5 { list-style: none; -webkit-padding-start: 0; padding-inline-start: 0; margin: 0; } -.emotion-8 { +.emotion-6 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -152,53 +141,53 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s margin-inline: 0.5rem; } -.emotion-8:last-of-type { +.emotion-6:last-of-type { margin-bottom: 1.5rem; } @media screen and (forced-colors: active) { - .emotion-8 { + .emotion-6 { border: solid 0.1875rem transparent; } } @media (min-width: 25rem) { - .emotion-8 { + .emotion-6 { margin-inline: 1rem; } } @media (min-width: 37.5rem) { - .emotion-8 { + .emotion-6 { margin-inline: 1rem; } } @media (min-width: 63rem) { - .emotion-8 { + .emotion-6 { margin-inline: 0; } } @media (max-width: 14.9375rem) { - .is-opera-mini .emotion-8 { + .is-opera-mini .emotion-6 { margin-inline: 0.5rem; } } @media (min-width: 25rem) { - .is-opera-mini .emotion-8 { + .is-opera-mini .emotion-6 { margin-inline: 1rem; } } @media (min-width: 63rem) { - .is-opera-mini .emotion-8 { + .is-opera-mini .emotion-6 { margin-inline: 0; } } -.emotion-9 { +.emotion-7 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -209,7 +198,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.is-opera-mini .emotion-9 { +.is-opera-mini .emotion-7 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -218,12 +207,12 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 25rem) { - .is-opera-mini .emotion-9 { + .is-opera-mini .emotion-7 { width: calc(50% - 1rem); } } -.emotion-10 { +.emotion-8 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; @@ -241,30 +230,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-10 { + .emotion-8 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-10 { + .emotion-8 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-10:hover, -.emotion-10:focus { +.emotion-8:hover, +.emotion-8:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-10:visited { +.emotion-8:visited { color: #545658; } -.emotion-11 { +.emotion-9 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -274,6 +263,17 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s inset-inline-end: 0.75rem; } +.emotion-18 { + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + clip: rect(1px, 1px, 1px, 1px); + height: 1px; + overflow: hidden; + position: absolute; + width: 1px; + margin: 0; +} +
- - -
  • - +
  • +
  • - - Link with Headline - - -
  • Show all links (no images) -

    - End of content -

    -
    - -
  • - +
  • +
  • - - Brasil homepage - - -
  • - - + Brasil homepage + + + + + + +

    + End of content +

    @@ -443,17 +443,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } .emotion-4 { - -webkit-clip-path: inset(100%); - clip-path: inset(100%); - clip: rect(1px, 1px, 1px, 1px); - height: 1px; - overflow: hidden; - position: absolute; - width: 1px; - margin: 0; -} - -.emotion-6 { background: #F6F6F6; padding: 0 0.5rem 1rem; margin: 0; @@ -466,19 +455,19 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 25rem) { - .emotion-6 { + .emotion-4 { padding: 0 1rem 1rem; margin: 0 -0.2rem; } } @media (min-width: 37.5rem) { - .emotion-6 { + .emotion-4 { padding: 0 1rem 1rem; } } -.emotion-7 { +.emotion-5 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -489,7 +478,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.is-opera-mini .emotion-7 { +.is-opera-mini .emotion-5 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -498,12 +487,12 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 25rem) { - .is-opera-mini .emotion-7 { + .is-opera-mini .emotion-5 { width: calc(50% - 1rem); } } -.emotion-8 { +.emotion-6 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; @@ -521,30 +510,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-8 { + .emotion-6 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-8 { + .emotion-6 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-8:hover, -.emotion-8:focus { +.emotion-6:hover, +.emotion-6:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-8:visited { +.emotion-6:visited { color: #545658; } -.emotion-9 { +.emotion-7 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -554,6 +543,17 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s inset-inline-end: 0.75rem; } +.emotion-8 { + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + clip: rect(1px, 1px, 1px, 1px); + height: 1px; + overflow: hidden; + position: absolute; + width: 1px; + margin: 0; +} +
    Skip content and continue reading +

    End of content

    - `; @@ -715,17 +715,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } .emotion-5 { - -webkit-clip-path: inset(100%); - clip-path: inset(100%); - clip: rect(1px, 1px, 1px, 1px); - height: 1px; - overflow: hidden; - position: absolute; - width: 1px; - margin: 0; -} - -.emotion-7 { background: #F6F6F6; padding: 0 0.5rem 1rem; margin: 0; @@ -738,19 +727,19 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 25rem) { - .emotion-7 { + .emotion-5 { padding: 0 1rem 1rem; margin: 0 -0.2rem; } } @media (min-width: 37.5rem) { - .emotion-7 { + .emotion-5 { padding: 0 1rem 1rem; } } -.emotion-8 { +.emotion-6 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -761,7 +750,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s width: 100%; } -.is-opera-mini .emotion-8 { +.is-opera-mini .emotion-6 { position: relative; background-color: #FFFFFF; padding: 1rem; @@ -770,12 +759,12 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 25rem) { - .is-opera-mini .emotion-8 { + .is-opera-mini .emotion-6 { width: calc(50% - 1rem); } } -.emotion-9 { +.emotion-7 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; @@ -793,30 +782,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-9 { + .emotion-7 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-9 { + .emotion-7 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-9:hover, -.emotion-9:focus { +.emotion-7:hover, +.emotion-7:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-9:visited { +.emotion-7:visited { color: #545658; } -.emotion-10 { +.emotion-8 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -826,6 +815,17 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s inset-inline-end: 0.75rem; } +.emotion-9 { + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + clip: rect(1px, 1px, 1px, 1px); + height: 1px; + overflow: hidden; + position: absolute; + width: 1px; + margin: 0; +} +
    Single link +

    End of content

    - `; @@ -937,17 +937,6 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh } .emotion-4 { - -webkit-clip-path: inset(100%); - clip-path: inset(100%); - clip: rect(1px, 1px, 1px, 1px); - height: 1px; - overflow: hidden; - position: absolute; - width: 1px; - margin: 0; -} - -.emotion-6 { background: #F6F6F6; padding: 0 0.5rem 1rem; margin: 0; @@ -960,19 +949,19 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh } @media (min-width: 25rem) { - .emotion-6 { + .emotion-4 { padding: 0 1rem 1rem; margin: 0 -0.2rem; } } @media (min-width: 37.5rem) { - .emotion-6 { + .emotion-4 { padding: 0 1rem 1rem; } } -.emotion-7 { +.emotion-5 { position: relative; background-color: #E6E8EA; padding: 1rem; @@ -983,7 +972,7 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh width: 100%; } -.is-opera-mini .emotion-7 { +.is-opera-mini .emotion-5 { position: relative; background-color: #E6E8EA; padding: 1rem; @@ -992,12 +981,12 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh } @media (min-width: 25rem) { - .is-opera-mini .emotion-7 { + .is-opera-mini .emotion-5 { width: calc(50% - 1rem); } } -.emotion-8 { +.emotion-6 { font-size: 0.9375rem; line-height: 1.25rem; font-family: ReithSerif,Helvetica,Arial,sans-serif; @@ -1015,30 +1004,30 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh } @media (min-width: 20rem) and (max-width: 37.4375rem) { - .emotion-8 { + .emotion-6 { font-size: 1rem; line-height: 1.25rem; } } @media (min-width: 37.5rem) { - .emotion-8 { + .emotion-6 { font-size: 1rem; line-height: 1.25rem; } } -.emotion-8:hover, -.emotion-8:focus { +.emotion-6:hover, +.emotion-6:focus { -webkit-text-decoration: underline; text-decoration: underline; } -.emotion-8:visited { +.emotion-6:visited { color: #545658; } -.emotion-9 { +.emotion-7 { position: absolute; top: 50%; -webkit-transform: translateY(-50%); @@ -1048,6 +1037,17 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh inset-inline-end: 0.75rem; } +.emotion-8 { + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + clip: rect(1px, 1px, 1px, 1px); + height: 1px; + overflow: hidden; + position: absolute; + width: 1px; + margin: 0; +} +
    Skip content and continue reading +

    End of content

    - `; From 4b00570749e5511ac1b52d7219316c37fd8d4d5a Mon Sep 17 00:00:00 2001 From: Aaron Moore Date: Mon, 12 Jan 2026 10:03:15 +0000 Subject: [PATCH 099/100] Remove `ramda` uses --- src/app/components/ArticleLinksBlock/index.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/app/components/ArticleLinksBlock/index.tsx b/src/app/components/ArticleLinksBlock/index.tsx index 993aaea0635..99243a22d87 100644 --- a/src/app/components/ArticleLinksBlock/index.tsx +++ b/src/app/components/ArticleLinksBlock/index.tsx @@ -1,6 +1,4 @@ import { use } from 'react'; -import isEmpty from 'ramda/src/isEmpty'; -import tail from 'ramda/src/tail'; import useViewTracker from '#hooks/useViewTracker'; import idSanitiser from '#lib/utilities/idSanitiser'; import { OptimoBlock } from '#app/models/types/optimo'; @@ -30,9 +28,7 @@ const ArticleLinksBlock = ({ const viewTracker = useViewTracker(eventTrackingData); const clickTracker = useClickTrackerHandler(eventTrackingData); - if (!blocks || isEmpty(blocks)) { - return null; - } + if (!blocks || blocks.length === 0) return null; const title = blocks[0]?.type === 'title' @@ -42,7 +38,7 @@ const ArticleLinksBlock = ({ : undefined; const blocksWithoutTitle = - blocks[0]?.type === 'title' ? tail(blocks) : blocks; + blocks[0]?.type === 'title' ? blocks.slice(1) : blocks; const isSingleItem = blocksWithoutTitle.length === 1; From f401b2b17e0e807e0e2ddd3e8e42eb5af23bdb67 Mon Sep 17 00:00:00 2001 From: Aaron Moore Date: Mon, 12 Jan 2026 10:19:11 +0000 Subject: [PATCH 100/100] Add `::before` pseudo class to link to allow hovering/focusing on entire element --- .../ArticleLinksBlock/Promo/index.styles.tsx | 15 ++++++- .../__snapshots__/index.test.tsx.snap | 44 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx index 94d9f7af375..5c77dfa05ce 100644 --- a/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx +++ b/src/app/components/ArticleLinksBlock/Promo/index.styles.tsx @@ -14,13 +14,26 @@ export default { overflowY: 'hidden', WebkitLineClamp: 4, WebkitBoxOrient: 'vertical', + color: isDarkUi ? palette.GREY_10 : palette.GREY_8, + '&:hover, &:focus': { textDecoration: 'underline', }, - color: isDarkUi ? palette.GREY_10 : palette.GREY_8, + '&:visited': { color: palette.GREY_6, }, + + '&::before': { + bottom: 0, + content: '""', + left: 0, + overflow: 'hidden', + position: 'absolute', + right: 0, + top: 0, + zIndex: 1, + }, }), promoBox: ({ isDarkUi, mq, palette, spacings }: Theme) => css({ diff --git a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap index 2453fc83a72..8a55fd91be0 100644 --- a/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap +++ b/src/app/components/ArticleLinksBlock/__snapshots__/index.test.tsx.snap @@ -253,6 +253,17 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s color: #545658; } +.emotion-8::before { + bottom: 0; + content: ""; + left: 0; + overflow: hidden; + position: absolute; + right: 0; + top: 0; + z-index: 1; +} + .emotion-9 { position: absolute; top: 50%; @@ -533,6 +544,17 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s color: #545658; } +.emotion-6::before { + bottom: 0; + content: ""; + left: 0; + overflow: hidden; + position: absolute; + right: 0; + top: 0; + z-index: 1; +} + .emotion-7 { position: absolute; top: 50%; @@ -805,6 +827,17 @@ exports[`Article Links Block Mid Page Article Links Block it should match a11y s color: #545658; } +.emotion-7::before { + bottom: 0; + content: ""; + left: 0; + overflow: hidden; + position: absolute; + right: 0; + top: 0; + z-index: 1; +} + .emotion-8 { position: absolute; top: 50%; @@ -1027,6 +1060,17 @@ exports[`Article Links Block Mid Page Article Links Block it should match snapsh color: #545658; } +.emotion-6::before { + bottom: 0; + content: ""; + left: 0; + overflow: hidden; + position: absolute; + right: 0; + top: 0; + z-index: 1; +} + .emotion-7 { position: absolute; top: 50%;