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..fcea812ff74 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) => @@ -356,12 +366,17 @@ const sectionControls = css` const sectionContent = css` margin: 0; + grid-column: content; .hidden > & { display: none; } +`; - grid-column: content; +const slimSectionContent = css` + ${from.wide} { + grid-column: 5 / 14; + } `; const sectionContentRow = (toggleable: boolean) => css` @@ -385,7 +400,23 @@ 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; + } + } +`; + +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 on top of carousel item dividers */ z-index: 1; } } @@ -619,6 +650,7 @@ export const FrontSection = ({ isOnPaidContentFront, targetedTerritory, hasPageSkin = false, + slimifySectionForAbTest = false, discussionApiUrl, collectionBranding, isTagPage = false, @@ -626,6 +658,8 @@ export const FrontSection = ({ isAboveDesktopAd = false, isAboveMobileAd = false, isLabs = false, + mostViewed = [], + deeplyRead = [], }: Props) => { const isToggleable = toggleable && !!sectionId; const showVerticalRule = !hasPageSkin; @@ -690,6 +724,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; + } + `, ]} /> )} @@ -784,18 +827,58 @@ export const FrontSection = ({
{children}
+ {slimifySectionForAbTest && sectionId === 'news' && ( +
+ + + +
+ )} + + {slimifySectionForAbTest && sectionId === 'features' && ( +
+ + + +
+ )} +
, + render: (args) => ( +
+ +
+ ), } satisfies Meta; export default meta; diff --git a/dotcom-rendering/src/components/MostPopularFrontRight.tsx b/dotcom-rendering/src/components/MostPopularFrontRight.tsx index a05da13bac3..af6e8123bbe 100644 --- a/dotcom-rendering/src/components/MostPopularFrontRight.tsx +++ b/dotcom-rendering/src/components/MostPopularFrontRight.tsx @@ -14,11 +14,19 @@ import { LinkHeadline } from './LinkHeadline'; const containerStyles = css` padding-top: ${space[2]}px; + padding-bottom: ${space[10]}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}; @@ -84,7 +92,10 @@ export const MostPopularFrontRight = ({ heading, trails }: Props) => { return (

{heading}

    diff --git a/dotcom-rendering/src/components/MostViewedFooterItem.tsx b/dotcom-rendering/src/components/MostViewedFooterItem.tsx index 1ad8e21417e..fec931d432e 100644 --- a/dotcom-rendering/src/components/MostViewedFooterItem.tsx +++ b/dotcom-rendering/src/components/MostViewedFooterItem.tsx @@ -84,7 +84,7 @@ export const MostViewedFooterItem = ({ -
    +
    {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'; @@ -74,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 ); } @@ -138,6 +154,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 +311,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 +394,7 @@ export const FrontLayout = ({ front, NAV }: Props) => { } if ( - collection.collectionType === 'news/most-popular' && + isMostPopular(collection) && !isPaidContent && switches.mostViewedFronts ) { @@ -457,6 +499,7 @@ export const FrontLayout = ({ front, NAV }: Props) => { index, collection, front.isNetworkFront, + isInSlimHomepageAbTestVariant, )} leftContent={decideLeftContent( front, @@ -496,6 +539,12 @@ export const FrontLayout = ({ front, NAV }: Props) => { index, )} isLabs={isLabs(collection)} + slimifySectionForAbTest={ + isInSlimHomepageAbTestVariant && + isTargetedContainerInSlimHomepageAbTest + } + mostViewed={front.mostViewed} + deeplyRead={front.deeplyRead} >