Skip to content

Commit 12d8757

Browse files
committed
rework the footer component to simplify rendering logic
1 parent 669773f commit 12d8757

2 files changed

Lines changed: 330 additions & 184 deletions

File tree

dotcom-rendering/src/components/Card/Card.tsx

Lines changed: 39 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
import { css } from '@emotion/react';
22
import { isUndefined } from '@guardian/libs';
33
import { between, from, space, until } from '@guardian/source/foundations';
4-
import { Hide, Link, SvgCamera } from '@guardian/source/react-components';
4+
import { Hide } from '@guardian/source/react-components';
55
import {
66
ArticleDesign,
77
type ArticleFormat,
88
ArticleSpecial,
99
} from '../../lib/articleFormat';
1010
import { isMediaCard } from '../../lib/cardHelpers';
11-
import { isWithinTwelveHours, secondsToDuration } from '../../lib/formatTime';
11+
import { secondsToDuration } from '../../lib/formatTime';
1212
import { appendLinkNameMedia } from '../../lib/getDataLinkName';
1313
import { getZIndex } from '../../lib/getZIndex';
1414
import { getOphanComponents } from '../../lib/labs';
15-
import { DISCUSSION_ID_DATA_ATTRIBUTE } from '../../lib/useCommentCount';
1615
import { BETA_CONTAINERS } from '../../model/enhanceCollections';
1716
import { palette } from '../../palette';
1817
import type { Branding } from '../../types/branding';
@@ -31,7 +30,6 @@ import type { MainMedia } from '../../types/mainMedia';
3130
import type { OnwardsSource } from '../../types/onwards';
3231
import { Avatar } from '../Avatar';
3332
import { BrandingLabel } from '../BrandingLabel';
34-
import { CardCommentCount } from '../CardCommentCount.importable';
3533
import { CardHeadline, type ResponsiveFontSize } from '../CardHeadline';
3634
import type { Loading } from '../CardPicture';
3735
import { CardPicture } from '../CardPicture';
@@ -50,8 +48,7 @@ import { SupportingKeyStoriesContent } from '../SupportingKeyStoriesContent';
5048
import { SvgMediaControlsPlay } from '../SvgMediaControlsPlay';
5149
import { YoutubeBlockComponent } from '../YoutubeBlockComponent.importable';
5250
import { AvatarContainer } from './components/AvatarContainer';
53-
import { CardAge } from './components/CardAge';
54-
import { CardFooter } from './components/CardFooter';
51+
import { CardFooter } from './components/CardFooterNew';
5552
import {
5653
CardLayout,
5754
decideAvatarPosition,
@@ -337,14 +334,6 @@ const decideSublinkPosition = (
337334
return alignment === 'vertical' ? 'inner' : 'outer';
338335
};
339336

340-
const liveBulletStyles = css`
341-
width: 9px;
342-
height: 9px;
343-
border-radius: 50%;
344-
background-color: ${palette('--pill-bullet')};
345-
margin-right: ${space[1]}px;
346-
`;
347-
348337
export const Card = ({
349338
linkTo,
350339
format,
@@ -431,143 +420,6 @@ export const Card = ({
431420
*/
432421
const isVideoArticle = format.design === ArticleDesign.Video;
433422

434-
const isLabs = format.theme === ArticleSpecial.Labs;
435-
436-
const decideAge = () => {
437-
if (!webPublicationDate) return undefined;
438-
const withinTwelveHours = isWithinTwelveHours(webPublicationDate);
439-
440-
const shouldShowAge =
441-
isStorylines ||
442-
isTagPage ||
443-
!!onwardsSource ||
444-
(showAge && withinTwelveHours);
445-
446-
if (!shouldShowAge) return undefined;
447-
448-
return (
449-
<CardAge
450-
webPublication={{
451-
date: webPublicationDate,
452-
isWithinTwelveHours: withinTwelveHours,
453-
}}
454-
showClock={showClock}
455-
serverTime={serverTime}
456-
isTagPage={isTagPage}
457-
/>
458-
);
459-
};
460-
461-
const CommentCount = () =>
462-
!!discussionId && (
463-
<Link
464-
{...{
465-
[DISCUSSION_ID_DATA_ATTRIBUTE]: discussionId,
466-
}}
467-
data-ignore="global-link-styling"
468-
data-link-name="Comment count"
469-
href={`${linkTo}#comments`}
470-
cssOverrides={css`
471-
/* See: https://css-tricks.com/nested-links/ */
472-
z-index: ${getZIndex('card-nested-link')};
473-
/* The following styles turn off those provided by Link */
474-
color: inherit;
475-
/* stylelint-disable-next-line property-disallowed-list */
476-
font-family: inherit;
477-
font-size: inherit;
478-
line-height: inherit;
479-
text-decoration: none;
480-
min-height: 10px;
481-
`}
482-
>
483-
<Island priority="feature" defer={{ until: 'visible' }}>
484-
<CardCommentCount
485-
discussionApiUrl={discussionApiUrl}
486-
discussionId={discussionId}
487-
/>
488-
</Island>
489-
</Link>
490-
);
491-
492-
const MediaOrNewsletterPill = () => (
493-
<div
494-
css={css`
495-
margin-top: auto;
496-
display: flex;
497-
${isStorylines &&
498-
`
499-
flex-direction: column;
500-
gap: ${space[1]}px;
501-
align-items: flex-start;
502-
`}
503-
`}
504-
>
505-
{/* Usually, we either display the pill or the footer,
506-
but if the card appears in the storylines section on tag pages
507-
then we do want to display the date on these cards as well as the media pill.
508-
*/}
509-
{isStorylines && (
510-
<CardFooter
511-
format={format}
512-
age={decideAge()}
513-
commentCount={<CommentCount />}
514-
cardBranding={
515-
isOnwardContent ? <LabsBranding /> : undefined
516-
}
517-
showLivePlayable={showLivePlayable}
518-
/>
519-
)}
520-
521-
{mainMedia?.type === 'YoutubeVideo' && isVideoArticle && (
522-
<>
523-
{mainMedia.isLive ? (
524-
<Pill
525-
content="Live"
526-
icon={<div css={liveBulletStyles} />}
527-
/>
528-
) : (
529-
<Pill
530-
content={secondsToDuration(mainMedia.duration)}
531-
icon={<SvgMediaControlsPlay width={18} />}
532-
prefix="Video"
533-
/>
534-
)}
535-
</>
536-
)}
537-
{mainMedia?.type === 'Audio' && (
538-
<Pill
539-
content={mainMedia.duration}
540-
icon={<SvgMediaControlsPlay width={18} />}
541-
prefix="Podcast"
542-
/>
543-
)}
544-
{mainMedia?.type === 'Gallery' && (
545-
<Pill
546-
content={mainMedia.count}
547-
icon={<SvgCamera />}
548-
prefix="Gallery"
549-
/>
550-
)}
551-
{mainMedia?.type === 'SelfHostedVideo' &&
552-
(format.design === ArticleDesign.Video ? (
553-
<Pill
554-
content=""
555-
icon={<SvgMediaControlsPlay width={18} />}
556-
prefix="Video"
557-
/>
558-
) : format.design === ArticleDesign.Audio ? (
559-
<Pill
560-
content=""
561-
icon={<SvgMediaControlsPlay width={18} />}
562-
prefix="Podcast"
563-
/>
564-
) : format.design === ArticleDesign.Gallery ? (
565-
<Pill content="" icon={<SvgCamera />} prefix="Gallery" />
566-
) : null)}
567-
{isNewsletter && <Pill content="Newsletter" />}
568-
</div>
569-
);
570-
571423
if (snapData?.embedHtml) {
572424
return (
573425
<SnapCssSandbox snapData={snapData}>
@@ -873,7 +725,7 @@ export const Card = ({
873725
alignment="end"
874726
ophanComponentLink={dataAttributes?.ophanComponentLink}
875727
ophanComponentName={dataAttributes?.ophanComponentName}
876-
isLabs={isLabs}
728+
isLabs={format.theme === ArticleSpecial.Labs}
877729
dataTestId="card-branding-logo"
878730
/>
879731
</div>
@@ -896,7 +748,7 @@ export const Card = ({
896748
alignment="end"
897749
ophanComponentLink={dataAttributes?.ophanComponentLink}
898750
ophanComponentName={dataAttributes?.ophanComponentName}
899-
isLabs={isLabs}
751+
isLabs={format.theme === ArticleSpecial.Labs}
900752
/>
901753
</div>
902754
</>
@@ -1300,33 +1152,28 @@ export const Card = ({
13001152
/>
13011153
)}
13021154

1155+
{/** Footer rendered inside the card boundary */}
13031156
{!isOpinionCardWithAvatar && (
1304-
<>
1305-
{showPill ? (
1306-
<>
1307-
{!!branding &&
1308-
format.theme ===
1309-
ArticleSpecial.Labs &&
1310-
isOnwardContent && (
1311-
<LabsBranding />
1312-
)}
1313-
<MediaOrNewsletterPill />
1314-
</>
1315-
) : (
1316-
<CardFooter
1317-
format={format}
1318-
age={decideAge()}
1319-
commentCount={<CommentCount />}
1320-
cardBranding={
1321-
isOnwardContent ? (
1322-
<LabsBranding />
1323-
) : undefined
1324-
}
1325-
showLivePlayable={showLivePlayable}
1326-
/>
1327-
)}
1328-
</>
1157+
<CardFooter
1158+
format={format}
1159+
showLivePlayable={showLivePlayable}
1160+
showAge={showAge}
1161+
cardBranding={<LabsBranding />}
1162+
mainMedia={mainMedia}
1163+
isNewsletter={isNewsletter}
1164+
showPill={showPill}
1165+
isStorylines={isStorylines}
1166+
onwardsSource={onwardsSource}
1167+
webPublicationDate={webPublicationDate}
1168+
showClock={showClock}
1169+
serverTime={serverTime}
1170+
isTagPage={isTagPage}
1171+
discussionId={discussionId}
1172+
discussionApiUrl={discussionApiUrl}
1173+
linkTo={linkTo}
1174+
/>
13291175
)}
1176+
13301177
{showLivePlayable &&
13311178
liveUpdatesPosition === 'inner' && (
13321179
<Island
@@ -1413,20 +1260,28 @@ export const Card = ({
14131260
{isOpinionCardWithAvatar && (
14141261
<CardFooter
14151262
format={format}
1416-
age={decideAge()}
1417-
commentCount={<CommentCount />}
14181263
showLivePlayable={showLivePlayable}
1264+
showAge={showAge}
1265+
cardBranding={<LabsBranding />}
1266+
mainMedia={mainMedia}
1267+
isNewsletter={isNewsletter}
14191268
shouldReserveSpace={{
14201269
mobile: avatarPosition.mobile === 'bottom',
14211270
desktop: avatarPosition.desktop === 'bottom',
14221271
}}
1272+
showPill={showPill}
1273+
isStorylines={isStorylines}
1274+
onwardsSource={onwardsSource}
1275+
webPublicationDate={webPublicationDate}
1276+
showClock={showClock}
1277+
serverTime={serverTime}
1278+
isTagPage={isTagPage}
1279+
discussionId={discussionId}
1280+
discussionApiUrl={discussionApiUrl}
1281+
linkTo={linkTo}
14231282
/>
14241283
)}
14251284
</div>
1426-
1427-
{!isOnwardContent && format.theme === ArticleSpecial.Labs && (
1428-
<LabsBranding />
1429-
)}
14301285
</CardWrapper>
14311286
);
14321287
};

0 commit comments

Comments
 (0)