Skip to content

Commit

Permalink
Story Hero MVP
Browse files Browse the repository at this point in the history
  • Loading branch information
yvonnetangsu committed Oct 6, 2023
1 parent 2e824d5 commit f676c51
Show file tree
Hide file tree
Showing 8 changed files with 386 additions and 13 deletions.
15 changes: 8 additions & 7 deletions components/BlurryPoster/BlurryPoster.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@ export const contentWrapper = (imageOnLeft: boolean) => cnb('relative z-10', {
export const headingWrapper = (imageOnLeft: boolean) => cnb('lg:rs-mt-7 rs-mb-5', {
'lg:w-[120%] lg:-ml-[20%] 3xl:w-auto 3xl:-ml-200 lg:mr-0' : imageOnLeft,
});
export const headingInnerWrapper = (imageOnLeft: boolean) => cnb('w-full border-l-[1rem] sm:border-l-[1.4rem] md:border-l-[2rem] pl-10 pr-20 sm:pl-16 sm:pr-30 md:pl-30 md:pr-50', {
export const headingInnerWrapper = (imageOnLeft: boolean, headingFont?: 'druk' | 'serif') => cnb('w-full border-l-[1rem] sm:border-l-[1.4rem] md:border-l-[2rem] pl-10 pr-20 sm:pl-16 sm:pr-30 md:pl-30 md:pr-50', {
'lg:border-l-0 lg:border-r-[3rem] xl:border-r-[4rem] lg:pl-0 lg:pr-50 xl:pr-60': imageOnLeft,
'lg:border-l-[3rem] xl:border-l-[4rem] lg:pl-50 xl:pl-60 lg:pr-0 3xl:pl-[calc(100%-750px-40px)] lg:w-[140%] xl:w-[120%]': !imageOnLeft,
});
export const heading = (imageOnLeft: boolean, isSmallHeading: boolean) => cnb('mb-0 -mt-01em fluid-type-7', {
'3xl:pl-[calc(100%-750px-40px)] lg:w-[140%] xl:w-[130%]': !imageOnLeft,
'md:fluid-type-8 lg:fluid-type-7 3xl:fluid-type-8 4xl:text-[17.1rem]': isSmallHeading,
'md:fluid-type-9': !isSmallHeading,
export const heading = (imageOnLeft: boolean, isSmallHeading: boolean, headingFont?: 'druk' | 'serif') => cnb('mb-0 -mt-01em', {
'3xl:pl-[calc(100%-750px-40px)] lg:w-[140%] xl:w-[130%]': !imageOnLeft && headingFont === 'druk',
'fluid-type-7 md:fluid-type-8 lg:fluid-type-7 3xl:fluid-type-8 4xl:text-[17.1rem]': isSmallHeading && headingFont === 'druk',
'fluid-type-7 md:fluid-type-9': !isSmallHeading && headingFont === 'druk',
'type-6' : headingFont === 'serif',
});

export const customHeading = (imageOnLeft: boolean) => cnb('flex flex-wrap gap-x-[1em] items-center mb-0 -mt-05em lg:-mt-08em children:inline-block', {
'3xl:pl-[calc(100%-750px-40px)] lg:w-[140%] xl:w-[130%]': !imageOnLeft,
export const customHeading = (imageOnLeft: boolean, headingFont?: 'druk' | 'serif') => cnb('flex flex-wrap gap-x-[1em] items-center mb-0 -mt-05em lg:-mt-08em children:inline-block', {
'3xl:pl-[calc(100%-750px-40px)] lg:w-[140%] xl:w-[130%]': !imageOnLeft && headingFont === 'druk',
});
export const customHeadingText = (font: 'druk' | 'serif', isSmallHeading: boolean) => cnb('hyphens-auto first:ml-0 last:mr-0', {
'fluid-type-7': font === 'druk',
Expand Down
18 changes: 13 additions & 5 deletions components/BlurryPoster/BlurryPoster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type BlurryPosterProps = HTMLAttributes<HTMLDivElement> & {
imageOnLeft?: boolean;
headingLevel?: HeadingType;
heading?: string;
headingFont?: 'serif' | 'druk';
customHeading?: SbTypographyProps[];
isSmallHeading?: boolean;
addDarkOverlay?: boolean;
Expand All @@ -35,6 +36,7 @@ export const BlurryPoster = ({
bgImageFocus,
imageOnLeft,
heading,
headingFont = 'druk',
customHeading,
headingLevel = 'h2',
isSmallHeading,
Expand Down Expand Up @@ -65,22 +67,28 @@ export const BlurryPoster = ({
<FlexBox className={styles.headingWrapper(imageOnLeft)}>
<AnimateInView
animation={imageOnLeft ? 'slideInFromRight' : 'slideInFromLeft'}
className={cnb(styles.headingInnerWrapper(imageOnLeft), accentBorderColors[tabColor])}
className={cnb(styles.headingInnerWrapper(imageOnLeft, headingFont), accentBorderColors[tabColor])}
>
{/* Render all Druk font heading if custom heading is not entered */}
{heading && !customHeading?.length && (
<Heading
font="druk"
as={headingLevel}
font={headingFont}
color="white"
leading="none"
className={styles.heading(imageOnLeft, isSmallHeading)}
leading={headingFont === 'druk' ? 'none' : 'display'}
className={styles.heading(imageOnLeft, isSmallHeading, headingFont)}
>
{heading}
</Heading>
)}
{/* Render custom mixed typography heading if entered */}
{!!customHeading?.length && (
<Heading size="base" leading="none" className={styles.customHeading(imageOnLeft)}>
<Heading
as={headingLevel}
size="base"
leading="none"
className={styles.customHeading(imageOnLeft, headingFont)}
>
{customHeading.map(({text, font, italic}) => (
<Text
as="span"
Expand Down
100 changes: 100 additions & 0 deletions components/Hero/StoryHeroMvp.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { cnb } from 'cnbuilder';

export const root = 'pt-80 md:pt-120 lg:pt-150 relative';

export const content = (hasHeroImage: boolean, isVerticalHero: boolean, isLeftImage: boolean) => cnb({
'rs-mt-10 xl:mt-[32.7rem]': !hasHeroImage,
'lg:order-2': isLeftImage && isVerticalHero && hasHeroImage,
'mt-40 lg:mb-0 xl:rs-mt-8': isVerticalHero && hasHeroImage,
'rs-mb-6': hasHeroImage,
'ml-0 rs-mt-9': !isVerticalHero && hasHeroImage,
});

export const tabSection = (hasTabColor: boolean, isVerticalHero: boolean, isLeftImage: boolean) => cnb(
'rs-mb-0 cc', {
'border-l-[1rem] sm:border-l-[1.4rem] md:border-l-[2rem] lg:border-l-[2.6rem]': hasTabColor,
'3xl:pl-0 3xl:pr-[calc(100%-75rem)]': isVerticalHero && isLeftImage,
'3xl:pr-0 3xl:pl-[calc(100%-75rem)]': isVerticalHero && !isLeftImage,
},
);

export const heading = (
hasHeroImage: boolean,
hasTabColor: boolean,
isVerticalHero: boolean,
isLeftImage: boolean,
) => cnb(
'mb-0',
isVerticalHero && hasHeroImage ? 'xl:max-w-700 type-5 lg:fluid-type-5' : 'xl:max-w-1200 type-5 lg:fluid-type-6', {
'-ml-10 sm:-ml-18 lg:-ml-26': hasTabColor,
'3xl:ml-[7.4rem]': isVerticalHero && hasHeroImage && isLeftImage && hasTabColor,
'3xl:ml-100': isVerticalHero && hasHeroImage && isLeftImage && !hasTabColor,
},
);

export const storyInfo = (
hasHeroImage: boolean,
hasTabColor: boolean,
isVerticalHero: boolean,
isLeftImage: boolean,
) => cnb(
'rs-mt-1 gc-card',
isVerticalHero && hasHeroImage ? 'xl:max-w-700' : 'xl:max-w-1200', {
'-ml-10 sm:-ml-18 lg:-ml-26': hasTabColor,
'3xl:ml-[7.4rem]': isVerticalHero && hasHeroImage && isLeftImage && hasTabColor,
'3xl:ml-100': isVerticalHero && hasHeroImage && isLeftImage && !hasTabColor,
},
);

export const chipDek = (hasHeroImage: boolean, isVerticalHero: boolean, isLeftImage: boolean) => cnb(
'cc', {
'3xl:ml-100 3xl:pl-0 3xl:pr-[calc(100%-75rem)]': isVerticalHero && hasHeroImage && isLeftImage,
'3xl:pr-0 3xl:pl-[calc(100%-75rem)]': isVerticalHero && hasHeroImage && !isLeftImage,
},
);

export const body = (hasHeroImage: boolean, isVerticalHero: boolean) => cnb(
'rs-mt-4 mb-0',
isVerticalHero && hasHeroImage ? 'xl:max-w-[56rem]' : 'max-w-prose',
);

export const taxonomy = 'list-unstyled leading-display gap-x-19 gap-y-8';
export const taxonomyItem = 'inline-block';

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 imageWrapper = (isVerticalHero: boolean, isLeftImage: boolean) => cnb('rounded-br-[16vw] overflow-hidden', {
'lg:order-1': isLeftImage && isVerticalHero,
});

export const image = (renderTwoImages: boolean) => cnb(
'w-full h-full',
renderTwoImages ? 'hidden lg:block' : '',
);
export const mobileImage = 'w-full h-full lg:hidden';

export const caption = (isVerticalHero: boolean, isLeftImage: boolean) => cnb('text-current rs-mt-0 cc type-0', {
'lg:pr-0': isVerticalHero && isLeftImage,
'lg:pl-0': isVerticalHero && !isLeftImage,
});
export const captionText = (isVerticalHero: boolean, isLeftImage: boolean) => cnb(isVerticalHero ? 'max-w-prose-wide' : 'max-w-900', {
'3xl:pl-100 mr-auto': isVerticalHero && isLeftImage,
'text-right 3xl:pr-100 ml-auto ': isVerticalHero && !isLeftImage,
});
132 changes: 132 additions & 0 deletions components/Hero/StoryHeroMvp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import React from 'react';
import { cnb } from 'cnbuilder';
import { Container } from '../Container';
import { BlurryPoster } from '../BlurryPoster';
import { CtaLink } from '../Cta';
import { Grid } from '../Grid';
import { FlexBox } from '../FlexBox';
import { Heading, Text, Paragraph } from '../Typography';
import { paletteAccentColors, type PaletteAccentHexColorType } from '@/utilities/colorPalettePlugin';
import { accentBorderColors, type AccentBorderColorType } from '@/utilities/datasource';
import { getProcessedImage } from '@/utilities/getProcessedImage';
import { slugify } from '@/utilities/slugify';
import { type SbImageType } from '../Storyblok/Storyblok.types';
import * as styles from './StoryHeroMvp.styles';

export type StoryHeroMvpProps = {
title: string;
headingFont?: 'serif' | 'druk' | 'druk-small';
byline?: string;
publishedDate?: string;
dek?: string;
heroImage?: SbImageType;
bgImage?: SbImageType;
aspectRatio?: styles.ImageCropType;
mobileImage?: SbImageType;
mobileAspectRatio?: styles.ImageCropType;
imageOnLeft?: boolean;
alt?: string;
caption?: string;
isVerticalHero?: boolean;
isLeftImage?: boolean;
isLightHero?: boolean;
tabColor?: {
value?: PaletteAccentHexColorType;
}
topics?: string[];
};

export const StoryHeroMvp = ({
title,
headingFont,
byline,
dek,
publishedDate,
heroImage: { filename, focus } = {},
mobileImage: { filename: mobileFilename, focus: mobileFocus } = {},
bgImage: { filename: bgImageSrc, focus: bgImageFocus } = {},
imageOnLeft,
alt,
caption,
isVerticalHero = false,
isLeftImage = false,
isLightHero = false,
aspectRatio = isVerticalHero ? '5x8' : '2x1',
mobileAspectRatio = '1x1',
tabColor: { value: tabColorValue } = {},
topics,
}: StoryHeroMvpProps) => {
const useTwoColLayout = isVerticalHero && !!filename;
const date = publishedDate && new Date(publishedDate);
const formattedDate = date && date.toLocaleDateString('en-US', {
weekday: 'long',
month: 'long',
day: 'numeric',
year: 'numeric',
});

const cropSize = styles.imageCrops[aspectRatio];
const cropWidth = parseInt(cropSize?.split('x')[0], 10);
const cropHeight = parseInt(cropSize?.split('x')[1], 10);
const mobileCropSize = styles.mobileImageCrops[mobileAspectRatio];
const mobileCropWidth = parseInt(mobileCropSize?.split('x')[0], 10);
const mobileCropHeight = parseInt(mobileCropSize?.split('x')[1], 10);

const renderOneImage = !!filename && !mobileFilename && mobileAspectRatio === aspectRatio;
// Render 2 different images if there is both a hero image or a mobile image
// Or when there is no mobile image, but the mobile aspect ratio is different from the desktop aspect ratio
const renderTwoImages = (!!filename && !!mobileFilename) ||
(!!filename && !mobileFilename && mobileAspectRatio !== aspectRatio);

// TODO: add srcset later in GIVCAMP-71
// This one will always be rendered when there's a hero image
const RenderedDesktopImage = (
<img
alt={alt || ''}
loading="eager"
width={cropWidth}
height={cropHeight}
src={getProcessedImage(filename, cropSize, focus)}
sizes={isVerticalHero ? `${renderOneImage ? '(max-width: 991px) 100vw, 50vw}' : '50vw'}` : '100vw'}
className={styles.image(renderTwoImages)}
/>
);

// This one will only be rendered when the conditions in renderTwoImages are met
const RenderedMobileImage = renderTwoImages && (
<img
alt={alt || ''}
loading="eager"
width={mobileCropWidth}
height={mobileCropHeight}
src={getProcessedImage(mobileFilename || filename, mobileCropSize, mobileFocus || focus)}
sizes="100vw"
className={styles.mobileImage}
/>
);

return (
<Container
as="header"
width="full"
bgColor={isLightHero ? 'white' : 'black'}
pb={8}
className={styles.root}
>
<BlurryPoster
heading={title}
headingLevel="h1"
headingFont={headingFont === 'serif' ? 'serif' : 'druk'}
isSmallHeading={headingFont !== 'druk'}
byline={byline}
publishedDate={formattedDate}
body={dek}
imageSrc={filename}
bgImageSrc={bgImageSrc}
imageOnLeft={imageOnLeft}
tabColor={paletteAccentColors[tabColorValue]}
addDarkOverlay
/>
</Container>
);
};
1 change: 1 addition & 0 deletions components/Hero/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './Hero';
export * from './StoryHero';
export * from './StoryHeroMvp';
2 changes: 1 addition & 1 deletion components/Masthead/Masthead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const Masthead = ({ isLight, className }: MastheadProps) => {
<FlexBox
justifyContent="between"
alignItems="center"
className={cnb('cc transition 3xl:px-100 py-12', !isAtTop ? 'lg:py-11' : 'md:py-26')}
className={cnb('cc transition py-12', !isAtTop ? 'lg:py-11' : 'md:py-26')}
>
<LogoLockup
isLink
Expand Down
Loading

0 comments on commit f676c51

Please sign in to comment.