Skip to content
Closed
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
24 changes: 12 additions & 12 deletions dotcom-rendering/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
DCRSlideshowImage,
DCRSnapType,
DCRSupportingContent,
MediaCategory,
} from '../../types/front';
import type { Palette } from '../../types/palette';
import { Avatar } from '../Avatar';
Expand All @@ -20,8 +21,8 @@ import { CardPicture } from '../CardPicture';
import { Hide } from '../Hide';
import { Island } from '../Island';
import { LatestLinks } from '../LatestLinks.importable';
import { MediaDuration } from '../MediaDuration';
import { MediaMeta } from '../MediaMeta';
import { MediaPill } from '../MediaPill';
import { Slideshow } from '../Slideshow';
import { Snap } from '../Snap';
import { SnapCssSandbox } from '../SnapCssSandbox';
Expand Down Expand Up @@ -65,6 +66,7 @@ export type Props = {
showClock?: boolean;
mediaType?: MediaType;
mediaDuration?: number;
mediaCategory?: MediaCategory;
showMainVideo?: boolean;
kickerText?: string;
showPulsingDot?: boolean;
Expand Down Expand Up @@ -273,6 +275,7 @@ export const Card = ({
avatarUrl,
showClock,
mediaDuration,
mediaCategory,
showMainVideo,
kickerText,
showPulsingDot,
Expand Down Expand Up @@ -443,17 +446,14 @@ export const Card = ({
<img src={image.src} alt="" />
)}

{isPlayableMainMedia &&
mediaDuration !== undefined &&
mediaDuration > 0 && (
<MediaDuration
mediaDuration={mediaDuration}
imagePosition={imagePosition}
imagePositionOnMobile={
imagePositionOnMobile
}
/>
)}
{isPlayableMainMedia && (
<MediaPill
mediaDuration={mediaDuration}
imagePosition={imagePosition}
imagePositionOnMobile={imagePositionOnMobile}
mediaCategory={mediaCategory}
/>
)}
</ImageWrapper>
)}
<ContentWrapper
Expand Down
1 change: 1 addition & 0 deletions dotcom-rendering/src/components/FrontCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const FrontCard = (props: Props) => {
isCrossword: trail.isCrossword,
mediaType: trail.mediaType,
mediaDuration: trail.mediaDuration,
mediaCategory: trail.mediaCategory,
starRating: trail.starRating,
dataLinkName: trail.dataLinkName,
snapData: trail.snapData,
Expand Down
66 changes: 0 additions & 66 deletions dotcom-rendering/src/components/MediaDuration.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/MediaMeta.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { secondsToDuration } from './MediaDuration';
import { secondsToDuration } from './MediaPill';

describe(`MediaText`, () => {
it(`converts from a number of seconds to a duration string`, () => {
Expand Down
111 changes: 111 additions & 0 deletions dotcom-rendering/src/components/MediaPill.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { css } from '@emotion/react';
import { palette, space, textSans } from '@guardian/source-foundations';
import { Hide } from '@guardian/source-react-components';
import type { MediaCategory } from '../types/front';
import type { ImagePositionType } from './Card/components/ImageWrapper';

const pillStyles = css`
position: absolute;
top: ${space[2]}px;
right: ${space[2]}px;
${textSans.xxsmall({ fontWeight: 'bold' })};
background-color: rgba(0, 0, 0, 0.7);
color: ${palette.neutral[100]};
border-radius: ${space[3]}px;
padding: 0 6px;
display: inline-flex;
`;

const pillItemStyles = css`
/* Target all but the first element, and add a border */
:nth-of-type(n + 2) {
border-left: 1px solid rgba(255, 255, 255, 0.5);
}
`;

const pillTextStyles = css`
line-height: ${space[4]}px;
padding: ${space[1]}px 6px;
`;

const liveStyles = css`
::before {
content: '';
width: 9px;
height: 9px;
border-radius: 50%;
background-color: ${palette.news[500]};
display: inline-block;
position: relative;
margin-right: 0.1875rem;
}
`;
const capitalise = (str: string): string =>
str.charAt(0).toUpperCase() + str.slice(1);

export function secondsToDuration(secs?: number): string {
if (typeof secs === `undefined` || secs === 0) {
return ``;
}
const seconds = Number(secs);
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor((seconds % 3600) % 60);

const duration = [];
if (h > 0) {
duration.push(h);
}
if (h > 0 && m < 10) duration.push(`0${m}`); // e.g 1:01:11
else duration.push(m); // supports 0:59
if (s > 0) {
if (s < 10) duration.push(`0${s}`);
else duration.push(s);
}
return duration.join(':');
}

export const MediaPill = ({
mediaDuration,
imagePosition,
imagePositionOnMobile,
mediaCategory,
}: {
mediaDuration?: number;
imagePosition?: ImagePositionType;
mediaCategory?: MediaCategory;
imagePositionOnMobile?: ImagePositionType;
}) => {
if (imagePosition === 'left') {
return null;
}
const hasDuration = mediaDuration !== undefined && mediaDuration > 0;
const showPill = hasDuration || mediaCategory !== undefined;
if (!showPill) return null;
const isLive = mediaCategory === 'live';

const renderPill = () => (
<div css={pillStyles}>
{!!mediaCategory && (
<div css={pillItemStyles}>
<div css={[pillTextStyles, isLive && liveStyles]}>
{capitalise(mediaCategory)}
</div>
</div>
)}
{hasDuration && (
<div css={pillItemStyles}>
<div css={pillTextStyles}>
{secondsToDuration(mediaDuration)}
</div>
</div>
)}
</div>
);

if (imagePositionOnMobile === 'left') {
return <Hide until="tablet">{renderPill()}</Hide>;
}

return renderPill();
};
13 changes: 13 additions & 0 deletions dotcom-rendering/src/model/enhanceCards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
DCRSupportingContent,
FEFrontCard,
FESupportingContent,
MediaCategory,
} from '../types/front';
import type { FETagType, TagType } from '../types/tag';
import { enhanceSnaps } from './enhanceSnaps';
Expand Down Expand Up @@ -136,6 +137,17 @@ const decideMediaType = (format: ArticleFormat): MediaType | undefined => {
}
};

const decideMediaCategory = (
trail: FEFrontCard,
tags: TagType[] = [],
): MediaCategory | undefined => {
if (trail.card.isLive) return 'live';
if (tags.some(({ id }) => id === 'tone/explainers')) return 'explainer';
if (tags.some(({ id }) => id === 'tone/documentaries'))
return 'documentary';
return;
};

const decideKicker = (
trail: FEFrontCard,
cardInTagFront: boolean,
Expand Down Expand Up @@ -288,6 +300,7 @@ export const enhanceCards = (
mediaDuration:
faciaCard.properties.maybeContent?.elements.mediaAtoms[0]
?.duration,
mediaCategory: decideMediaCategory(faciaCard, tags),
showMainVideo: faciaCard.properties.showMainVideo,
isExternalLink: faciaCard.card.cardStyle.type === 'ExternalLink',
embedUri: faciaCard.properties.embedUri ?? undefined,
Expand Down
3 changes: 3 additions & 0 deletions dotcom-rendering/src/types/front.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ export type FEFrontCard = {
type: string;
};

export type MediaCategory = 'live' | 'documentary' | 'explainer';

export type DCRFrontCard = {
format: ArticleFormat;
url: string;
Expand All @@ -291,6 +293,7 @@ export type DCRFrontCard = {
avatarUrl?: string;
mediaType?: MediaType;
mediaDuration?: number;
mediaCategory?: MediaCategory;
showMainVideo: boolean;
isExternalLink: boolean;
embedUri?: string;
Expand Down