Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GIVCAMP-307 | Stacked story hero variant #251

Merged
merged 6 commits into from
Mar 19, 2024
Merged
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
81 changes: 38 additions & 43 deletions components/BlurryPoster/BlurryPoster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,42 +93,44 @@ export const BlurryPoster = ({

return (
<Container {...props} bgColor={bgColor} width="full" className={styles.root}>
<picture>
<source
srcSet={getProcessedImage(bgImageSrc, addBgBlur ? '1000x600' : '2000x1200', bgImageFocus)}
media="(min-width: 1200px)"
// Exact height and width don't matter as long as aspect ratio is the same as the image
width={2000}
height={1200}
/>
<source
srcSet={getProcessedImage(bgImageSrc, addBgBlur ? '600x600' : '1200x1200', bgImageFocus)}
media="(min-width: 768px)"
width={1200}
height={1200}
/>
<source
srcSet={getProcessedImage(bgImageSrc, addBgBlur ? '450x300' : '900x600', bgImageFocus)}
media="(min-width: 461px)"
width={900}
height={600}
/>
<source
srcSet={getProcessedImage(bgImageSrc, addBgBlur ? '200x300' : '600x900', bgImageFocus)}
media="(max-width: 460px)"
width={600}
height={900}
/>
<img
src={getProcessedImage(bgImageSrc, addBgBlur ? '1000x600' : '2000x1200', bgImageFocus)}
alt={bgImageAlt || ''}
width={2000}
height={1200}
aria-describedby={hasCaption && !!bgImageAlt ? 'story-hero-caption' : undefined}
className={styles.bgImage}
fetchPriority={type === 'hero' ? 'high' : 'auto'}
/>
</picture>
{bgImageSrc && (
<picture>
<source
srcSet={getProcessedImage(bgImageSrc, addBgBlur ? '1000x600' : '2000x1200', bgImageFocus)}
media="(min-width: 1200px)"
// Exact height and width don't matter as long as aspect ratio is the same as the image
width={2000}
height={1200}
/>
<source
srcSet={getProcessedImage(bgImageSrc, addBgBlur ? '600x600' : '1200x1200', bgImageFocus)}
media="(min-width: 768px)"
width={1200}
height={1200}
/>
<source
srcSet={getProcessedImage(bgImageSrc, addBgBlur ? '450x300' : '900x600', bgImageFocus)}
media="(min-width: 461px)"
width={900}
height={600}
/>
<source
srcSet={getProcessedImage(bgImageSrc, addBgBlur ? '200x300' : '600x900', bgImageFocus)}
media="(max-width: 460px)"
width={600}
height={900}
/>
<img
src={getProcessedImage(bgImageSrc, addBgBlur ? '1000x600' : '2000x1200', bgImageFocus)}
alt={bgImageAlt || ''}
width={2000}
height={1200}
aria-describedby={hasCaption && !!bgImageAlt ? 'story-hero-caption' : undefined}
className={styles.bgImage}
fetchPriority={type === 'hero' ? 'high' : 'auto'}
/>
</picture>
)}
<div className={cnb(styles.blurWrapper(
addBgBlur,
!!darkOverlay && darkOverlay !== 'none', type, bgColor,
Expand Down Expand Up @@ -202,13 +204,6 @@ export const BlurryPoster = ({
{body}
</Paragraph>
)}
{/* No authors and published dates for MVP */}
{/* {byline && (
<Text>{byline}</Text>
)}
{date && (
<time dateTime={publishedDate}>{formattedDate}</time>
)} */}
{cta && (
<div className={styles.cta}>
{cta}
Expand Down
27 changes: 0 additions & 27 deletions components/Hero/StoryHeroMvp.styles.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,3 @@
import { cnb } from 'cnbuilder';

export const root = 'relative';

export const imageCrops = {
'1x1': '1200x1200',
'2x1': '2000x1000',
'3x2': '2100x1400',
'5x8': '1000x1600',
'16x9': '2000x1125',
'free': '2000x0',
};
export type ImageCropType = keyof typeof imageCrops;

export const mobileImageCrops = {
'1x1': '1000x1000',
'2x1': '1000x500',
'3x2': '1200x800',
'5x8': '1000x1600',
'16x9': '1600x900',
'free': '1000x0',
};

export const image = (renderTwoImages: boolean) => cnb(
'size-full',
renderTwoImages ? 'hidden lg:block' : '',
);
export const mobileImage = 'size-full lg:hidden';
export const captionWrapper = 'mt-06em';
export const caption = 'caption *:leading-display mt-08em max-w-prose-wide';
81 changes: 50 additions & 31 deletions components/Hero/StoryHeroMvp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { Container } from '@/components/Container';
import { BlurryPoster } from '@/components/BlurryPoster';
import { CreateBloks } from '@/components/CreateBloks';
import { RichText } from '@/components/RichText';
import { type SbImageType, type SbTypographyProps } from '@/components/Storyblok/Storyblok.types';
import { StoryHeroStacked } from '@/components/Hero/StoryHeroStacked';
import { type SbImageType, type SbTypographyProps, type SbColorPickerType } from '@/components/Storyblok/Storyblok.types';
import { type SbBlokData } from '@storyblok/react/rsc';
import { paletteAccentColors, type PaletteAccentHexColorType } from '@/utilities/colorPalettePlugin';
import { getNumBloks } from '@/utilities/getNumBloks';
import { hasRichText } from '@/utilities/hasRichText';
import{ type HeroOverlayType } from '@/utilities/datasource';
import { type HeroOverlayType } from '@/utilities/datasource';
import * as styles from './StoryHeroMvp.styles';

export type StoryHeroMvpProps = {
Expand All @@ -20,6 +21,8 @@ export type StoryHeroMvpProps = {
byline?: string;
publishedDate?: string;
dek?: string;
heroVariant?: 'default' | 'stacked';
heroBgColor?: SbColorPickerType;
heroImage?: SbImageType;
bgImage?: SbImageType;
bgImageAlt?: string;
Expand All @@ -46,6 +49,8 @@ export const StoryHeroMvp = ({
byline,
dek,
publishedDate,
heroVariant,
heroBgColor: { color: bgHexColor } = {},
heroImage: { filename, focus } = {},
bgImage: { filename: bgImageSrc, focus: bgImageFocus } = {},
bgImageAlt,
Expand All @@ -67,42 +72,56 @@ export const StoryHeroMvp = ({
day: 'numeric',
year: 'numeric',
});

const Caption = hasRichText(caption)
? <RichText textColor="black-70" wysiwyg={caption} className={styles.caption} />
: undefined;
const hasCaption = hasRichText(caption);
const Caption = hasCaption ? <RichText textColor="black-70" wysiwyg={caption} className={styles.caption} /> : undefined;

return (
<Container
as="header"
width="full"
className={styles.root}
>
<BlurryPoster
type="hero"
isTwoCol={useTwoColLayout}
heading={title}
superhead={superhead}
customHeading={customHeading}
headingLevel="h1"
headingFont={headingFont === 'druk' ? 'druk' : 'serif'}
isSmallHeading={isSmallHeading}
byline={byline}
publishedDate={formattedDate}
body={dek}
imageSrc={filename}
imageFocus={focus}
alt={alt}
bgImageSrc={bgImageSrc}
bgImageFocus={bgImageFocus}
bgImageAlt={bgImageAlt}
bgColor={isLightHero ? 'white' : 'black'}
addBgBlur={addBgBlur}
darkOverlay={darkOverlay}
imageOnLeft={isLeftImage}
tabColor={paletteAccentColors[tabColorValue]}
hasCaption={hasRichText(caption)}
/>
{heroVariant === 'stacked' ? (
<StoryHeroStacked
title={title}
superhead={superhead}
headingFont={headingFont}
isSmallHeading={isSmallHeading}
dek={dek}
heroBgColor={bgHexColor}
imageSrc={filename}
imageFocus={focus}
alt={alt}
isLightHero={isLightHero}
hasCaption={hasCaption}
/>
) : (
<BlurryPoster
type="hero"
isTwoCol={useTwoColLayout}
heading={title}
superhead={superhead}
customHeading={customHeading}
headingLevel="h1"
headingFont={headingFont === 'druk' ? 'druk' : 'serif'}
isSmallHeading={isSmallHeading}
byline={byline}
publishedDate={formattedDate}
body={dek}
imageSrc={filename}
imageFocus={focus}
alt={alt}
bgImageSrc={bgImageSrc}
bgImageFocus={bgImageFocus}
bgImageAlt={bgImageAlt}
bgColor={isLightHero ? 'white' : 'black'}
addBgBlur={addBgBlur}
darkOverlay={darkOverlay}
imageOnLeft={isLeftImage}
tabColor={paletteAccentColors[tabColorValue]}
hasCaption={hasCaption}
/>
)}
{!!getNumBloks(heroTexturedBar) && (
<CreateBloks blokSection={heroTexturedBar} />
)}
Expand Down
21 changes: 21 additions & 0 deletions components/Hero/StoryHeroStacked.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { cnb } from 'cnbuilder';

export const root = 'relative';

export const contentWrapper = 'mt-40 md:-mt-60 xl:mt-0';
export const superhead = (isLightHero: boolean) => cnb('cc mb-04em w-full', !isLightHero && 'text-shadow-sm');
export const heading = (
isSmallHeading?: boolean,
headingFont?: 'druk' | 'serif',
) => cnb('mb-0 text-balance mx-auto whitespace-pre-line', {
'fluid-type-7 max-w-1400': headingFont === 'druk',
'md:fluid-type-8': isSmallHeading && headingFont === 'druk',
'md:fluid-type-9': !isSmallHeading && headingFont === 'druk',
'fluid-type-5 md:fluid-type-7 max-w-1200': headingFont === 'serif',
'xl:fluid-type-8 ': headingFont === 'serif' && !isSmallHeading,
});
export const dek = 'max-w-900 text-balance mx-auto rs-mt-3';
export const image = 'rs-mt-4 w-full';
export const mobileImage = 'size-full lg:hidden';
export const captionWrapper = 'mt-06em';
export const caption = 'caption *:leading-display mt-08em max-w-prose-wide';
130 changes: 130 additions & 0 deletions components/Hero/StoryHeroStacked.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { AnimateInView } from '@/components/Animate';
import { Container } from '@/components/Container';
import {
Heading, Paragraph, Text, SrOnlyText,
} from '@/components/Typography';
import { getProcessedImage } from '@/utilities/getProcessedImage';
import { getSbImageSize } from '@/utilities/getSbImageSize';
import * as styles from './StoryHeroStacked.styles';

export type StoryHeroStackedProps = {
title: string;
superhead?: string;
headingFont?: 'serif' | 'druk';
isSmallHeading?: boolean;
dek?: string;
heroBgColor?: string; // Hex color value from Storyblok native color picker
imageSrc?: string;
imageFocus?: string;
alt?: string;
hasCaption?: boolean;
isLightHero?: boolean;
};

export const StoryHeroStacked = ({
title,
superhead,
headingFont,
isSmallHeading,
dek,
heroBgColor,
imageSrc,
imageFocus,
alt,
hasCaption,
isLightHero = false,
}: StoryHeroStackedProps) => {
// We keep the original image aspect ratio
const imageSize = getSbImageSize(imageSrc) || { width: 0, height: 0 };
const { width: imageWidth, height: imageHeight } = imageSize;

return (
<Container
width="full"
className={styles.root}
pt={10}
style={{ backgroundColor: heroBgColor || '#888' }}
>
<Container className={styles.contentWrapper}>
{superhead && (
<AnimateInView animation="slideUp">
<Text
size={1}
align="center"
color={isLightHero ? 'black' : 'white'}
// If there is a heading, superhead will be rendered as screen reader text as part of the heading
aria-hidden
className={styles.superhead(isLightHero)}
>
{superhead}
</Text>
</AnimateInView>
)}
{title && (
<AnimateInView animation="slideUp" delay={0.1}>
<Heading
as="h1"
align="center"
color={isLightHero ? 'black' : 'white'}
font={headingFont}
leading={headingFont === 'druk' ? 'druk' : 'tight'}
className={styles.heading(isSmallHeading, headingFont)}
>
{superhead && <SrOnlyText>{`${superhead}:`}</SrOnlyText>}{title}
</Heading>
</AnimateInView>
)}
{dek && (
<AnimateInView animation="slideUp" delay={0.2}>
<Paragraph
variant="overview"
weight="normal"
leading="display"
align="center"
className={styles.dek}
color={isLightHero ? 'black' : 'white'}
noMargin
>
{dek}
</Paragraph>
</AnimateInView>
)}
</Container>
{imageSrc && (
<AnimateInView animation="zoomSharpen" duration={1}>
<picture>
<source
srcSet={getProcessedImage(imageSrc, '2000x0', imageFocus)}
media="(min-width: 1500px)"
/>
<source
srcSet={getProcessedImage(imageSrc, '1500x0', imageFocus)}
media="(min-width: 1200px)"
/>
<source
srcSet={getProcessedImage(imageSrc, '1200x0', imageFocus)}
media="(min-width: 768px)"
/>
<source
srcSet={getProcessedImage(imageSrc, '800x0', imageFocus)}
media="(min-width: 576px)"
/>
<source
srcSet={getProcessedImage(imageSrc, '600x0', imageFocus)}
media="(max-width: 575px)"
/>
<img
src={getProcessedImage(imageSrc, '2000x0', imageFocus)}
alt={alt || ''}
aria-describedby={hasCaption ? 'story-hero-caption' : undefined}
fetchPriority="high"
width={imageWidth}
height={imageHeight}
className={styles.image}
/>
</picture>
</AnimateInView>
)}
</Container>
);
};
Loading
Loading