Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
domlander committed Jan 20, 2025
1 parent 1d04e41 commit 236955e
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 107 deletions.
12 changes: 12 additions & 0 deletions dotcom-rendering/src/components/Card/components/CardFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { css } from '@emotion/react';
import { palette, space, textSansBold12 } from '@guardian/source/foundations';
import { SvgCamera } from '@guardian/source/react-components';
import { Pill } from '../../../components/Pill';
import { SvgMediaControlsPlay } from '../../../components/SvgMediaControlsPlay';
import { type ArticleFormat, ArticleSpecial } from '../../../lib/articleFormat';
import type { MainMedia } from '../../../types/mainMedia';

Expand Down Expand Up @@ -63,6 +64,17 @@ export const CardFooter = ({
return <footer css={labStyles}>{cardBranding}</footer>;
}

if (mediaType === 'Audio') {
return (
<footer css={contentStyles}>
<Pill
content={<time>3:35</time>}
icon={<SvgMediaControlsPlay />}
/>
</footer>
);
}

if (mediaType === 'Gallery') {
return (
<footer css={contentStyles}>
Expand Down
13 changes: 13 additions & 0 deletions dotcom-rendering/src/components/FeatureCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,19 @@ export const Opinion: Story = {
},
};

export const Podcast: Story = {
args: {
image: {
src: 'https://media.guim.co.uk/ecb7f0bebe473d6ef1375b5cb60b78f9466a5779/0_229_3435_2061/master/3435.jpg',
altText: 'alt text',
},
mainMedia: {
type: 'Audio',
duration: 120,
},
},
};

export const Gallery: Story = {
args: {
image: {
Expand Down
243 changes: 139 additions & 104 deletions dotcom-rendering/src/components/FeatureCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
DCRSupportingContent,
} from '../types/front';
import type { MainMedia } from '../types/mainMedia';
import type { PodcastSeriesImage } from '../types/tag';
import { CardAge as AgeStamp } from './Card/components/CardAge';
import { CardFooter } from './Card/components/CardFooter';
import { CardLink } from './Card/components/CardLink';
Expand Down Expand Up @@ -74,6 +75,7 @@ export type Props = {
aspectRatio?: AspectRatio;
showQuotes?: boolean;
galleryCount?: number;
podcastImage?: PodcastSeriesImage;
};

const baseCardStyles = css`
Expand Down Expand Up @@ -117,6 +119,13 @@ const hoverStyles = css`
}
`;

const contentStyles = css`
position: absolute;
bottom: 0;
left: 0;
width: 100%;
`;

/**
* Image mask gradient has additional colour stops to emulate a non-linear
* ease in / ease out curve to make the transition smoother. Values were
Expand All @@ -126,14 +135,9 @@ const hoverStyles = css`
* https://css-tricks.com/easing-linear-gradients/
*/
const overlayStyles = css`
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
flex-grow: 1;
gap: ${space[1]}px;
padding: 64px ${space[2]}px ${space[2]}px;
mask-image: linear-gradient(
Expand All @@ -151,6 +155,22 @@ const overlayStyles = css`
backdrop-filter: blur(12px) brightness(0.5);
`;

const podcastImageContainerStyles = css`
position: relative;
/**
* We want this to sit 8px above the text.
* height of image (80px) + desired space above text (8px) - padding-top of text container (64px) = 24px
*/
bottom: ${space[6]}px;
left: ${space[2]}px;
z-index: ${getZIndex('card-podcast-image')};
`;

const podcastImageStyles = css`
position: absolute;
border-radius: ${space[2]}px;
`;

const starRatingWrapper = css`
background-color: ${palette('--star-rating-background')};
color: ${palette('--star-rating-fill')};
Expand Down Expand Up @@ -296,6 +316,7 @@ export const FeatureCard = ({
starRating,
showQuotes,
galleryCount,
podcastImage,
}: Props) => {
const hasSublinks = supportingContent && supportingContent.length > 0;

Expand Down Expand Up @@ -336,10 +357,6 @@ export const FeatureCard = ({
background-color: ${palette(
'--feature-card-background',
)};
img {
width: 100%;
display: block;
}
`}
>
{media.type === 'video' && (
Expand Down Expand Up @@ -395,106 +412,124 @@ export const FeatureCard = ({
{/* This image overlay is styled when the CardLink is hovered */}
<div className="image-overlay" />

<div css={overlayStyles}>
{/**
* Without the wrapping div the headline and
* byline would have space inserted between
* them due to being direct children of the
* flex container
*/}
<div>
<CardHeadline
headlineText={headlineText}
<div css={contentStyles}>
{mainMedia?.type === 'Audio' &&
podcastImage && (
<div
css={
podcastImageContainerStyles
}
>
<img
src={podcastImage.src}

Check warning

Code scanning / CodeQL

Client-side URL redirect Medium

Untrusted URL redirection depends on a
user-provided value
.

Check failure

Code scanning / CodeQL

Client-side cross-site scripting High

Cross-site scripting vulnerability due to
user-provided value
.
alt={podcastImage.altText}
width={80}
height={80}
css={podcastImageStyles}
/>
</div>
)}
<div css={overlayStyles}>
{/**
* Without the wrapping div the headline and
* byline would have space inserted between
* them due to being direct children of the
* flex container
*/}
<div>
<CardHeadline
headlineText={headlineText}
format={format}
fontSizes={headlineSizes}
showQuotes={showQuotes}
kickerText={
format.design ===
ArticleDesign.LiveBlog &&
!kickerText
? 'Live'
: kickerText
}
showPulsingDot={
format.design ===
ArticleDesign.LiveBlog ||
showPulsingDot
}
byline={byline}
showByline={showByline}
isExternalLink={isExternalLink}
headlineColour={palette(
'--feature-card-headline',
)}
kickerColour={palette(
'--feature-card-kicker-text',
)}
isBetaContainer={true}
/>
</div>

{starRating !== undefined ? (
<div css={starRatingWrapper}>
<StarRating
rating={starRating}
size="small"
/>
</div>
) : null}

{!!trailText && (
<div css={trailTextWrapper}>
<TrailText
trailText={trailText}
trailTextColour={palette(
'--feature-card-trail-text',
)}
trailTextSize={'regular'}
padBottom={false}
/>
</div>
)}
<CardFooter
format={format}
fontSizes={headlineSizes}
showQuotes={showQuotes}
kickerText={
format.design ===
ArticleDesign.LiveBlog &&
!kickerText
? 'Live'
: kickerText
age={
<CardAge
webPublicationDate={
webPublicationDate
}
showClock={!!showClock}
absoluteServerTimes={
absoluteServerTimes
}
/>
}
showPulsingDot={
format.design ===
ArticleDesign.LiveBlog ||
showPulsingDot
commentCount={
<CommentCount
linkTo={linkTo}
discussionId={discussionId}
discussionApiUrl={
discussionApiUrl
}
/>
}
byline={byline}
showByline={showByline}
isExternalLink={isExternalLink}
headlineColour={palette(
'--feature-card-headline',
)}
kickerColour={palette(
'--feature-card-kicker-text',
)}
isBetaContainer={true}
/**TODO: Determine if this is needed */
// cardBranding={
// branding ? (
// <CardBranding
// branding={branding}
// format={format}
// onwardsSource={
// onwardsSource
// }
// containerPalette={
// containerPalette
// }
// />
// ) : undefined
// }
showLivePlayable={false}
mediaType={mainMedia?.type}
galleryCount={galleryCount}
/>
</div>

{starRating !== undefined ? (
<div css={starRatingWrapper}>
<StarRating
rating={starRating}
size="small"
/>
</div>
) : null}

{!!trailText && (
<div css={trailTextWrapper}>
<TrailText
trailText={trailText}
trailTextColour={palette(
'--feature-card-trail-text',
)}
trailTextSize={'regular'}
padBottom={false}
/>
</div>
)}
<CardFooter
format={format}
age={
<CardAge
webPublicationDate={
webPublicationDate
}
showClock={!!showClock}
absoluteServerTimes={
absoluteServerTimes
}
/>
}
commentCount={
<CommentCount
linkTo={linkTo}
discussionId={discussionId}
discussionApiUrl={
discussionApiUrl
}
/>
}
/**TODO: Determine if this is needed */
// cardBranding={
// branding ? (
// <CardBranding
// branding={branding}
// format={format}
// onwardsSource={
// onwardsSource
// }
// containerPalette={
// containerPalette
// }
// />
// ) : undefined
// }
showLivePlayable={false}
mediaType={mainMedia?.type}
galleryCount={galleryCount}
/>
</div>
</div>
)}
Expand Down
4 changes: 1 addition & 3 deletions dotcom-rendering/src/components/Pill.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export const WithGalleryIcon = {

export const WithGalleryIconAndPrefix = {
args: {
content: '10',
...WithGalleryIcon.args,
prefix: 'Gallery',
icon: <SvgCamera />,
iconSide: 'right',
},
} satisfies Story;
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const ScrollableFeature = ({
mobile: 'xsmall',
}}
galleryCount={card.galleryCount}
podcastImage={card.podcastImage}
/>
</ScrollableCarousel.Item>
);
Expand Down
1 change: 1 addition & 0 deletions dotcom-rendering/src/lib/getZIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const indices = [
// See: https://www.sarasoueidan.com/blog/nested-links/
'card-nested-link',
'card-link',
'card-podcast-image',
] as const;

// Implementation code - you don't need to change this to get a new index
Expand Down

0 comments on commit 236955e

Please sign in to comment.