Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions dotcom-rendering/docs/lightbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Frontend's lightbox was added to the Guardian's website in 2014. [The PR to add

## How it gets hydrated

On the server, we only insert a small amount of html and zero javascript. This html can be found in LightboxLayout. On the client hydration is trigged when the page url contains a hash that martches an expected pattern, namely, `img-[n]`. Using the `deferUntil='hash'` feature of Islands, we only execute the Lightbox javascript at the point the url changes and lightbox is requested.
On the server, we only insert a small amount of html and zero javascript. This html can be found in LightboxLayout. On the client hydration is trigged when the page url contains a hash that martches an expected pattern, namely, `img-[n]`. Using the `defer={{ until: 'hash' }}` feature of Islands, we only execute the Lightbox javascript at the point the url changes and lightbox is requested.

## How it works

Expand All @@ -45,7 +45,7 @@ You open and close the lightbox by changing the url. When a reader clicks the 'c

This file is used on the server to co er each article image with an <a> tag. No javascript is used here, only platform features and css.

If the image is clicked the a tag captured this and mutates the url to add a hash in the form `img-[n]`. This triggers hydration based on the `deferUntil='hash'` island.
If the image is clicked the a tag captured this and mutates the url to add a hash in the form `img-[n]`. This triggers hydration based on the `defer={{ until: 'hash' }}` island.

### `LightboxLayout`

Expand Down
14 changes: 1 addition & 13 deletions dotcom-rendering/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,19 +514,7 @@ declare namespace JSX {
'amp-youtube': any;

/** Island {@link ./src/components/Island.tsx} */
'gu-island': {
name: string;
deferUntil?: 'idle' | 'visible' | 'interaction' | 'hash';
rootMargin?: string;
clientOnly?: boolean;
props: any;
children: React.ReactNode;
/**
* This should be a stringified JSON of `ConfigContext`
* @see /dotcom-rendering/src/types/configContext.ts
*/
config: string;
};
'gu-island': import('./src/components/Island.tsx').GuIsland;
}

interface IntrinsicAttributes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ export const AllEditorialNewslettersPage = ({
/>
<SkipTo id="maincontent" label="Skip to main content" />
<SkipTo id="navigation" label="Skip to navigation" />
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<AlreadyVisited />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<FocusStyles />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<Metrics
commercialMetricsEnabled={
!!newslettersPage.config.switches.commercialMetrics
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/ArticleBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ export const ArticleBody = ({
dir={languageDirection}
>
{isRecipe(tags) && (
<Island deferUntil="hash" clientOnly={true}>
<Island defer={{ until: 'hash' }} clientOnly={true}>
<RecipeMultiplier />
</Island>
)}
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/ArticleLastUpdated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const ArticleLastUpdated = ({ format, lastUpdated }: Props) => {
<div css={lastUpdatedStyles(palette)}>
{format.design === ArticleDesign.LiveBlog && (
<span css={livePulseIconStyles(palette)}>
<Island deferUntil="visible">
<Island defer={{ until: 'visible' }}>
<PulsingDot />
</Island>
LIVE
Expand Down
9 changes: 6 additions & 3 deletions dotcom-rendering/src/components/ArticleMeta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ export const ArticleMeta = ({
>
<div css={meta(format)}>
{branding && (
<Island deferUntil="visible">
<Island defer={{ until: 'visible' }}>
<Branding
branding={branding}
palette={palette}
Expand Down Expand Up @@ -380,7 +380,7 @@ export const ArticleMeta = ({
)}
{messageUs &&
format.design === ArticleDesign.LiveBlog && (
<Island deferUntil="visible">
<Island defer={{ until: 'visible' }}>
<SendAMessage
formFields={messageUs.formFields}
formId={messageUs.formId}
Expand Down Expand Up @@ -449,7 +449,10 @@ export const ArticleMeta = ({
>
<div>
{isCommentable && (
<Island clientOnly={true} deferUntil="idle">
<Island
clientOnly={true}
defer={{ until: 'idle' }}
>
<CommentCount
discussionApiUrl={discussionApiUrl}
shortUrlId={shortUrlId}
Expand Down
12 changes: 6 additions & 6 deletions dotcom-rendering/src/components/ArticlePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ export const ArticlePage = (props: WebProps | AppProps) => {
<Island clientOnly={true}>
<LightboxHash />
</Island>
<Island clientOnly={true} deferUntil="hash">
<Island clientOnly={true} defer={{ until: 'hash' }}>
<LightboxJavascript
format={format}
images={article.imagesForLightbox}
/>
</Island>
</>
)}
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<FocusStyles />
</Island>
{(format.design === ArticleDesign.LiveBlog ||
Expand All @@ -96,20 +96,20 @@ export const ArticlePage = (props: WebProps | AppProps) => {
{renderingTarget === 'Web' && (
<>
<SkipTo id="navigation" label="Skip to navigation" />
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<AlreadyVisited />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<Metrics
commercialMetricsEnabled={
!!article.config.switches.commercialMetrics
}
/>
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<BrazeMessaging idApiUrl={article.config.idApiUrl} />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<ReaderRevenueDev
shouldHideReaderRevenue={
article.shouldHideReaderRevenue
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ export const Card = ({
min-height: 10px;
`}
>
<Island deferUntil="visible">
<Island defer={{ until: 'visible' }}>
<CardCommentCount
format={format}
discussionApiUrl={discussionApiUrl}
Expand Down
4 changes: 2 additions & 2 deletions dotcom-rendering/src/components/DiscussionLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const DiscussionLayout = ({
// If we're not hiding an advert stretch to the right
stretchRight={!hideAd}
leftContent={
<Island clientOnly={true} deferUntil="visible">
<Island clientOnly={true} defer={{ until: 'visible' }}>
<DiscussionMeta
format={format}
discussionApiUrl={discussionApiUrl}
Expand All @@ -69,7 +69,7 @@ export const DiscussionLayout = ({
max-width: 100%;
`}
>
<Island deferUntil="visible">
<Island defer={{ until: 'visible' }}>
<DiscussionContainer
format={format}
discussionApiUrl={discussionApiUrl}
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/EmailSignUpSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const EmailSignUpSwitcher = ({
const { renderingTarget } = useConfig();

return renderingTarget === 'Apps' ? (
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<AppEmailSignUp skipToIndex={index} {...emailSignUpProps} />
</Island>
) : (
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ const FooterLinks = ({

const rrLinks = (
<div css={readerRevenueLinks}>
<Island deferUntil="visible" clientOnly={true}>
<Island defer={{ until: 'visible' }} clientOnly={true}>
<ReaderRevenueLinks
urls={urls}
editionId={editionId}
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/FrontMostViewed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const FrontMostViewed = ({
>
{/* We only need hydration if there are multiple tabs */}
{showMostViewedTab ? (
<Island deferUntil="visible">
<Island defer={{ until: 'visible' }}>
<MostViewedFooter
tabs={tabs}
sectionId="Most viewed"
Expand Down
10 changes: 5 additions & 5 deletions dotcom-rendering/src/components/FrontPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ export const FrontPage = ({ front, NAV }: Props) => {
/>
<SkipTo id="maincontent" label="Skip to main content" />
<SkipTo id="navigation" label="Skip to navigation" />
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<AlreadyVisited />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<FocusStyles />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<Metrics
commercialMetricsEnabled={
!!front.config.switches.commercialMetrics
Expand All @@ -83,10 +83,10 @@ export const FrontPage = ({ front, NAV }: Props) => {
<Island clientOnly={true}>
<SetAdTargeting adTargeting={adTargeting} />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<BrazeMessaging idApiUrl={front.config.idApiUrl} />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island clientOnly={true} defer={{ until: 'idle' }}>
<ReaderRevenueDev shouldHideReaderRevenue={false} />
</Island>
<FrontLayout front={front} NAV={NAV} />
Expand Down
4 changes: 2 additions & 2 deletions dotcom-rendering/src/components/FrontSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -697,13 +697,13 @@ export const FrontSection = ({
>
{isString(targetedTerritory) &&
isAustralianTerritory(targetedTerritory) ? (
<Island deferUntil="visible">
<Island defer={{ until: 'visible' }}>
<AustralianTerritorySwitcher
targetedTerritory={targetedTerritory}
/>
</Island>
) : showMore ? (
<Island deferUntil="interaction">
<Island defer={{ until: 'interaction' }}>
<ShowMore
title={title}
sectionId={sectionId}
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/GroupedNewsletterList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const GroupedNewslettersList = ({ groupedNewsletters }: Props) => {
<>
{groupedNewsletters.groups.map((group, index) => (
<Section fullWidth={true} key={group.title}>
<Island deferUntil="idle">
<Island defer={{ until: 'idle' }}>
<CarouselForNewsletters
heading={group.title}
onwardsSource="newsletters-page"
Expand Down
4 changes: 2 additions & 2 deletions dotcom-rendering/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ export const Header = ({
</Island>

<div css={[hasPageSkin ? pageSkinContainer : center, explicitHeight]}>
<Island deferUntil="hash" clientOnly={true}>
<Island defer={{ until: 'hash' }} clientOnly={true}>
<Snow />
</Island>
<Logo editionId={editionId} hasPageSkin={hasPageSkin} />
<Island deferUntil="idle" clientOnly={true}>
<Island defer={{ until: 'idle' }} clientOnly={true}>
<SupportTheG
urls={urls}
editionId={editionId}
Expand Down
39 changes: 39 additions & 0 deletions dotcom-rendering/src/components/Island.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @file
* Test that impossible prop combinations are caught by TypeScript.
*
* What we're really testing is that this file compiles.
*
* The tests themselves are not really testing anything, but because it's a
* *.test.tsx, Jest will run it.
*
* The test are just there to stop Jest blowing up when it gets the compiled version.
*/

import { Island } from './Island';

const Mock = () => <>🏝️</>;

() => (
<Island>
<Mock />
</Island>
);

() => (
<Island defer={{ until: 'interaction' }}>
<Mock />
</Island>
);

() => (
// @ts-expect-error -- until interaction must have
// server-rendered fallback
<Island defer={{ until: 'interaction' }} clientOnly={true}>
<Mock />
</Island>
);

// this is just to stop Jest complaining about no tests
test('this is not a real test, ignore it, it tells you nothing useful 💃', () =>
undefined);
Comment on lines +37 to +39
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a future improvement could be to devise a neat way to check types like this in the future, hopefully without the need for this test

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i promise to look at this properly 🤠

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to join to the dots #9033

Loading