{props.renderAds ? (
@@ -404,7 +419,7 @@ const BannerAndMasthead = (props: {
idApiUrl={props.config.idApiUrl}
contributionsServiceUrl={props.contributionsServiceUrl}
showSubNav={false}
- showSlimNav={true}
+ showSlimNav={props.showSlimNav ?? true}
hasPageSkin={false}
hasPageSkinContentSelfConstrain={false}
pageId={props.pageId}
diff --git a/dotcom-rendering/src/layouts/LiveLayout.tsx b/dotcom-rendering/src/layouts/LiveLayout.tsx
index ff64da7bd6f..af659375f8d 100644
--- a/dotcom-rendering/src/layouts/LiveLayout.tsx
+++ b/dotcom-rendering/src/layouts/LiveLayout.tsx
@@ -20,6 +20,7 @@ import { ArticleMeta } from '../components/ArticleMeta.web';
import { ArticleTitle } from '../components/ArticleTitle';
import { Carousel } from '../components/Carousel.island';
import { DecideLines } from '../components/DecideLines';
+import { DirectoryPageNav } from '../components/DirectoryPageNav';
import { DiscussionLayout } from '../components/DiscussionLayout';
import { FilterKeyEventsToggle } from '../components/FilterKeyEventsToggle.island';
import { FootballMatchHeaderFallback } from '../components/FootballMatchHeader/FootballMatchHeaderFallback';
@@ -50,6 +51,8 @@ import { canRenderAds } from '../lib/canRenderAds';
import { getContributionsServiceUrl } from '../lib/contributions';
import { decideStoryPackageTrails } from '../lib/decideTrail';
import { getZIndex } from '../lib/getZIndex';
+import { useBetaAB } from '../lib/useAB';
+import { worldCupTagId } from '../lib/worldCup2026';
import type { NavType } from '../model/extract-nav';
import { palette as themePalette } from '../palette';
import type { ArticleDeprecated } from '../types/article';
@@ -305,6 +308,12 @@ export const LiveLayout = (props: WebProps | AppsProps) => {
const renderAds = canRenderAds(article);
+ const ab = useBetaAB();
+
+ const isWorldCup2026 =
+ article.tags.some((tag) => tag.id === worldCupTagId) &&
+ ab?.isUserInTest('webx-world-cup-2026-subnav');
+
const isWeb = renderingTarget === 'Web';
const isApps = renderingTarget === 'Apps';
@@ -337,7 +346,7 @@ export const LiveLayout = (props: WebProps | AppsProps) => {
discussionApiUrl={article.config.discussionApiUrl}
idApiUrl={article.config.idApiUrl}
contributionsServiceUrl={contributionsServiceUrl}
- showSubNav={true}
+ showSubNav={!isWorldCup2026}
showSlimNav={false}
hasPageSkin={false}
hasPageSkinContentSelfConstrain={false}
@@ -354,6 +363,10 @@ export const LiveLayout = (props: WebProps | AppsProps) => {
)}
+
{isWeb && renderAds && hasLiveBlogTopAd && (
{
const renderAds = canRenderAds(article);
+ const ab = useBetaAB();
+
+ const isWorldCup2026 =
+ article.tags.some((tag) => tag.id === worldCupTagId) &&
+ ab?.isUserInTest('webx-world-cup-2026-subnav');
+
const avatarUrl = getSoleContributor(article.tags, article.byline)
?.bylineLargeImageUrl;
@@ -303,7 +312,7 @@ export const PictureLayout = (props: WebProps | AppsProps) => {
discussionApiUrl={article.config.discussionApiUrl}
idApiUrl={article.config.idApiUrl}
contributionsServiceUrl={contributionsServiceUrl}
- showSubNav={true}
+ showSubNav={!isWorldCup2026}
showSlimNav={false}
hasPageSkin={false}
hasPageSkinContentSelfConstrain={false}
@@ -330,6 +339,10 @@ export const PictureLayout = (props: WebProps | AppsProps) => {
)}
+
{
const contributionsServiceUrl = getContributionsServiceUrl(article);
+ const ab = useBetaAB();
+
+ const isWorldCup2026 =
+ article.tags.some((tag) => tag.id === worldCupTagId) &&
+ ab?.isUserInTest('webx-world-cup-2026-subnav');
+
const renderAds = canRenderAds(article);
const isLabs = format.theme === ArticleSpecial.Labs;
@@ -282,7 +290,7 @@ export const ShowcaseLayout = (props: WebProps | AppsProps) => {
contributionsServiceUrl={
contributionsServiceUrl
}
- showSubNav={true}
+ showSubNav={!isWorldCup2026}
showSlimNav={false}
hasPageSkin={false}
hasPageSkinContentSelfConstrain={false}
diff --git a/dotcom-rendering/src/layouts/SportDataPageLayout.tsx b/dotcom-rendering/src/layouts/SportDataPageLayout.tsx
index 90f7ddfbe06..3314b8b0783 100644
--- a/dotcom-rendering/src/layouts/SportDataPageLayout.tsx
+++ b/dotcom-rendering/src/layouts/SportDataPageLayout.tsx
@@ -14,6 +14,8 @@ import { StickyBottomBanner } from '../components/StickyBottomBanner.island';
import { SubNav } from '../components/SubNav.island';
import { canRenderAds } from '../lib/canRenderAds';
import { getContributionsServiceUrl } from '../lib/contributions';
+import { useBetaAB } from '../lib/useAB';
+import { worldCup2026PageIds } from '../lib/worldCup2026';
import { palette as themePalette } from '../palette';
import type {
AppSportDataPage,
@@ -97,9 +99,14 @@ export const SportDataPageLayout = (
const isApps = props.renderingTarget === 'Apps';
const pageFooter = sportData.pageFooter;
const renderAds = canRenderAds(sportData);
+ const ab = useBetaAB();
const contributionsServiceUrl = getContributionsServiceUrl(sportData);
+ const isWorldCup2026 =
+ worldCup2026PageIds.includes(sportData.config.pageId) &&
+ ab?.isUserInTest('webx-world-cup-2026-subnav');
+
return (
<>
{isWeb && (
@@ -126,7 +133,7 @@ export const SportDataPageLayout = (
discussionApiUrl={sportData.config.discussionApiUrl}
idApiUrl={sportData.config.idApiUrl}
contributionsServiceUrl={contributionsServiceUrl}
- showSubNav={true}
+ showSubNav={!isWorldCup2026}
showSlimNav={false}
hasPageSkin={sportData.config.hasPageSkin}
pageId={sportData.config.pageId}
diff --git a/dotcom-rendering/src/layouts/StandardLayout.tsx b/dotcom-rendering/src/layouts/StandardLayout.tsx
index 65ebfbc5994..abb72147805 100644
--- a/dotcom-rendering/src/layouts/StandardLayout.tsx
+++ b/dotcom-rendering/src/layouts/StandardLayout.tsx
@@ -57,6 +57,8 @@ import { decideStoryPackageTrails } from '../lib/decideTrail';
import type { EditionId } from '../lib/edition';
import { safeParseURL } from '../lib/parse';
import { parse } from '../lib/slot-machine-flags';
+import { useBetaAB } from '../lib/useAB';
+import { worldCupTagId } from '../lib/worldCup2026';
import type { NavType } from '../model/extract-nav';
import { palette as themePalette } from '../palette';
import type { ArticleDeprecated } from '../types/article';
@@ -383,6 +385,12 @@ export const StandardLayout = (props: WebProps | AppProps) => {
const isLabs = format.theme === ArticleSpecial.Labs;
+ const ab = useBetaAB();
+
+ const isWorldCup2026 =
+ article.tags.some((tag) => tag.id === worldCupTagId) &&
+ ab?.isUserInTest('webx-world-cup-2026-subnav');
+
const renderAds = canRenderAds(article);
return (
@@ -410,7 +418,7 @@ export const StandardLayout = (props: WebProps | AppProps) => {
discussionApiUrl={article.config.discussionApiUrl}
idApiUrl={article.config.idApiUrl}
contributionsServiceUrl={contributionsServiceUrl}
- showSubNav={!isLabs}
+ showSubNav={!isLabs && !isWorldCup2026}
showSlimNav={false}
hasPageSkinContentSelfConstrain={true}
pageId={article.pageId}
diff --git a/dotcom-rendering/src/layouts/TagPageLayout.tsx b/dotcom-rendering/src/layouts/TagPageLayout.tsx
index cf16f5e16ea..10933b47239 100644
--- a/dotcom-rendering/src/layouts/TagPageLayout.tsx
+++ b/dotcom-rendering/src/layouts/TagPageLayout.tsx
@@ -25,6 +25,8 @@ import {
getTagPageBannerAdPositions,
getTagPageMobileAdPositions,
} from '../lib/getTagPageAdPositions';
+import { useBetaAB } from '../lib/useAB';
+import { worldCup2026PageIds } from '../lib/worldCup2026';
import { enhanceTags } from '../model/enhanceTags';
import type { NavType } from '../model/extract-nav';
import type { TagPage as TagPageModel } from '../types/tagPage';
@@ -66,6 +68,12 @@ export const TagPageLayout = ({ tagPage, NAV }: Props) => {
const isAccessibilityPage =
tagPage.config.pageId === 'help/accessibility-help';
+ const ab = useBetaAB();
+
+ const isWorldCup2026 =
+ worldCup2026PageIds.includes(pageId) &&
+ ab?.isUserInTest('webx-world-cup-2026-subnav');
+
return (
<>
@@ -91,7 +99,7 @@ export const TagPageLayout = ({ tagPage, NAV }: Props) => {
discussionApiUrl={tagPage.config.discussionApiUrl}
idApiUrl={tagPage.config.idApiUrl}
contributionsServiceUrl={contributionsServiceUrl}
- showSubNav={true}
+ showSubNav={!isWorldCup2026}
showSlimNav={false}
hasPageSkin={hasPageSkin}
pageId={pageId}
diff --git a/dotcom-rendering/src/lib/worldCup2026.tsx b/dotcom-rendering/src/lib/worldCup2026.tsx
new file mode 100644
index 00000000000..8a4befa4ae5
--- /dev/null
+++ b/dotcom-rendering/src/lib/worldCup2026.tsx
@@ -0,0 +1,50 @@
+export const worldCup2026PageIds = [
+ 'football/world-cup-2026',
+ 'football/world-cup-2026/fixtures',
+ 'football/world-cup-2026/overview',
+];
+
+export const worldCupTagId = 'football/world-cup-2026';
+
+export const WorldCup2026Icon = () => (
+
+);
+
+// Smaller version has slightly different proportions to better fit in the nav when the header isn't shown.
+export const WorldCup2026IconSmall = () => (
+
+);