1
1
import { css } from '@emotion/react' ;
2
- import { space } from '@guardian/source/foundations' ;
2
+ import { from , space } from '@guardian/source/foundations' ;
3
3
import { SvgMediaControlsPlay } from '@guardian/source/react-components' ;
4
4
import { ArticleDesign , type ArticleFormat } from '../lib/articleFormat' ;
5
5
import { secondsToDuration } from '../lib/formatTime' ;
@@ -86,6 +86,21 @@ const contentStyles = css`
86
86
flex-direction : column;
87
87
` ;
88
88
89
+ const overlayContainerStyles = css `
90
+ position : absolute;
91
+ bottom : 0 ;
92
+ left : 0 ;
93
+ width : 100% ;
94
+ ` ;
95
+
96
+ const immersiveOverlayContainerStyles = css `
97
+ ${ from . tablet } {
98
+ height : 100% ;
99
+ top : 0 ;
100
+ width : 25% ;
101
+ }
102
+ ` ;
103
+
89
104
/**
90
105
* Image mask gradient has additional colour stops to emulate a non-linear
91
106
* ease in / ease out curve to make the transition smoother. Values were
@@ -94,14 +109,10 @@ const contentStyles = css`
94
109
* reduced.) The following article has more detail on non-linear gradients:
95
110
* https://css-tricks.com/easing-linear-gradients/
96
111
*/
97
- const overlayStyles = css `
98
- display : flex;
99
- flex-direction : column;
100
- text-align : start;
101
- gap : ${ space [ 1 ] } px;
102
- padding : 64px ${ space [ 2 ] } px ${ space [ 2 ] } px;
112
+
113
+ const overlayMaskGradientStyles = ( angle : string ) => css `
103
114
mask-image : linear-gradient(
104
- 180 deg ,
115
+ ${ angle } ,
105
116
transparent 0px ,
106
117
rgba (0 , 0 , 0 , 0.0381 ) 8px ,
107
118
rgba (0 , 0 , 0 , 0.1464 ) 16px ,
@@ -112,14 +123,31 @@ const overlayStyles = css`
112
123
rgba (0 , 0 , 0 , 0.9619 ) 56px ,
113
124
rgb (0 , 0 , 0 ) 64px
114
125
);
126
+ ` ;
127
+ const overlayStyles = css `
128
+ display : flex;
129
+ flex-direction : column;
130
+ text-align : start;
131
+ gap : ${ space [ 1 ] } px;
132
+ padding : 64px ${ space [ 2 ] } px ${ space [ 2 ] } px;
115
133
backdrop-filter : blur (12px ) brightness (0.5 );
134
+ ${ overlayMaskGradientStyles ( '180deg' ) } ;
116
135
117
136
/* Ensure the waveform is behind the other elements, e.g. headline, pill */
118
137
> * {
119
138
z-index : 1 ;
120
139
}
121
140
` ;
122
141
142
+ const immersiveOverlayStyles = css `
143
+ ${ from . tablet } {
144
+ height : 100% ;
145
+ padding : ${ space [ 2 ] } px 64px ${ space [ 2 ] } px ${ space [ 2 ] } px;
146
+ backdrop-filter : blur (12px ) brightness (0.5 );
147
+ ${ overlayMaskGradientStyles ( '270deg' ) }
148
+ }
149
+ ` ;
150
+
123
151
const podcastImageContainerStyles = css `
124
152
position : relative;
125
153
/* Needs to display above of the image mask overlay */
@@ -247,7 +275,7 @@ export type Props = {
247
275
* An immersive feature card variant. It dictates that the card has a full width background image on all breakpoints. It also dictates the the card change aspect ratio to 5:3 on desktop and 4:5 on mobile.
248
276
*
249
277
*/
250
- // isImmersive?: boolean;
278
+ isImmersive ?: boolean ;
251
279
} ;
252
280
253
281
export const FeatureCard = ( {
@@ -283,7 +311,8 @@ export const FeatureCard = ({
283
311
starRating,
284
312
showQuotes,
285
313
collectionId,
286
- isNewsletter = false , // isImmersive = false,
314
+ isNewsletter = false ,
315
+ isImmersive = false ,
287
316
} : Props ) => {
288
317
const hasSublinks = supportingContent && supportingContent . length > 0 ;
289
318
@@ -319,7 +348,7 @@ export const FeatureCard = ({
319
348
isExternalLink = { isExternalLink }
320
349
/>
321
350
) }
322
- < div css = { contentStyles } >
351
+ < div css = { [ contentStyles ] } >
323
352
{ showYoutubeVideo && (
324
353
< div
325
354
data-chromatic = "ignore"
@@ -446,12 +475,11 @@ export const FeatureCard = ({
446
475
< div className = "image-overlay" />
447
476
448
477
< div
449
- css = { css `
450
- position : absolute;
451
- bottom : 0 ;
452
- left : 0 ;
453
- width : 100% ;
454
- ` }
478
+ css = { [
479
+ overlayContainerStyles ,
480
+ isImmersive &&
481
+ immersiveOverlayContainerStyles ,
482
+ ] }
455
483
>
456
484
{ mainMedia ?. type === 'Audio' &&
457
485
! ! mainMedia . podcastImage ?. src && (
@@ -480,7 +508,13 @@ export const FeatureCard = ({
480
508
</ div >
481
509
</ div >
482
510
) }
483
- < div css = { overlayStyles } >
511
+ < div
512
+ css = { [
513
+ overlayStyles ,
514
+ isImmersive &&
515
+ immersiveOverlayStyles ,
516
+ ] }
517
+ >
484
518
{ /**
485
519
* Without the wrapping div the headline and byline would have space
486
520
* inserted between them due to being direct children of the flex container
0 commit comments