Skip to content

Commit

Permalink
allll the changes
Browse files Browse the repository at this point in the history
  • Loading branch information
abeddow91 committed Jan 23, 2025
1 parent 4806928 commit 16df27e
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 93 deletions.
189 changes: 100 additions & 89 deletions dotcom-rendering/src/components/Masthead/HighlightsCard.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import { css } from '@emotion/react';
import { isUndefined } from '@guardian/libs';
import {
between,
from,
space,
textSansBold12,
until,
} from '@guardian/source/foundations';
import { between, from, space, until } from '@guardian/source/foundations';
import { SvgCamera } from '@guardian/source/react-components';
import { ArticleDesign, type ArticleFormat } from '../../lib/articleFormat';
import { isMediaCard as isMedia } from '../../lib/cardHelpers';
import { palette } from '../../palette';
import type { StarRating as Rating } from '../../types/content';
import type { DCRFrontImage } from '../../types/front';
import type { MainMedia } from '../../types/mainMedia';
import { PodcastSeriesImage } from '../../types/tag';

Check failure on line 11 in dotcom-rendering/src/components/Masthead/HighlightsCard.tsx

View workflow job for this annotation

GitHub Actions / lint / check

All imports in the declaration are only used as types. Use `import type`
import { Avatar } from '../Avatar';
import { CardLink } from '../Card/components/CardLink';
import { CardHeadline } from '../CardHeadline';
Expand Down Expand Up @@ -41,6 +36,8 @@ export type HighlightsCardProps = {
starRating?: Rating;
galleryCount?: number;
audioDuration?: string;
/** The square podcast series image, if it exists for a card */
podcastImage?: PodcastSeriesImage;
};

const gridContainer = css`
Expand All @@ -49,11 +46,11 @@ const gridContainer = css`
/** Relative positioning is required to absolutely
position the card link overlay */
position: relative;
gap: 8px;
column-gap: ${space[2]}px;
grid-template-areas:
'headline headline'
'rating rating'
'media-icon image';
'headline headline'
'media-icon media-icon'
'. image';
/* Applied word-break: break-word to prevent text overflow
and ensure long words break onto the next line.
Expand Down Expand Up @@ -83,76 +80,50 @@ const gridContainer = css`
}
`;

const mediaGrid = css`
grid-template-areas:
'image'
'headline'
'media-icon';
${from.desktop} {
width: 300px;
grid-template-areas:
'image headline'
'image media-icon';
}
`;

const headline = css`
grid-area: headline;
margin-bottom: ${space[1]}px;
`;

const mediaIcon = css`
grid-area: media-icon;
align-self: end;
display: flex;
align-items: flex-end;
`;

const audioPill = css`
display: flex;
align-items: center;
column-gap: 4px;
`;

const audioPillIcon = css`
width: ${space[6]}px;
height: ${space[6]}px;
background-color: ${palette('--pill-background')};
border-radius: 50%;
> svg {
fill: ${palette('--highlights-container-background')};
}
`;

const audioPillText = css`
${textSansBold12};
color: ${palette('--highlight-card-audio-text')};
`;

const imageArea = css`
grid-area: image;
height: 106px;
width: 106px;
height: 112px;
width: 112px;
align-self: end;
position: relative;
${until.desktop} {
margin-top: ${space[2]}px;
}
${from.desktop} {
height: 112px;
width: 112px;
align-self: start;
}
`;

/** Avatar alignment is an exception and should align with the bottom of the card *if* there is a gap.*/
const avatarAlignmentStyles = css`
align-self: end;
`;

const hoverStyles = css`
:hover .image-overlay {
position: absolute;
bottom: 0;
right: 0;
height: 100%;
width: 100%;
border-radius: 100%;
background-color: ${palette('--card-background-hover')};
}
:hover .circular {
border-radius: 100%;
}
/* Only underline the headline element we want to target (not kickers/sublink headlines) */
:hover .card-headline .show-underline {
text-decoration: underline;
Expand All @@ -163,14 +134,64 @@ const starWrapper = css`
background-color: ${palette('--star-rating-background')};
color: ${palette('--star-rating-fill')};
width: fit-content;
height: fit-content;
grid-area: rating;
${from.desktop} {
grid-area: media-icon;
align-self: flex-end;
}
grid-area: media-icon;
align-self: flex-end;
`;

const decideImage = (
imageLoading: Loading,
format: ArticleFormat,
image?: DCRFrontImage,
podcastImage?: PodcastSeriesImage,
avatarUrl?: string,
byline?: string,
) => {
if (!image && !avatarUrl) {
return null;
}
if (avatarUrl) {
return (
<Avatar
src={avatarUrl}
alt={byline ?? ''}
shape="cutout"
imageSize="large"
/>
);
}
if (format.design === ArticleDesign.Audio && podcastImage?.src) {
return (
<>
<CardPicture
imageSize="medium"
mainImage={podcastImage.src}
alt={podcastImage.altText}
loading={imageLoading}
isCircular={false}
aspectRatio={'1:1'}
/>
<div className="image-overlay"> </div>
</>
);
}
if (!image) {
return null;
}
return (
<>
<CardPicture
imageSize="medium"
mainImage={image.src}
alt={image.altText}
loading={imageLoading}
isCircular={true}
/>
{/* This image overlay is styled when the CardLink is hovered */}
<div className="image-overlay circular"> </div>
</>
);
};

export const HighlightsCard = ({
linkTo,
format,
Expand All @@ -187,24 +208,25 @@ export const HighlightsCard = ({
starRating,
galleryCount,
audioDuration,
podcastImage,
}: HighlightsCardProps) => {
const isMediaCard = isMedia(format);

const MediaPill = () => (
<div css={mediaIcon}>
{mainMedia?.type === 'Video' && (
{mainMedia?.type === 'Video' && mainMedia.duration && (

Check failure on line 217 in dotcom-rendering/src/components/Masthead/HighlightsCard.tsx

View workflow job for this annotation

GitHub Actions / lint / check

Potentially falsey number in logical AND expression. Please use boolean
<Pill
content={secondsToDuration(mainMedia.duration)}
icon={<SvgMediaControlsPlay />}
iconSize={'small'}
/>
)}
{mainMedia?.type === 'Audio' && (
<div css={audioPill}>
<div css={audioPillIcon}>
<SvgMediaControlsPlay />
</div>
<span css={audioPillText}>{audioDuration}</span>
</div>
{mainMedia?.type === 'Audio' && audioDuration && (

Check failure on line 224 in dotcom-rendering/src/components/Masthead/HighlightsCard.tsx

View workflow job for this annotation

GitHub Actions / lint / check

Potentially falsey string in logical AND expression. Please use boolean
<Pill
content={audioDuration}
icon={<SvgMediaControlsPlay />}
iconSize={'small'}
/>
)}
{mainMedia?.type === 'Gallery' && (
<Pill
Expand All @@ -216,9 +238,10 @@ export const HighlightsCard = ({
)}
</div>
);

return (
<FormatBoundary format={format}>
<div css={[gridContainer, hoverStyles, isMediaCard && mediaGrid]}>
<div css={[gridContainer, hoverStyles]}>
<CardLink
linkTo={linkTo}
headlineText={headlineText}
Expand Down Expand Up @@ -256,27 +279,15 @@ export const HighlightsCard = ({

{!!mainMedia && isMediaCard && MediaPill()}

<div css={imageArea}>
{(avatarUrl && (
<Avatar
src={avatarUrl}
alt={byline ?? ''}
shape="cutout"
/>
)) ??
(image && (
<>
<CardPicture
imageSize="medium"
mainImage={image.src}
alt={image.altText}
loading={imageLoading}
isCircular={true}
/>
{/* This image overlay is styled when the CardLink is hovered */}
<div className="image-overlay"> </div>
</>
))}
<div css={[imageArea, avatarUrl && avatarAlignmentStyles]}>
{decideImage(
imageLoading,
format,
image,
podcastImage,
avatarUrl,
byline,
)}
</div>
</div>
</FormatBoundary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ export const ScrollableHighlights = ({ trails }: Props) => {
starRating={trail.starRating}
galleryCount={trail.galleryCount}
audioDuration={trail.audioDuration}
podcastImage={trail.podcastImage}
/>
</li>
);
Expand Down
8 changes: 4 additions & 4 deletions dotcom-rendering/src/layouts/FrontLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export const FrontLayout = ({ front, NAV }: Props) => {

const contributionsServiceUrl = getContributionsServiceUrl(front);

const { abTests, isPreview } = front.config;
// const { abTests, isPreview } = front.config;

const { absoluteServerTimes = false } = front.config.switches;

Expand All @@ -160,9 +160,9 @@ export const FrontLayout = ({ front, NAV }: Props) => {
};

const Highlights = () => {
const showHighlights =
// Must be opted into the Europe beta test or in preview
abTests.europeBetaFrontVariant === 'variant' || isPreview;
const showHighlights = true;
// Must be opted into the Europe beta test or in preview
// abTests.europeBetaFrontVariant === 'variant' || isPreview;

const highlightsCollection =
front.pressedPage.collections.find(isHighlights);
Expand Down

0 comments on commit 16df27e

Please sign in to comment.