From e3ef1f7d93e6e96aa9fcdc9608172c8b933b7fb6 Mon Sep 17 00:00:00 2001 From: hotinglok Date: Tue, 11 Aug 2026 15:25:09 +0100 Subject: [PATCH 1/2] Use title as visible headline, rmeove visually hidden h1 --- .../[service]/live/[id]/Header/index.test.tsx | 14 ----- .../[service]/live/[id]/LivePageLayout.tsx | 18 +++++++ .../pages/[service]/live/[id]/live.test.tsx | 51 +++++++++++++++++-- .../pages/[service]/live/[id]/styles.ts | 14 +++++ 4 files changed, 78 insertions(+), 19 deletions(-) diff --git a/ws-nextjs-app/pages/[service]/live/[id]/Header/index.test.tsx b/ws-nextjs-app/pages/[service]/live/[id]/Header/index.test.tsx index bc3731aef3e..42ebeed7eda 100644 --- a/ws-nextjs-app/pages/[service]/live/[id]/Header/index.test.tsx +++ b/ws-nextjs-app/pages/[service]/live/[id]/Header/index.test.tsx @@ -120,19 +120,5 @@ describe('Live Page Header', () => { expect(tabIndex).toEqual('-1'); }); - it('should render a translated match summary H2 for sport data headers', async () => { - await act(async () => { - render(
, { - service: 'afaanoromoo', - }); - }); - - expect( - screen.getByRole('heading', { - level: 2, - name: 'Cuunfaa Taphaa', - }), - ).toBeInTheDocument(); - }); }); }); diff --git a/ws-nextjs-app/pages/[service]/live/[id]/LivePageLayout.tsx b/ws-nextjs-app/pages/[service]/live/[id]/LivePageLayout.tsx index ed458ee24d1..97e9b6baa4c 100644 --- a/ws-nextjs-app/pages/[service]/live/[id]/LivePageLayout.tsx +++ b/ws-nextjs-app/pages/[service]/live/[id]/LivePageLayout.tsx @@ -14,6 +14,8 @@ import { HeadToHeadV2Data } from '#app/components-webcore/SportDataHeader/head-t import { PortraitVideoItems } from '#app/models/types/optimo'; import useLivePagePolling from '#app/hooks/useLivePagePolling'; import useToggle from '#app/hooks/useToggle'; +import Heading from '#app/components/Heading'; +import VisuallyHiddenText from '#app/components/VisuallyHiddenText'; import { getImageFromPost, getHeadlineFromPost, @@ -113,6 +115,8 @@ const LivePage = ({ pageData, assetId }: LivePageProps) => { sportDataEventContent || {}; const showSportData = !!sportData && Boolean(sportHeaderEnabled); + const matchSummary = translations.sport?.matchSummary ?? 'Match Summary'; + const { url: imageUrl, urlTemplate: imageUrlTemplate, @@ -228,6 +232,20 @@ const LivePage = ({ pageData, assetId }: LivePageProps) => { /> )}
+ {showSportData && ( + <> + + {title} + + {matchSummary} + + )}
{keyPoints && ( diff --git a/ws-nextjs-app/pages/[service]/live/[id]/live.test.tsx b/ws-nextjs-app/pages/[service]/live/[id]/live.test.tsx index d110e805aea..c4555f7a699 100644 --- a/ws-nextjs-app/pages/[service]/live/[id]/live.test.tsx +++ b/ws-nextjs-app/pages/[service]/live/[id]/live.test.tsx @@ -817,7 +817,7 @@ describe('Live Page', () => { expect(title).toBeInTheDocument(); }); - it('should render a visually hidden h1 when displaying sportData', async () => { + it('should render the title as the only visible h1 when displaying sportData', async () => { const pageDataWithSportData = { ...mockPageData, sportDataEventContent: sportDataFixture.data.sportDataEventContent, @@ -828,15 +828,56 @@ describe('Live Page', () => { render(); }); - const visuallyHiddenTitle = screen.getByText( - 'Israeli tanks shell Jabalia camp as heavy fighting continues in north Gaza', // mock data, in production this would be a sport title + const title = screen.getByRole('heading', { + level: 1, + name: 'Israeli tanks shell Jabalia camp as heavy fighting continues in north Gaza', // mock data, in production this would be a sport title + }); + expect(title).toBeInTheDocument(); + expect(title).not.toHaveStyle( + 'overflow: hidden; position: absolute; width: 1px;', ); - expect(visuallyHiddenTitle).toBeInTheDocument(); - expect(visuallyHiddenTitle).toHaveStyle( + }); + + it('should render a translated visually hidden match summary h2 below the h1 when displaying sportData', async () => { + const pageDataWithSportData = { + ...mockPageData, + sportDataEventContent: sportDataFixture.data.sportDataEventContent, + } as unknown as ComponentProps['pageData']; + mockPollingUpdate(pageDataWithSportData); + + await act(async () => { + render(, { + service: 'afaanoromoo', + }); + }); + + const matchSummary = screen.getByRole('heading', { + level: 2, + name: 'Cuunfaa Taphaa', + }); + expect(matchSummary).toHaveStyle( 'overflow: hidden; position: absolute; width: 1px;', ); }); + it('should render the sport banner before the headings grid in the DOM order when displaying sportData', async () => { + const pageDataWithSportData = { + ...mockPageData, + sportDataEventContent: sportDataFixture.data.sportDataEventContent, + } as unknown as ComponentProps['pageData']; + mockPollingUpdate(pageDataWithSportData); + + const { container } = await act(async () => { + return render(); + }); + + const domOrder = Array.from( + container.querySelectorAll('h1, [data-testid="head-to-head-v2"]'), + ); + expect(domOrder[0]).toHaveAttribute('data-testid', 'head-to-head-v2'); + expect(domOrder[1].tagName).toBe('H1'); + }); + it('should not render HeadToHeadV2 when sportDataEventContent is not present', async () => { mockPollingUpdate(mockPageData); diff --git a/ws-nextjs-app/pages/[service]/live/[id]/styles.ts b/ws-nextjs-app/pages/[service]/live/[id]/styles.ts index 18cd602007a..501dd718470 100644 --- a/ws-nextjs-app/pages/[service]/live/[id]/styles.ts +++ b/ws-nextjs-app/pages/[service]/live/[id]/styles.ts @@ -8,6 +8,20 @@ export default { maxWidth: `${pixelsToRem(1008)}rem`, margin: `${pixelsToRem(20)}rem auto`, }), + heading: ({ mq }: Theme) => + css({ + gridColumn: '1 / 13', + textAlign: 'start', + '&:focus': { + outline: 'none', + }, + marginBottom: '1rem', + + [mq.GROUP_2_MAX_WIDTH]: { + fontSize: '2rem', + lineHeight: '2.625rem', + }, + }), outerGrid: ({ mq, gridWidths, spacings }: Theme) => css({ maxWidth: `${pixelsToRem(gridWidths[1280])}rem`, From 1a548234c88de4758796d73acc7105c4dfa1fecd Mon Sep 17 00:00:00 2001 From: hotinglok Date: Tue, 11 Aug 2026 16:58:07 +0100 Subject: [PATCH 2/2] Change visible headline to h2, remove unnecessary match summary duplicate --- .../[service]/live/[id]/LivePageLayout.tsx | 21 ++++++++----------- .../pages/[service]/live/[id]/styles.ts | 7 +------ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/ws-nextjs-app/pages/[service]/live/[id]/LivePageLayout.tsx b/ws-nextjs-app/pages/[service]/live/[id]/LivePageLayout.tsx index 97e9b6baa4c..440f91fddb9 100644 --- a/ws-nextjs-app/pages/[service]/live/[id]/LivePageLayout.tsx +++ b/ws-nextjs-app/pages/[service]/live/[id]/LivePageLayout.tsx @@ -233,18 +233,15 @@ const LivePage = ({ pageData, assetId }: LivePageProps) => { )}
{showSportData && ( - <> - - {title} - - {matchSummary} - + + {title} + )}
{keyPoints && ( diff --git a/ws-nextjs-app/pages/[service]/live/[id]/styles.ts b/ws-nextjs-app/pages/[service]/live/[id]/styles.ts index 501dd718470..f994d22239c 100644 --- a/ws-nextjs-app/pages/[service]/live/[id]/styles.ts +++ b/ws-nextjs-app/pages/[service]/live/[id]/styles.ts @@ -8,7 +8,7 @@ export default { maxWidth: `${pixelsToRem(1008)}rem`, margin: `${pixelsToRem(20)}rem auto`, }), - heading: ({ mq }: Theme) => + heading: () => css({ gridColumn: '1 / 13', textAlign: 'start', @@ -16,11 +16,6 @@ export default { outline: 'none', }, marginBottom: '1rem', - - [mq.GROUP_2_MAX_WIDTH]: { - fontSize: '2rem', - lineHeight: '2.625rem', - }, }), outerGrid: ({ mq, gridWidths, spacings }: Theme) => css({