Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
f2d317e
Type tidying
frederickobrien Mar 11, 2026
d087f53
Move all column settings into layout config
frederickobrien Mar 11, 2026
744539d
Remove maxWidth wrapper divs
frederickobrien Mar 11, 2026
6eb25a8
Rough first pass
frederickobrien May 19, 2026
211c9c2
Refactor grid centre rule, more breakpoints
frederickobrien May 21, 2026
6471809
Rough implementation of portrait/landscape variants
frederickobrien May 26, 2026
a87148c
Feature specific styling
frederickobrien Jun 11, 2026
dd62136
Use grid module helpers for columns
frederickobrien Jun 23, 2026
231cf02
First, clumsy pass at immersive forking
frederickobrien Jun 23, 2026
39b646d
Distinguish between feature and non-feature immersives
frederickobrien Jun 30, 2026
86a943f
Fix portrait main media config
frederickobrien Jun 30, 2026
05d9d26
Tie main media styling to article arrangement
frederickobrien Jun 30, 2026
0dafbd3
Restore wrapper
frederickobrien Jul 1, 2026
d67d072
Enhance article meta and layout handling for immersive designs
alessiaAmitrano Jul 7, 2026
4afd212
show byline for immersive landscape
alessiaAmitrano Jul 17, 2026
ec86165
show byline and avatar in a row, show series tag, reintroduce borders…
alessiaAmitrano Jul 21, 2026
d582bd9
add testing for new layoutType parameters influencing contributor sho…
alessiaAmitrano Jul 22, 2026
f92e085
Rough first pass
frederickobrien May 19, 2026
ad4cd74
Rough implementation of portrait/landscape variants
frederickobrien May 26, 2026
1eb6a80
Feature specific styling
frederickobrien Jun 11, 2026
adbec3e
Distinguish between feature and non-feature immersives
frederickobrien Jun 30, 2026
57534d9
Tie main media styling to article arrangement
frederickobrien Jun 30, 2026
2c36282
Rebase tidying
frederickobrien Jul 7, 2026
e33d5d1
Rich review tweaks
frederickobrien Jul 16, 2026
eeaa9ce
Caption grid area and meta section
frederickobrien Jul 21, 2026
b0df0eb
make layoutType optional for ArticleMeta web and app components
alessiaAmitrano Jul 28, 2026
dd4af19
make layoutType optional for ArticleTitle and children
alessiaAmitrano Jul 28, 2026
f020894
Merge remote-tracking branch 'origin/portrait-layout' into aa/portrai…
alessiaAmitrano Jul 28, 2026
7c88363
fix issues post merge
alessiaAmitrano Jul 28, 2026
6739f4c
fix duplicate prop in ArticleHeadline component
alessiaAmitrano Jul 28, 2026
7aaa4fa
Rough first pass
frederickobrien May 19, 2026
d693896
Rough implementation of portrait/landscape variants
frederickobrien May 26, 2026
249ea42
Feature specific styling
frederickobrien Jun 11, 2026
4db971e
Distinguish between feature and non-feature immersives
frederickobrien Jun 30, 2026
2d1b937
Tie main media styling to article arrangement
frederickobrien Jun 30, 2026
3107ac9
Rebase tidying
frederickobrien Jul 7, 2026
ebf1fbc
Rich review tweaks
frederickobrien Jul 16, 2026
2100f70
Caption grid area and meta section
frederickobrien Jul 21, 2026
b31f2df
Update immersive ad count test
frederickobrien Jul 29, 2026
a6a17d7
add changes lost during merge
alessiaAmitrano Jul 29, 2026
b1372f6
Merge commit 'b31f2dfb5958c6710a6ce41054eb29969588e941' into aa/portr…
alessiaAmitrano Jul 29, 2026
7e700b3
remove duplicate identifier
alessiaAmitrano Jul 29, 2026
c19bea4
Rough first pass
frederickobrien May 19, 2026
b73ce4a
Rough implementation of portrait/landscape variants
frederickobrien May 26, 2026
a316395
Feature specific styling
frederickobrien Jun 11, 2026
b950785
Distinguish between feature and non-feature immersives
frederickobrien Jun 30, 2026
691fcea
Tie main media styling to article arrangement
frederickobrien Jun 30, 2026
0904753
Rebase tidying
frederickobrien Jul 7, 2026
6041b44
Rich review tweaks
frederickobrien Jul 16, 2026
8f76f07
Caption grid area and meta section
frederickobrien Jul 21, 2026
4f66342
Update immersive ad count test
frederickobrien Jul 29, 2026
396b1a8
Merge branch 'portrait-layout' into aa/portrait-layout-continued
frederickobrien Jul 30, 2026
457487d
Update ArticleHeadline.tsx
frederickobrien Jul 30, 2026
59e1d12
Merge branch 'portrait-layout' of https://github.com/guardian/dotcom-…
DanielCliftonGuardian Jul 30, 2026
6c16119
Apply suggestions from code review
frederickobrien Jul 30, 2026
8d18e72
Merge pull request #16482 from guardian/aa/portrait-layout-continued
frederickobrien Jul 30, 2026
8e1bd1a
Simplify `shouldShowAvatar` switch
frederickobrien Jul 30, 2026
265d0f2
Remove leftover debug crop and duplicate CSS from immersive grid layout
DanielCliftonGuardian Jul 30, 2026
724623d
Fix immersive content overlapping the Labs header
DanielCliftonGuardian Jul 30, 2026
996fd99
Preserve immersive main media aspect ratios
DanielCliftonGuardian Jul 30, 2026
e96161e
Route only Labs immersive articles through the new grid
DanielCliftonGuardian Aug 3, 2026
12c9356
Update DecideLayout.stories.tsx
DanielCliftonGuardian Aug 3, 2026
1b5a7b6
Merge branch 'main' into portrait-layout
DanielCliftonGuardian Aug 3, 2026
09f4a73
Update playwright assertion
DanielCliftonGuardian Aug 3, 2026
8970a22
Merge branch 'main' into portrait-layout
DanielCliftonGuardian Aug 3, 2026
077c348
Fixes and reverts
DanielCliftonGuardian Aug 3, 2026
df7f16e
Fix legacy styles
DanielCliftonGuardian Aug 3, 2026
1e3c43e
Fix grid index
DanielCliftonGuardian Aug 3, 2026
9c82546
Use isImmersive
DanielCliftonGuardian Aug 3, 2026
3ba796b
Add immersive labs dark mode stories and new labs colours
DanielCliftonGuardian Aug 4, 2026
3e1ac35
Update paletteDeclarations.ts
DanielCliftonGuardian Aug 4, 2026
2b8b344
Enable snapshots for immersive labs stories
DanielCliftonGuardian Aug 4, 2026
e1b0079
Fix section title colours and colours for other design types
DanielCliftonGuardian Aug 4, 2026
51ac52b
Fix series tag portrait position
DanielCliftonGuardian Aug 10, 2026
aef4915
Video labs text colour
DanielCliftonGuardian Aug 10, 2026
613cb9e
Update all labs headers with new styles
DanielCliftonGuardian Aug 10, 2026
9308830
Rename, refactor
DanielCliftonGuardian Aug 11, 2026
0c77fb6
Refactor ternary
DanielCliftonGuardian Aug 11, 2026
c2abc00
Refactoring addressing comments
DanielCliftonGuardian Aug 11, 2026
fb9520b
Labs header link hover colour fix
DanielCliftonGuardian Aug 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dotcom-rendering/playwright/tests/lightbox.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ test.describe('Lightbox', () => {

// Open lightbox by clicking on the fourth image within the article body
// Lightbox should open at the fifth image as the first image is the main media image
await page.locator('article img').nth(3).click({ force: true });
await page.locator('button.open-lightbox').nth(4).click();

await expectToBeVisible(page, '#gu-lightbox');

Expand Down
219 changes: 141 additions & 78 deletions dotcom-rendering/src/components/ArticleHeadline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
until,
} from '@guardian/source/foundations';
import { grid } from '../../src/grid';
import { type LayoutType } from '../layouts/lib/articleArrangements';
import { interactiveLegacyClasses } from '../layouts/lib/interactiveLegacyStyling';
import { getAgeWarning } from '../lib/age-warning';
import {
Expand All @@ -39,6 +40,7 @@ import { StarRating } from './StarRating/StarRating';
type Props = {
headlineString: string;
format: ArticleFormat;
layoutType?: LayoutType;
byline?: string;
tags: TagType[];
webPublicationDateDeprecated: string;
Expand Down Expand Up @@ -214,7 +216,16 @@ const invertedStyles = css`
box-decoration-break: clone;
`;

const immersiveStyles = css`
const legacyInvertedStyles = css`
white-space: pre-wrap;
padding-right: ${space[1]}px;
padding-bottom: ${space[1]}px;
box-shadow: -6px 0 0 ${themePalette('--headline-background')};
/* Box decoration is required to push the box shadow out on Firefox */
box-decoration-break: clone;
`;

const legacyImmersiveStyles = css`
min-height: 112px;
padding-bottom: ${space[6]}px;
padding-left: ${space[1]}px;
Expand All @@ -230,16 +241,47 @@ const immersiveStyles = css`
margin-right: ${space[5]}px;
`;

const darkBackground = css`
background-color: ${themePalette('--headline-background')};
const legacyImmersiveWrapper = css`
margin-left: 6px;

${from.tablet} {
margin-left: 16px;
}

${from.leftCol} {
margin-left: 25px;
}

flex-grow: 1;
z-index: ${getZIndex('articleHeadline')};

${until.mobileLandscape} {
margin-right: 40px;
}
`;

const invertedText = css`
const legacyInvertedText = css`
white-space: pre-wrap;
padding-bottom: ${space[1]}px;
padding-right: ${space[1]}px;
`;

const darkBackground = css`
background-color: ${themePalette('--headline-background')};
`;

const invertedText = css`
${from.desktop} {
color: white;
background-color: black;
white-space: pre-wrap;
padding-bottom: ${space[1]}px;
padding-right: ${space[1]}px;
margin-left: -10px;
padding-left: 10px;
}
`;

const maxWidth = css`
${from.desktop} {
max-width: 620px;
Expand All @@ -255,96 +297,90 @@ const invertedWrapper = css`
margin-left: 6px;
`;

const immersiveWrapper = css`
/*
Make sure we vertically align the headline font with the body font
*/
margin-left: 6px;

${from.tablet} {
margin-left: 16px;
}

${from.leftCol} {
margin-left: 25px;
}

/*
We need this grow to ensure the headline fills the main content column
*/
flex-grow: 1;
/*
This z-index is what ensures the headline text shows above the pseudo black
box that extends the black background to the right
*/
z-index: ${getZIndex('articleHeadline')};

${until.mobileLandscape} {
margin-right: 40px;
}
`;

// Due to MainMedia using position: relative, this seems to effect the rendering order
// To mitigate we use z-index
// TODO: find a cleaner solution
const zIndex = css`
z-index: 1;
`;

const ageWarningMargins = (format: ArticleFormat) => {
const ageWarningMargins = (
format: ArticleFormat,
isLegacyImmersive: boolean,
) => {
if (format.design === ArticleDesign.Gallery) {
return '';
}
return format.display === ArticleDisplay.Immersive
? css`
margin-left: 0px;
margin-bottom: 0px;
if (format.display === ArticleDisplay.Immersive) {
return isLegacyImmersive
? css`
margin-left: 0;
margin-bottom: 0;

${from.tablet} {
margin-left: 10px;
}
${from.tablet} {
margin-left: 10px;
}

${from.leftCol} {
margin-left: 20px;
}
`
: css`
margin-top: 12px;
margin-left: -10px;
margin-bottom: 6px;

${from.tablet} {
margin-left: -20px;
}
${from.leftCol} {
margin-left: 20px;
}
`
: '';
}
return css`
margin-top: 12px;
margin-left: -10px;
margin-bottom: 6px;

${from.leftCol} {
margin-left: -10px;
margin-top: 0;
}
`;
};
${from.tablet} {
margin-left: -20px;
}

const backgroundStyles = css`
background-color: ${themePalette('--age-warning-wrapper-background')};
`;
${from.leftCol} {
margin-left: -10px;
margin-top: 0;
}
`;
};

const WithAgeWarning = ({
tags,
webPublicationDateDeprecated,
format,
children,
snapToInverted = false,
isLegacyImmersive = false,
}: {
tags: TagType[];
webPublicationDateDeprecated: string;
format: ArticleFormat;
children: React.ReactNode;
snapToInverted?: boolean;
isLegacyImmersive?: boolean;
}) => {
const age = getAgeWarning(tags, webPublicationDateDeprecated);

if (age) {
return (
<>
<div css={[backgroundStyles, ageWarningMargins(format)]}>
<div
css={[
ageWarningMargins(format, isLegacyImmersive),
isLegacyImmersive &&
css`
background-color: ${themePalette(
'--age-warning-wrapper-background',
)};
`,
snapToInverted && !isLegacyImmersive
? css`
${from.desktop} {
margin-left: -10px;
}
`
: '',
]}
>
<AgeWarning age={age} />
</div>
{children}
Expand Down Expand Up @@ -433,13 +469,16 @@ const galleryStyles = css`
export const ArticleHeadline = ({
headlineString,
format,
layoutType,
tags,
byline,
webPublicationDateDeprecated,
hasAvatar,
isMatch,
starRating,
}: Props) => {
const isInverted = layoutType === 'immersiveLandscapeDefault';
const isLegacyImmersive = layoutType == null;
switch (format.display) {
case ArticleDisplay.Immersive: {
switch (format.design) {
Expand All @@ -465,12 +504,22 @@ export const ArticleHeadline = ({
format.theme === ArticleSpecial.Labs
? labsFont
: headlineFont(format),
invertedText,
css`
color: ${themePalette(
'--headline-colour',
)};
`,
isLegacyImmersive
? [
legacyInvertedText,
css`
color: ${themePalette(
'--headline-colour',
)};
`,
]
: isInverted
? [invertedText, darkBackground]
: css`
color: ${themePalette(
'--headline-colour',
)};
`,
]}
>
{headlineString}
Expand All @@ -496,16 +545,28 @@ export const ArticleHeadline = ({
webPublicationDateDeprecated
}
format={format}
snapToInverted={isInverted}
isLegacyImmersive={isLegacyImmersive}
>
<h1
css={[
immersiveWrapper,
darkBackground,
css`
color: ${themePalette(
'--headline-colour',
)};
`,
isLegacyImmersive
? [
legacyImmersiveWrapper,
darkBackground,
css`
color: ${themePalette(
'--headline-colour',
)};
`,
]
: isInverted
? [invertedText, darkBackground]
: css`
color: ${themePalette(
'--headline-colour',
)};
`,
]}
>
<span
Expand All @@ -514,8 +575,10 @@ export const ArticleHeadline = ({
? jumboLabsFont
: headlineFont(format),
maxWidth,
invertedStyles,
immersiveStyles,
isLegacyImmersive && [
legacyInvertedStyles,
legacyImmersiveStyles,
],
displayBlock,
]}
>
Expand Down
21 changes: 13 additions & 8 deletions dotcom-rendering/src/components/ArticleMeta.apps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { from, space, until } from '@guardian/source/foundations';
import { StraightLines } from '@guardian/source-development-kitchen/react-components';
import type { ReactNode } from 'react';
import { grid } from '../grid';
import type { LayoutType } from '../layouts/lib/articleArrangements';
import { interactiveLegacyClasses } from '../layouts/lib/interactiveLegacyStyling';
import {
ArticleDesign,
Expand Down Expand Up @@ -36,6 +37,7 @@ import { PodcastMeta } from './PodcastMeta';

type Props = {
format: ArticleFormat;
layoutType?: LayoutType;
byline?: string;
tags: TagType[];
primaryDateline: string;
Expand Down Expand Up @@ -242,6 +244,7 @@ const galleryMetaContainer = css`
export const ArticleMetaApps = ({
branding,
format,
layoutType,
byline,
tags,
primaryDateline,
Expand All @@ -253,9 +256,10 @@ export const ArticleMetaApps = ({
headline,
mainMediaElements,
}: Props) => {
const isImmersiveGrid = layoutType?.startsWith('immersive') ?? false;
const soleContributor = getSoleContributor(tags, byline);
const authorName = soleContributor?.title ?? 'Author Image';
const avatarUrl = shouldShowAvatar(format)
const avatarUrl = shouldShowAvatar(format, isImmersiveGrid)
? soleContributor?.bylineLargeImageUrl
: undefined;

Expand Down Expand Up @@ -328,13 +332,14 @@ export const ArticleMetaApps = ({
</MetaGridAvatar>
)}
<MetaGridByline isComment={isComment}>
{shouldShowContributor(format) && !!byline && (
<Contributor
byline={byline}
tags={tags}
format={format}
/>
)}
{shouldShowContributor(format, isImmersiveGrid) &&
!!byline && (
<Contributor
byline={byline}
tags={tags}
format={format}
/>
)}
{shouldShowFollowButtons(
isComment || isAnalysis || isImmersive,
) &&
Expand Down
Loading
Loading