From 55aa09ebaef8e124803b7dea271d520c8be13fff Mon Sep 17 00:00:00 2001 From: Dominik Lander Date: Thu, 26 Feb 2026 16:54:53 +0000 Subject: [PATCH 1/4] Render Most Viewed on right if in test --- ab-testing/config/abTests.ts | 2 +- .../src/components/FrontSection.tsx | 85 ++++++++++++++++++- .../src/components/MostPopularFrontRight.tsx | 2 + .../src/components/MostViewedFooterItem.tsx | 2 +- dotcom-rendering/src/layouts/FrontLayout.tsx | 38 ++++++++- 5 files changed, 123 insertions(+), 6 deletions(-) diff --git a/ab-testing/config/abTests.ts b/ab-testing/config/abTests.ts index 0b54a2036d6..9730cc14e56 100644 --- a/ab-testing/config/abTests.ts +++ b/ab-testing/config/abTests.ts @@ -112,7 +112,7 @@ const ABTests: ABTest[] = [ description: "Test placing the Most Viewed and Deeply Read components in the right-hand column on the homepage.", owners: ["fronts.and.curation@guardian.co.uk"], - status: "OFF", + status: "ON", expirationDate: `2026-04-28`, type: "server", audienceSize: 0 / 100, diff --git a/dotcom-rendering/src/components/FrontSection.tsx b/dotcom-rendering/src/components/FrontSection.tsx index 747232f9cdc..a971a98ff09 100644 --- a/dotcom-rendering/src/components/FrontSection.tsx +++ b/dotcom-rendering/src/components/FrontSection.tsx @@ -14,14 +14,17 @@ import type { } from '../types/front'; import type { TagPagePagination } from '../types/tagPage'; import { isAustralianTerritory, type Territory } from '../types/territory'; +import type { TrailType } from '../types/trails'; import { AustralianTerritorySwitcher } from './AustralianTerritorySwitcher.importable'; import { BrandingLabel } from './BrandingLabel'; import { ContainerOverrides } from './ContainerOverrides'; import { ContainerTitle } from './ContainerTitle'; import { FrontPagination } from './FrontPagination'; import { FrontSectionTitle } from './FrontSectionTitle'; +import { Hide } from './Hide'; import { Island } from './Island'; import { LabsSectionHeader } from './LabsSectionHeader'; +import { MostPopularFrontRight } from './MostPopularFrontRight'; import { ShowHideButton } from './ShowHideButton'; import { ShowMore } from './ShowMore.importable'; import { Treats } from './Treats'; @@ -90,6 +93,11 @@ type Props = { * the page skin background showing through the containers */ hasPageSkin?: boolean; + /** + * The Slim Homepage AB test requires some sections to have reduced width so that + * the Most Popular Front Right component can be placed on the right-hand side. + */ + slimifySectionForAbTest?: boolean; discussionApiUrl: string; collectionBranding?: CollectionBranding; isTagPage?: boolean; @@ -98,6 +106,8 @@ type Props = { isAboveMobileAd?: boolean; /** Indicates whether this is a Guardian Labs container */ isLabs?: boolean; + mostViewed?: TrailType[]; + deeplyRead?: TrailType[]; }; const width = (columns: number, columnWidth: number, columnGap: number) => @@ -354,14 +364,17 @@ const sectionControls = css` } `; -const sectionContent = css` +const sectionContent = (isInSlimHomepageTestVariant: boolean) => css` margin: 0; + grid-column: content; .hidden > & { display: none; } - grid-column: content; + ${from.wide} { + grid-column: ${isInSlimHomepageTestVariant ? '5 / 14' : 'content'}; + } `; const sectionContentRow = (toggleable: boolean) => css` @@ -391,6 +404,22 @@ const sectionContentBorderFromLeftCol = css` } `; +const slimHomepageRightBorderStyles = css` + ${from.wide} { + ::after { + content: ''; + position: absolute; + top: ${space[2]}px; + bottom: 0; + right: 0; + border-right: 1px solid ${schemePalette('--section-border')}; + transform: translateX(-50%); + /** Keeps the vertical divider ontop of carousel item dividers */ + z-index: 1; + } + } +`; + const sectionBottomContent = css` grid-row: bottom-content; grid-column: content; @@ -619,6 +648,7 @@ export const FrontSection = ({ isOnPaidContentFront, targetedTerritory, hasPageSkin = false, + slimifySectionForAbTest = false, discussionApiUrl, collectionBranding, isTagPage = false, @@ -626,6 +656,8 @@ export const FrontSection = ({ isAboveDesktopAd = false, isAboveMobileAd = false, isLabs = false, + mostViewed = [], + deeplyRead = [], }: Props) => { const isToggleable = toggleable && !!sectionId; const showVerticalRule = !hasPageSkin; @@ -690,6 +722,15 @@ export const FrontSection = ({ title, showSectionColours, ), + // To reduce the width of the border line between Features + // and More features in the Slim Homepage AB test. + slimifySectionForAbTest && + sectionId === 'more-features' && + css` + ${from.wide} { + grid-column: 2 / 14; + } + `, ]} /> )} @@ -783,19 +824,57 @@ export const FrontSection = ({
{children}
+ {slimifySectionForAbTest && sectionId === 'news' && ( +
+ + + +
+ )} + + {slimifySectionForAbTest && sectionId === 'features' && ( +
+ + + +
+ )} +
-
+
{format.design === ArticleDesign.LiveBlog ? ( { const isHighlights = ({ collectionType }: DCRCollectionType) => collectionType === 'scrollable/highlights'; +const isMostPopular = ({ collectionType }: DCRCollectionType) => + collectionType === 'news/most-popular'; + const isLabs = ({ containerPalette }: DCRCollectionType) => containerPalette === 'Branded'; @@ -138,6 +142,23 @@ export const FrontLayout = ({ front, NAV }: Props) => { const contributionsServiceUrl = getContributionsServiceUrl(front); + const abTests = useBetaAB(); + + /** + * The Slim Homepage AB test only runs on /uk and on screen widths >=1300px. + * In the variant of this test a Most Popular component is added to the right-hand side of the page. + * Page skins require slim content and is incompatible with this test. We do not run this test + * on pages where there is a page skin (a page skin takes precedence). + */ + const isInSlimHomepageAbTestVariant = + (pageId === 'uk' && + !hasPageSkin && + abTests?.isUserInTestGroup( + 'fronts-and-curation-slim-homepage', + 'variant', + )) ?? + false; + const fallbackAspectRatio = (collectionType: DCRContainerType) => { switch (collectionType) { case 'scrollable/feature': @@ -278,6 +299,15 @@ export const FrontLayout = ({ front, NAV }: Props) => { } | ${ophanName}`; const mostPopularTitle = 'Most popular'; + /** + * We only shrink the content of certain sections to place the Most Popular + * content on the right-hand side. Other sections remain full-width. + */ + const isTargetedContainerInSlimHomepageAbTest = + collection.displayName === 'News' || + collection.displayName === 'Features' || + collection.displayName === 'More features'; + if (collection.collectionType === 'scrollable/highlights') { // Highlights are rendered in the Masthead component return null; @@ -352,7 +382,7 @@ export const FrontLayout = ({ front, NAV }: Props) => { } if ( - collection.collectionType === 'news/most-popular' && + isMostPopular(collection) && !isPaidContent && switches.mostViewedFronts ) { @@ -496,6 +526,12 @@ export const FrontLayout = ({ front, NAV }: Props) => { index, )} isLabs={isLabs(collection)} + slimifySectionForAbTest={ + isInSlimHomepageAbTestVariant && + isTargetedContainerInSlimHomepageAbTest + } + mostViewed={front.mostViewed} + deeplyRead={front.deeplyRead} > Date: Mon, 2 Mar 2026 11:04:07 +0000 Subject: [PATCH 2/4] Only use absolute positioning for Deeply Read --- dotcom-rendering/src/components/FrontSection.tsx | 1 + .../src/components/MostPopularFrontRight.tsx | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/dotcom-rendering/src/components/FrontSection.tsx b/dotcom-rendering/src/components/FrontSection.tsx index a971a98ff09..1152b2c561c 100644 --- a/dotcom-rendering/src/components/FrontSection.tsx +++ b/dotcom-rendering/src/components/FrontSection.tsx @@ -863,6 +863,7 @@ export const FrontSection = ({ ${from.wide} { grid-row: content-toggleable; grid-column: 14 / 18; + position: relative; } `} > diff --git a/dotcom-rendering/src/components/MostPopularFrontRight.tsx b/dotcom-rendering/src/components/MostPopularFrontRight.tsx index 4872d24779a..61180310d28 100644 --- a/dotcom-rendering/src/components/MostPopularFrontRight.tsx +++ b/dotcom-rendering/src/components/MostPopularFrontRight.tsx @@ -13,14 +13,19 @@ import { FormatBoundary } from './FormatBoundary'; import { LinkHeadline } from './LinkHeadline'; const containerStyles = css` - position: absolute; - width: 300px; padding-top: ${space[2]}px; display: flex; flex-direction: column; gap: ${space[8]}px; `; +const absolutePositionStyles = css` + position: absolute; + top: 0; + left: 0; + width: 300px; +`; + const headingStyles = css` padding-left: 80px; ${headlineBold24}; @@ -86,7 +91,10 @@ export const MostPopularFrontRight = ({ heading, trails }: Props) => { return (

{heading}

    From 908e8ab5e487c47a95431408f7f04e48d0c8a5f6 Mon Sep 17 00:00:00 2001 From: Dominik Lander Date: Mon, 2 Mar 2026 17:55:08 +0000 Subject: [PATCH 3/4] Disable show/hide button if covered by Most Popular Front Right containers --- dotcom-rendering/src/components/FrontSection.tsx | 4 ++-- .../components/MostPopularFrontRight.stories.tsx | 6 +++++- dotcom-rendering/src/layouts/FrontLayout.tsx | 15 ++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dotcom-rendering/src/components/FrontSection.tsx b/dotcom-rendering/src/components/FrontSection.tsx index 1152b2c561c..e27527b704a 100644 --- a/dotcom-rendering/src/components/FrontSection.tsx +++ b/dotcom-rendering/src/components/FrontSection.tsx @@ -398,7 +398,7 @@ const sectionContentBorderFromLeftCol = css` bottom: 0; border-left: 1px solid ${schemePalette('--section-border')}; transform: translateX(-50%); - /** Keeps the vertical divider ontop of carousel item dividers */ + /** Keeps the vertical divider on top of carousel item dividers */ z-index: 1; } } @@ -414,7 +414,7 @@ const slimHomepageRightBorderStyles = css` right: 0; border-right: 1px solid ${schemePalette('--section-border')}; transform: translateX(-50%); - /** Keeps the vertical divider ontop of carousel item dividers */ + /** Keeps the vertical divider on top of carousel item dividers */ z-index: 1; } } diff --git a/dotcom-rendering/src/components/MostPopularFrontRight.stories.tsx b/dotcom-rendering/src/components/MostPopularFrontRight.stories.tsx index 5beec8cf891..3ffde68ffc8 100644 --- a/dotcom-rendering/src/components/MostPopularFrontRight.stories.tsx +++ b/dotcom-rendering/src/components/MostPopularFrontRight.stories.tsx @@ -7,7 +7,11 @@ const meta = { component: MostPopularFrontRight, title: 'Components/MostPopularFrontRight', decorators: [rightColumnDecorator], - render: (args) => , + render: (args) => ( +
    + +
    + ), } satisfies Meta; export default meta; diff --git a/dotcom-rendering/src/layouts/FrontLayout.tsx b/dotcom-rendering/src/layouts/FrontLayout.tsx index 783387fd0b1..968fce6fb25 100644 --- a/dotcom-rendering/src/layouts/FrontLayout.tsx +++ b/dotcom-rendering/src/layouts/FrontLayout.tsx @@ -78,13 +78,25 @@ const isToggleable = ( index: number, collection: DCRCollectionType, isNetworkFront: boolean, + isInSlimHomepageAbTestVariant: boolean, ) => { if (isNetworkFront) { + /** + * The show/hide button would be covered by the MostPopularFrontRight component + * in the variant of the Slim Homepage AB test. + */ + const hideForSlimHomepageAbTest = + isInSlimHomepageAbTestVariant && + (collection.displayName === 'News' || + collection.displayName === 'Features' || + collection.displayName === 'More features'); + return ( collection.displayName.toLowerCase() !== 'headlines' && !isNavList(collection) && !isHighlights(collection) && - !isLabs(collection) + !isLabs(collection) && + !hideForSlimHomepageAbTest ); } @@ -487,6 +499,7 @@ export const FrontLayout = ({ front, NAV }: Props) => { index, collection, front.isNetworkFront, + isInSlimHomepageAbTestVariant, )} leftContent={decideLeftContent( front, From 3acc60dcd5af65a89a9e645252b23f9fa4fb1d42 Mon Sep 17 00:00:00 2001 From: Dominik Lander Date: Tue, 3 Mar 2026 07:58:08 +0000 Subject: [PATCH 4/4] Refactor CSS --- dotcom-rendering/src/components/FrontSection.tsx | 9 ++++++--- .../src/components/MostPopularFrontRight.tsx | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/dotcom-rendering/src/components/FrontSection.tsx b/dotcom-rendering/src/components/FrontSection.tsx index e27527b704a..fcea812ff74 100644 --- a/dotcom-rendering/src/components/FrontSection.tsx +++ b/dotcom-rendering/src/components/FrontSection.tsx @@ -364,16 +364,18 @@ const sectionControls = css` } `; -const sectionContent = (isInSlimHomepageTestVariant: boolean) => css` +const sectionContent = css` margin: 0; grid-column: content; .hidden > & { display: none; } +`; +const slimSectionContent = css` ${from.wide} { - grid-column: ${isInSlimHomepageTestVariant ? '5 / 14' : 'content'}; + grid-column: 5 / 14; } `; @@ -824,7 +826,8 @@ export const FrontSection = ({