Skip to content

Commit c1e741a

Browse files
committed
Move the linear gradient blur into its own div so that it does not affect the content
1 parent 675856d commit c1e741a

1 file changed

Lines changed: 190 additions & 157 deletions

File tree

dotcom-rendering/src/components/FeatureCard.tsx

Lines changed: 190 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -164,38 +164,50 @@ const overlayMaskGradientStyles = (angle: string) => css`
164164
);
165165
`;
166166

167+
const contentOverlayStyle = css`
168+
position: absolute;
169+
bottom: 0;
170+
left: 0;
171+
width: 100%;
172+
`;
173+
167174
const overlayStyles = css`
168175
position: relative;
169176
display: flex;
170177
flex-direction: column;
171178
text-align: start;
172179
gap: ${space[1]}px;
173180
padding: ${space[9]}px ${space[2]}px ${space[2]}px;
181+
182+
/*
183+
* Ensure the waveform is behind the other elements, e.g. headline, pill.
184+
* Links define their own z-index.
185+
*/
186+
> :not(.waveform):not(a) {
187+
z-index: 1;
188+
}
189+
`;
190+
191+
const blurStyles = css`
192+
position: absolute;
193+
inset: 0;
174194
backdrop-filter: blur(12px) brightness(0.5);
175195
@supports not (backdrop-filter: blur(12px)) {
176196
background-color: ${transparentColour(sourcePalette.neutral[10], 0.7)};
177197
}
178198
${overlayMaskGradientStyles('180deg')};
199+
`;
179200

180-
/*
181-
* Ensure the waveform is behind the other elements, e.g. headline, pill.
182-
* Links define their own z-index.
183-
*/
184-
185-
> :not(.waveform):not(a) {
186-
z-index: 1;
201+
const immersiveOverlayBlurStyles = css`
202+
${from.tablet} {
203+
padding: ${space[2]}px ${space[12]}px ${space[2]}px ${space[2]}px;
204+
${overlayMaskGradientStyles('270deg')}
187205
}
188206
`;
189207

190208
const immersiveOverlayStyles = css`
191209
${from.tablet} {
192210
height: 100%;
193-
/**
194-
* Why 48px right padding?
195-
* 48px is to point at which the gradient can go behind the content whilst maintaining accessibility.
196-
*/
197-
padding: ${space[2]}px ${space[12]}px ${space[2]}px ${space[2]}px;
198-
${overlayMaskGradientStyles('270deg')}
199211
}
200212
`;
201213

@@ -644,165 +656,186 @@ export const FeatureCard = ({
644656
noPointerEvents,
645657
]}
646658
>
647-
{mainMedia?.type === 'Audio' &&
648-
!!mainMedia.podcastImage?.src &&
649-
(isImmersive ? (
650-
<Hide from="tablet">
651-
{renderPodcastImage(
659+
<div css={contentOverlayStyle}>
660+
{mainMedia?.type === 'Audio' &&
661+
!!mainMedia.podcastImage?.src &&
662+
(isImmersive ? (
663+
<Hide from="tablet">
664+
{renderPodcastImage(
665+
mainMedia.podcastImage
666+
.src,
667+
mainMedia.podcastImage
668+
.altText ?? '',
669+
false, // Immersive cards are styled as feature cards below the tablet viewport
670+
)}
671+
</Hide>
672+
) : (
673+
renderPodcastImage(
652674
mainMedia.podcastImage.src,
653675
mainMedia.podcastImage
654676
.altText ?? '',
655-
false, // Immersive cards are styled as feature cards below the tablet viewport
656-
)}
657-
</Hide>
658-
) : (
659-
renderPodcastImage(
660-
mainMedia.podcastImage.src,
661-
mainMedia.podcastImage
662-
.altText ?? '',
663-
false,
664-
)
665-
))}
666-
<div
667-
css={[
668-
overlayStyles,
669-
isImmersive &&
670-
immersiveOverlayStyles,
671-
isSelfHostedVideoWithControls &&
672-
underlineOnHoverStyles,
673-
]}
674-
>
675-
{/** Only the overlay is a link for self-hosted videos with controls. */}
676-
{isSelfHostedVideoWithControls && (
677-
<CardLink
678-
linkTo={linkTo}
679-
headlineText={headlineText}
680-
dataLinkName={dataLinkName}
681-
isExternalLink={isExternalLink}
682-
/>
683-
)}
677+
false,
678+
)
679+
))}
680+
<div
681+
css={[
682+
blurStyles,
683+
isImmersive &&
684+
immersiveOverlayBlurStyles,
685+
]}
686+
/>
684687

685-
{isImmersive &&
686-
mainMedia?.type === 'Audio' &&
687-
!!mainMedia.podcastImage?.src && (
688-
<div
689-
css={
690-
podcastImageContainerStyles
688+
<div
689+
css={[
690+
overlayStyles,
691+
isImmersive &&
692+
immersiveOverlayStyles,
693+
isSelfHostedVideoWithControls &&
694+
underlineOnHoverStyles,
695+
]}
696+
>
697+
{/** Only the overlay is a link for self-hosted videos with controls. */}
698+
{isSelfHostedVideoWithControls && (
699+
<CardLink
700+
linkTo={linkTo}
701+
headlineText={headlineText}
702+
dataLinkName={dataLinkName}
703+
isExternalLink={
704+
isExternalLink
691705
}
692-
>
693-
<Hide until="tablet">
694-
{renderPodcastImage(
695-
mainMedia
696-
.podcastImage
697-
.src,
698-
mainMedia
699-
.podcastImage
700-
.altText ?? '',
701-
true,
702-
)}
703-
</Hide>
704-
</div>
706+
/>
705707
)}
706708

707-
{/**
708-
* Without the wrapping div the headline and byline would have space
709-
* inserted between them due to being direct children of the flex container
710-
*/}
711-
<div>
712-
<CardHeadline
713-
headlineText={headlineText}
714-
format={format}
715-
fontSizes={headlineSizes}
716-
showQuotes={showQuotes}
717-
kickerText={
718-
format.design ===
719-
ArticleDesign.LiveBlog &&
720-
!kickerText
721-
? 'Live'
722-
: kickerText
723-
}
724-
showPulsingDot={
725-
format.design ===
726-
ArticleDesign.LiveBlog ||
727-
showPulsingDot
728-
}
729-
byline={byline}
730-
showByline={showByline}
731-
isExternalLink={isExternalLink}
732-
headlineColour={palette(
733-
'--feature-card-headline',
734-
)}
735-
kickerColour={palette(
736-
'--feature-card-kicker-text',
737-
)}
738-
quoteColour={palette(
739-
'--feature-card-quote-icon',
709+
{isImmersive &&
710+
mainMedia?.type === 'Audio' &&
711+
!!mainMedia.podcastImage
712+
?.src && (
713+
<div
714+
css={
715+
podcastImageContainerStyles
716+
}
717+
>
718+
<Hide until="tablet">
719+
{renderPodcastImage(
720+
mainMedia
721+
.podcastImage
722+
.src,
723+
mainMedia
724+
.podcastImage
725+
.altText ??
726+
'',
727+
true,
728+
)}
729+
</Hide>
730+
</div>
740731
)}
741-
/>
742-
</div>
743-
744-
{!isUndefined(starRating) && (
745-
<StarRating
746-
rating={starRating}
747-
size={starRatingSize}
748-
useAlternativeTheme={true}
749-
/>
750-
)}
751732

752-
{!!trailText && (
753-
<div css={trailTextWrapper}>
754-
<TrailText
755-
trailText={trailText}
756-
trailTextColour={palette(
757-
'--feature-card-trail-text',
733+
{/**
734+
* Without the wrapping div the headline and byline would have space
735+
* inserted between them due to being direct children of the flex container
736+
*/}
737+
<div>
738+
<CardHeadline
739+
headlineText={headlineText}
740+
format={format}
741+
fontSizes={headlineSizes}
742+
showQuotes={showQuotes}
743+
kickerText={
744+
format.design ===
745+
ArticleDesign.LiveBlog &&
746+
!kickerText
747+
? 'Live'
748+
: kickerText
749+
}
750+
showPulsingDot={
751+
format.design ===
752+
ArticleDesign.LiveBlog ||
753+
showPulsingDot
754+
}
755+
byline={byline}
756+
showByline={showByline}
757+
isExternalLink={
758+
isExternalLink
759+
}
760+
headlineColour={palette(
761+
'--feature-card-headline',
762+
)}
763+
kickerColour={palette(
764+
'--feature-card-kicker-text',
765+
)}
766+
quoteColour={palette(
767+
'--feature-card-quote-icon',
758768
)}
759-
trailTextSize="regular"
760-
padBottom={false}
761-
hideUntil="tablet"
762769
/>
763770
</div>
764-
)}
765771

766-
<CardFooter
767-
format={format}
768-
age={
769-
showCardAge ? (
770-
<FeatureCardCardAge
771-
webPublicationDate={
772-
webPublicationDate
773-
}
774-
showClock={!!showClock}
775-
serverTime={serverTime}
776-
isStorylines={
777-
isStorylines
778-
}
779-
/>
780-
) : undefined
781-
}
782-
commentCount={
783-
showCommentCount ? (
784-
<FeatureCardCommentCount
785-
linkTo={linkTo}
786-
discussionId={
787-
discussionId
788-
}
789-
discussionApiUrl={
790-
discussionApiUrl
791-
}
792-
/>
793-
) : undefined
794-
}
795-
showLivePlayable={false}
796-
isNewsletter={isNewsletter}
797-
mainMedia={mainMedia}
798-
/>
772+
{!isUndefined(starRating) && (
773+
<StarRating
774+
rating={starRating}
775+
size={starRatingSize}
776+
useAlternativeTheme={true}
777+
/>
778+
)}
799779

800-
{!isImmersive &&
801-
mainMedia?.type === 'Audio' &&
802-
renderWaveform(
803-
mainMedia.duration,
804-
233,
780+
{!!trailText && (
781+
<div css={trailTextWrapper}>
782+
<TrailText
783+
trailText={trailText}
784+
trailTextColour={palette(
785+
'--feature-card-trail-text',
786+
)}
787+
trailTextSize="regular"
788+
padBottom={false}
789+
hideUntil="tablet"
790+
/>
791+
</div>
805792
)}
793+
794+
<CardFooter
795+
format={format}
796+
age={
797+
showCardAge ? (
798+
<FeatureCardCardAge
799+
webPublicationDate={
800+
webPublicationDate
801+
}
802+
showClock={
803+
!!showClock
804+
}
805+
serverTime={
806+
serverTime
807+
}
808+
isStorylines={
809+
isStorylines
810+
}
811+
/>
812+
) : undefined
813+
}
814+
commentCount={
815+
showCommentCount ? (
816+
<FeatureCardCommentCount
817+
linkTo={linkTo}
818+
discussionId={
819+
discussionId
820+
}
821+
discussionApiUrl={
822+
discussionApiUrl
823+
}
824+
/>
825+
) : undefined
826+
}
827+
showLivePlayable={false}
828+
isNewsletter={isNewsletter}
829+
mainMedia={mainMedia}
830+
/>
831+
832+
{!isImmersive &&
833+
mainMedia?.type === 'Audio' &&
834+
renderWaveform(
835+
mainMedia.duration,
836+
233,
837+
)}
838+
</div>
806839
</div>
807840
</div>
808841

0 commit comments

Comments
 (0)