diff --git a/dotcom-rendering/src/components/ContainerTitle.tsx b/dotcom-rendering/src/components/ContainerTitle.tsx
index 6d37f970e3..15f79065e2 100644
--- a/dotcom-rendering/src/components/ContainerTitle.tsx
+++ b/dotcom-rendering/src/components/ContainerTitle.tsx
@@ -4,12 +4,15 @@ import {
between,
headlineBold17,
headlineBold24,
+ headlineBold28,
space,
textEgyptian17,
+ textSansBold17,
until,
} from '@guardian/source/foundations';
import { type EditionId, getEditionFromId } from '../lib/edition';
import { palette as schemePalette } from '../palette';
+import type { DCRContainerLevel } from '../types/front';
import { localisedTitle } from './Localisation';
type Props = {
@@ -20,6 +23,7 @@ type Props = {
showDateHeader?: boolean;
editionId?: EditionId;
lightweightHeader?: boolean;
+ containerLevel?: DCRContainerLevel;
};
const linkStyles = css`
@@ -33,6 +37,20 @@ const headerStyles = css`
overflow-wrap: break-word; /*if a single word is too long, this will break the word up rather than have the display be affected*/
`;
+const containerLevelStyling = (level: DCRContainerLevel) => {
+ if (level === 'Primary') {
+ return css`
+ ${headlineBold28};
+ `;
+ }
+ if (level === 'Secondary') {
+ return css`
+ ${textSansBold17};
+ `;
+ }
+ return null;
+};
+
const headerStylesWithUrl = css`
:hover {
text-decoration: underline;
@@ -94,6 +112,7 @@ export const ContainerTitle = ({
showDateHeader,
editionId,
fontColour = schemePalette('--article-section-title'),
+ containerLevel,
}: Props) => {
if (!title) return null;
@@ -115,6 +134,8 @@ export const ContainerTitle = ({
headerStylesWithUrl,
headerStyles,
lightweightHeader && article17,
+ containerLevel &&
+ containerLevelStyling(containerLevel),
]}
>
{localisedTitle(title, editionId)}
@@ -123,7 +144,11 @@ export const ContainerTitle = ({
) : (
{localisedTitle(title, editionId)}
diff --git a/dotcom-rendering/src/components/FrontSection.stories.tsx b/dotcom-rendering/src/components/FrontSection.stories.tsx
index 186ccb88a2..b979a3ff72 100644
--- a/dotcom-rendering/src/components/FrontSection.stories.tsx
+++ b/dotcom-rendering/src/components/FrontSection.stories.tsx
@@ -96,6 +96,23 @@ export const ContainerStory = {
args: { title: 'Default Container', showTopBorder: false },
};
+export const PrimaryContainerStory = {
+ name: 'primary container',
+ args: {
+ title: 'Primary Container',
+ showTopBorder: false,
+ containerLevel: 'Primary',
+ },
+};
+export const SecondaryContainerStory = {
+ name: 'secondary container',
+ args: {
+ title: 'Secondary Container',
+ showTopBorder: false,
+ containerLevel: 'Secondary',
+ },
+};
+
export const NoTitleStory = {
name: 'with no title',
args: { showTopBorder: false },
diff --git a/dotcom-rendering/src/components/FrontSection.tsx b/dotcom-rendering/src/components/FrontSection.tsx
index 73c5fdec31..ecb8ed29bd 100644
--- a/dotcom-rendering/src/components/FrontSection.tsx
+++ b/dotcom-rendering/src/components/FrontSection.tsx
@@ -6,7 +6,11 @@ import type { EditionId } from '../lib/edition';
import { hideAge } from '../lib/hideAge';
import { palette, palette as schemePalette } from '../palette';
import type { CollectionBranding } from '../types/branding';
-import type { DCRContainerPalette, TreatType } from '../types/front';
+import type {
+ DCRContainerLevel,
+ DCRContainerPalette,
+ TreatType,
+} from '../types/front';
import type { DCRFrontPagination } from '../types/tagPage';
import { isAustralianTerritory, type Territory } from '../types/territory';
import { AustralianTerritorySwitcher } from './AustralianTerritorySwitcher.importable';
@@ -48,6 +52,9 @@ type Props = {
containerName?: string;
/** Fronts containers can have their styling overridden using a `containerPalette` */
containerPalette?: DCRContainerPalette;
+ /** Fronts containers can have their styling overridden using a `containerLevel`. If used, this can be either "Primary" or "Secondary", both of which have different styles*/
+ containerLevel?: DCRContainerLevel;
+
/** Defaults to `false`. If true a Hide button is show top right allowing this section
* to be collapsed
*/
@@ -421,6 +428,7 @@ export const FrontSection = ({
children,
containerName,
containerPalette,
+ containerLevel,
description,
editionId,
leftContent,
@@ -513,6 +521,7 @@ export const FrontSection = ({
url={!isOnPaidContentFront ? url : undefined}
showDateHeader={showDateHeader}
editionId={editionId}
+ containerLevel={containerLevel}
/>
}
collectionBranding={collectionBranding}
diff --git a/dotcom-rendering/src/layouts/FrontLayout.tsx b/dotcom-rendering/src/layouts/FrontLayout.tsx
index e8522f9a62..da9212381e 100644
--- a/dotcom-rendering/src/layouts/FrontLayout.tsx
+++ b/dotcom-rendering/src/layouts/FrontLayout.tsx
@@ -661,6 +661,7 @@ export const FrontLayout = ({ front, NAV }: Props) => {
collectionBranding={
collection.collectionBranding
}
+ containerLevel={collection.containerLevel}
>
{
+ if (levels?.includes('Primary')) return 'Primary';
+ if (levels?.includes('Secondary')) return 'Secondary';
+ return undefined;
+};
+
export const enhanceCollections = ({
collections,
editionId,
@@ -92,6 +120,15 @@ export const enhanceCollections = ({
},
);
+ /** "Primary" or "Secondary" container level styling should only be applied to fairground containers
+ * Ideally this logic would (and might) exist in the fronts tool.
+ */
+ const containerLevel = FAIRGROUND_CONTAINERS.includes(collectionType)
+ ? getContainerLevel(
+ collection.config.metadata?.map((meta) => meta.type),
+ )
+ : undefined;
+
return {
id,
displayName,
@@ -131,6 +168,7 @@ export const enhanceCollections = ({
},
canShowMore: hasMore && !collection.config.hideShowMore,
targetedTerritory: collection.targetedTerritory,
+ containerLevel,
};
});
};
diff --git a/dotcom-rendering/src/model/front-schema.json b/dotcom-rendering/src/model/front-schema.json
index 8a7414788f..924d53f77b 100644
--- a/dotcom-rendering/src/model/front-schema.json
+++ b/dotcom-rendering/src/model/front-schema.json
@@ -3244,6 +3244,8 @@
"LongRunningAltPalette",
"LongRunningPalette",
"Podcast",
+ "Primary",
+ "Secondary",
"SombreAltPalette",
"SombrePalette",
"Special",
diff --git a/dotcom-rendering/src/types/front.ts b/dotcom-rendering/src/types/front.ts
index fb923ef2a5..057f68af21 100644
--- a/dotcom-rendering/src/types/front.ts
+++ b/dotcom-rendering/src/types/front.ts
@@ -119,7 +119,9 @@ export type FEContainerPalette =
| 'Podcast'
| 'Branded'
| 'BreakingPalette'
- | 'SpecialReportAltPalette';
+ | 'SpecialReportAltPalette'
+ | 'Primary'
+ | 'Secondary';
export type FEFrontCardStyle =
| 'SpecialReport'
@@ -153,6 +155,8 @@ export type DCRContainerPalette =
// TODO: These may need to be declared differently than the front types in the future
export type DCRContainerType = FEContainerType;
+export type DCRContainerLevel = 'Primary' | 'Secondary';
+
/** @see https://github.com/guardian/frontend/blob/0bf69f55a/common/app/model/content/Atom.scala#L191-L196 */
interface MediaAsset {
id: string;
@@ -407,6 +411,7 @@ export type DCRCollectionType = {
description?: string;
collectionType: DCRContainerType;
containerPalette?: DCRContainerPalette;
+ containerLevel?: DCRContainerLevel;
grouped: DCRGroupedTrails;
curated: DCRFrontCard[];
backfill: DCRFrontCard[];