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
7 changes: 0 additions & 7 deletions dotcom-rendering/src/components/Card/components/CardLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,16 @@ type Props = {
headlineText: string;
dataLinkName?: string;
isExternalLink: boolean;
trackCardClick?: () => void;
};

const InternalLink = ({
linkTo,
headlineText,
dataLinkName,
trackCardClick,
}: {
linkTo: string;
headlineText: string;
dataLinkName?: string;
trackCardClick?: () => void;
}) => {
return (
// eslint-disable-next-line jsx-a11y/anchor-has-content -- we have an aria-label attribute describing the content
Expand All @@ -42,7 +39,6 @@ const InternalLink = ({
css={fauxLinkStyles}
data-link-name={dataLinkName}
aria-label={headlineText}
onClick={trackCardClick}
/>
);
};
Expand Down Expand Up @@ -77,7 +73,6 @@ export const CardLink = ({
headlineText,
dataLinkName = 'article', //this makes sense if the link is to an article, but should this say something like "external" if it's an external link? are there any other uses/alternatives?
isExternalLink,
trackCardClick,
}: Props) => {
return (
<>
Expand All @@ -86,15 +81,13 @@ export const CardLink = ({
linkTo={linkTo}
headlineText={headlineText}
dataLinkName={dataLinkName}
trackCardClick={trackCardClick}
/>
)}
{!isExternalLink && (
<InternalLink
linkTo={linkTo}
headlineText={headlineText}
dataLinkName={dataLinkName}
trackCardClick={trackCardClick}
/>
)}
</>
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/DecideContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export const DecideContainer = ({
return <NavList trails={trails} showImage={true} />;
case 'scrollable/highlights':
return (
<Island priority="critical">
<Island priority="critical" defer={{ until: 'visible' }}>
<ScrollableHighlights trails={trails} frontId={frontId} />
</Island>
);
Expand Down
3 changes: 0 additions & 3 deletions dotcom-rendering/src/components/Masthead/HighlightsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export type HighlightsCardProps = {
byline?: string;
isExternalLink: boolean;
starRating?: Rating;
trackCardClick: () => void;
};

const container = css`
Expand Down Expand Up @@ -134,7 +133,6 @@ export const HighlightsCard = ({
byline,
isExternalLink,
starRating,
trackCardClick,
}: HighlightsCardProps) => {
const isMediaCard = isMedia(format);

Expand All @@ -146,7 +144,6 @@ export const HighlightsCard = ({
headlineText={headlineText}
dataLinkName={dataLinkName}
isExternalLink={isExternalLink}
trackCardClick={trackCardClick}
/>

<div css={content}>
Expand Down
131 changes: 2 additions & 129 deletions dotcom-rendering/src/components/ScrollableHighlights.importable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { css } from '@emotion/react';
import type { ABTestAPI as ABTestAPIType } from '@guardian/ab-core';
import { from, space } from '@guardian/source/foundations';
import {
Button,
Expand All @@ -8,16 +7,8 @@ import {
SvgChevronRightSingle,
} from '@guardian/source/react-components';
import { useEffect, useRef, useState } from 'react';
import { submitComponentEvent } from '../client/ophan/ophan';
import { getZIndex } from '../lib/getZIndex';
import { ophanComponentId } from '../lib/ophan-helpers';
import {
clearHighlightsState,
getOrderedHighlights,
onHighlightEvent,
resetHighlightsState,
} from '../lib/personaliseHighlights';
import { useAB } from '../lib/useAB';
import { palette } from '../palette';
import type { DCRFrontCard } from '../types/front';
import { HighlightsCard } from './Masthead/HighlightsCard';
Expand Down Expand Up @@ -86,10 +77,6 @@ const carouselStyles = css`
position: relative;
`;

const scrollSnapStyles = css`
scroll-snap-type: x mandatory;
`;

const itemStyles = css`
scroll-snap-align: start;
grid-area: span 1;
Expand Down Expand Up @@ -219,55 +206,12 @@ const getOphanInfo = (frontId?: string) => {
};
};

const isEqual = (
historicalHighlights: DCRFrontCard[],
currentHighlights: DCRFrontCard[],
) => {
const c = currentHighlights.map((v) => v.url);
const h = historicalHighlights.map((v) => v.url);
return c.every((v) => {
return h.includes(v);
});
};
export const ScrollableHighlights = ({ trails, frontId }: Props) => {
const carouselRef = useRef<HTMLOListElement | null>(null);
const carouselLength = trails.length;
const imageLoading = 'eager';
const [showPreviousButton, setShowPreviousButton] = useState(false);
const [showNextButton, setShowNextButton] = useState(true);
const [shouldShowHighlights, setShouldShowHighlights] = useState(false);
const [orderedTrails, setOrderedTrails] = useState<DCRFrontCard[]>(trails);

const ABTestAPI = useAB()?.api;

type Attr =
| 'click-tracking'
| 'view-tracking'
| 'click-and-view-tracking'
| 'not-in-test'
| undefined;

const getUserABAttr = (api?: ABTestAPIType): Attr => {
if (!api) return undefined;

if (api.isUserInVariant('PersonalisedHighlights', 'click-tracking')) {
return 'click-tracking';
}
if (api.isUserInVariant('PersonalisedHighlights', 'view-tracking')) {
return 'view-tracking';
}
if (
api.isUserInVariant(
'PersonalisedHighlights',
'click-and-view-tracking',
)
) {
return 'click-and-view-tracking';
}
return 'not-in-test';
};

const abTestPersonalisedHighlightAttr = getUserABAttr(ABTestAPI);

const scrollTo = (direction: 'left' | 'right') => {
if (!carouselRef.current) return;
Expand Down Expand Up @@ -302,15 +246,6 @@ export const ScrollableHighlights = ({ trails, frontId }: Props) => {
setShowNextButton(scrollLeft < maxScrollLeft);
};

useEffect(() => {
if (
abTestPersonalisedHighlightAttr === 'view-tracking' ||
abTestPersonalisedHighlightAttr === 'click-and-view-tracking'
) {
onHighlightEvent('VIEW');
}
}, [abTestPersonalisedHighlightAttr]);

useEffect(() => {
const carouselElement = carouselRef.current;
if (!carouselElement) return;
Expand All @@ -328,57 +263,11 @@ export const ScrollableHighlights = ({ trails, frontId }: Props) => {
};
}, []);

useEffect(() => {
if (abTestPersonalisedHighlightAttr === undefined) {
return;
}

if (abTestPersonalisedHighlightAttr === 'not-in-test') {
clearHighlightsState();
setOrderedTrails(trails);
setShouldShowHighlights(true);
return;
}

const personalisedHighlights = getOrderedHighlights(trails);
if (
personalisedHighlights.length === 0 ||
personalisedHighlights.length !== trails.length ||
!isEqual(personalisedHighlights, trails)
) {
/* Reset to editorial order */
resetHighlightsState(trails);
setOrderedTrails(trails);
setShouldShowHighlights(true);
return;
}
/* Otherwise, use personalised order from local storage */
setOrderedTrails(personalisedHighlights);
setShouldShowHighlights(true);
/* Fire a view event only if the container has been personalised */
void submitComponentEvent(
{
component: {
componentType: 'CONTAINER',
id: `reordered-highlights-container`,
},
action: 'VIEW',
},
'Web',
);
}, [trails, abTestPersonalisedHighlightAttr]);

const { ophanComponentLink, ophanComponentName, ophanFrontName } =
getOphanInfo(frontId);

return (
<div
css={[
containerStyles,
{ visibility: shouldShowHighlights ? 'visible' : 'hidden' },
]}
data-link-name={ophanFrontName}
>
<div css={containerStyles} data-link-name={ophanFrontName}>
<ol
data-link-name={ophanComponentLink}
data-component={ophanComponentName}
Expand All @@ -387,16 +276,10 @@ export const ScrollableHighlights = ({ trails, frontId }: Props) => {
css={[
carouselStyles,
generateCarouselColumnStyles(carouselLength),
/*
* Enable scroll-snap only when visible to prevent browser scroll anchoring.
* When items reorder, browsers try to keep previously visible items in view,
* causing unwanted scrolling. Enabling snap after reordering forces position 0.
// */
shouldShowHighlights && scrollSnapStyles,
]}
data-heatphan-type="carousel"
>
{orderedTrails.map((trail) => {
{trails.map((trail) => {
return (
<li
key={trail.url}
Expand All @@ -416,16 +299,6 @@ export const ScrollableHighlights = ({ trails, frontId }: Props) => {
showQuotedHeadline={trail.showQuotedHeadline}
mainMedia={trail.mainMedia}
starRating={trail.starRating}
trackCardClick={() => {
if (
abTestPersonalisedHighlightAttr ===
'click-tracking' ||
abTestPersonalisedHighlightAttr ===
'click-and-view-tracking'
) {
onHighlightEvent('CLICK', trail);
}
}}
/>
</li>
);
Expand Down
8 changes: 1 addition & 7 deletions dotcom-rendering/src/experiments/ab-tests.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import type { ABTest } from '@guardian/ab-core';
import { abTestTest } from './tests/ab-test-test';
import { noAuxiaSignInGate } from './tests/no-auxia-sign-in-gate';
import { personalisedHighlights } from './tests/personalised-highlights';
import { userBenefitsApi } from './tests/user-benefits-api';

// keep in sync with ab-tests in frontend
// https://github.com/guardian/frontend/tree/main/static/src/javascripts/projects/common/modules/experiments/ab-tests.ts
export const tests: ABTest[] = [
abTestTest,
userBenefitsApi,
personalisedHighlights,
noAuxiaSignInGate,
];
export const tests: ABTest[] = [abTestTest, userBenefitsApi, noAuxiaSignInGate];
43 changes: 0 additions & 43 deletions dotcom-rendering/src/experiments/tests/personalised-highlights.ts

This file was deleted.

Loading
Loading