diff --git a/components/BlurryPoster/BlurryPoster.tsx b/components/BlurryPoster/BlurryPoster.tsx index 82ab4356..39137274 100644 --- a/components/BlurryPoster/BlurryPoster.tsx +++ b/components/BlurryPoster/BlurryPoster.tsx @@ -93,42 +93,44 @@ export const BlurryPoster = ({ return ( - - - - - - {bgImageAlt - + {bgImageSrc && ( + + + + + + {bgImageAlt + + )}
)} - {/* No authors and published dates for MVP */} - {/* {byline && ( - {byline} - )} - {date && ( - - )} */} {cta && (
{cta} diff --git a/components/Hero/StoryHeroMvp.styles.ts b/components/Hero/StoryHeroMvp.styles.ts index e147ca3a..147c2407 100644 --- a/components/Hero/StoryHeroMvp.styles.ts +++ b/components/Hero/StoryHeroMvp.styles.ts @@ -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'; diff --git a/components/Hero/StoryHeroMvp.tsx b/components/Hero/StoryHeroMvp.tsx index e41b5d6a..fdb593d7 100644 --- a/components/Hero/StoryHeroMvp.tsx +++ b/components/Hero/StoryHeroMvp.tsx @@ -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 = { @@ -20,6 +21,8 @@ export type StoryHeroMvpProps = { byline?: string; publishedDate?: string; dek?: string; + heroVariant?: 'default' | 'stacked'; + heroBgColor?: SbColorPickerType; heroImage?: SbImageType; bgImage?: SbImageType; bgImageAlt?: string; @@ -46,6 +49,8 @@ export const StoryHeroMvp = ({ byline, dek, publishedDate, + heroVariant, + heroBgColor: { color: bgHexColor } = {}, heroImage: { filename, focus } = {}, bgImage: { filename: bgImageSrc, focus: bgImageFocus } = {}, bgImageAlt, @@ -67,10 +72,8 @@ export const StoryHeroMvp = ({ day: 'numeric', year: 'numeric', }); - - const Caption = hasRichText(caption) - ? - : undefined; + const hasCaption = hasRichText(caption); + const Caption = hasCaption ? : undefined; return ( - + {heroVariant === 'stacked' ? ( + + ) : ( + + )} {!!getNumBloks(heroTexturedBar) && ( )} diff --git a/components/Hero/StoryHeroStacked.styles.ts b/components/Hero/StoryHeroStacked.styles.ts new file mode 100644 index 00000000..9e9d3a96 --- /dev/null +++ b/components/Hero/StoryHeroStacked.styles.ts @@ -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'; diff --git a/components/Hero/StoryHeroStacked.tsx b/components/Hero/StoryHeroStacked.tsx new file mode 100644 index 00000000..4831df2c --- /dev/null +++ b/components/Hero/StoryHeroStacked.tsx @@ -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 ( + + + {superhead && ( + + + {superhead} + + + )} + {title && ( + + + {superhead && {`${superhead}:`}}{title} + + + )} + {dek && ( + + + {dek} + + + )} + + {imageSrc && ( + + + + + + + + {alt + + + )} + + ); +}; diff --git a/components/Hero/index.ts b/components/Hero/index.ts index d49cde69..6475fd2d 100644 --- a/components/Hero/index.ts +++ b/components/Hero/index.ts @@ -2,3 +2,4 @@ export * from './Hero'; export * from './BasicHero'; export * from './StoryHero'; export * from './StoryHeroMvp'; +export * from './StoryHeroStacked'; diff --git a/components/Storyblok/SbStoryMvp/SbStoryMvp.tsx b/components/Storyblok/SbStoryMvp/SbStoryMvp.tsx index 4e675db2..b1cbaddf 100644 --- a/components/Storyblok/SbStoryMvp/SbStoryMvp.tsx +++ b/components/Storyblok/SbStoryMvp/SbStoryMvp.tsx @@ -30,6 +30,8 @@ export const SbStoryMvp = ({ byline, dek, publishedDate, + heroVariant, + heroBgColor, heroImage, bgImage, bgImageAlt, @@ -70,6 +72,8 @@ export const SbStoryMvp = ({ dek={dek} byline={byline} publishedDate={publishedDate} + heroVariant={heroVariant} + heroBgColor={heroBgColor} heroImage={heroImage} bgImage={bgImage} bgImageAlt={bgImageAlt} diff --git a/components/Storyblok/Storyblok.types.ts b/components/Storyblok/Storyblok.types.ts index de2aab84..716215b7 100644 --- a/components/Storyblok/Storyblok.types.ts +++ b/components/Storyblok/Storyblok.types.ts @@ -50,3 +50,8 @@ export type SbColorStopProps = { stop: string; hexColor: string; }; + +// Storyblok Native Color Picker +export type SbColorPickerType = { + color?: string; +};