From aed45206be202b1e268827ba9c349b4b2c5ac822 Mon Sep 17 00:00:00 2001 From: Tero Tikkanen Date: Thu, 5 Oct 2023 12:38:14 +0300 Subject: [PATCH] Add alternative layout for frontPageHeroBlock --- common/images.js | 6 + components/common/StreamField.tsx | 2 +- .../contentblocks/FrontPageHeroBlock.js | 50 ------- .../contentblocks/FrontPageHeroBlock.tsx | 59 ++++++++ components/home/HeroSmallImage.tsx | 134 ++++++++++++++++++ 5 files changed, 200 insertions(+), 51 deletions(-) delete mode 100644 components/contentblocks/FrontPageHeroBlock.js create mode 100644 components/contentblocks/FrontPageHeroBlock.tsx create mode 100644 components/home/HeroSmallImage.tsx diff --git a/common/images.js b/common/images.js index cf05db50..97000460 100644 --- a/common/images.js +++ b/common/images.js @@ -59,6 +59,12 @@ images.fragments = { height focalPointX focalPointY + full: rendition(size: "1600x1600", crop: false) { + id + width + height + src + } large: rendition(size: "1600x600") { id width diff --git a/components/common/StreamField.tsx b/components/common/StreamField.tsx index 8b22b45e..c7749642 100644 --- a/components/common/StreamField.tsx +++ b/components/common/StreamField.tsx @@ -450,7 +450,7 @@ function StreamFieldBlock(props: StreamFieldBlockProps) { { - const { - id = '', - layout, - imageSrc, - imageAlign, - heading, - lead, - altText, - imageCredit, - } = props; - return ( - - ); -}; - -FrontPageHeroBlock.defaultProps = { - layout: 'big-image', - imageSrc: '', - imageAlign: 'left', - lead: '', - altText: '', - imageCredit: '', -}; - -FrontPageHeroBlock.propTypes = { - id: PropTypes.string, - layout: PropTypes.string, - imageSrc: PropTypes.string, - imageAlign: PropTypes.string, - heading: PropTypes.string.isRequired, - lead: PropTypes.string, - altText: PropTypes.string, - imageCredit: PropTypes.string, -}; - -export default FrontPageHeroBlock; diff --git a/components/contentblocks/FrontPageHeroBlock.tsx b/components/contentblocks/FrontPageHeroBlock.tsx new file mode 100644 index 00000000..75569461 --- /dev/null +++ b/components/contentblocks/FrontPageHeroBlock.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import HeroFullImage from 'components/home/HeroFullImage'; +import HeroSmallImage from 'components/home/HeroSmallImage'; + +interface FrontPageHeroProps { + id: string; + layout: 'small_image' | 'big_image'; + image: any; + imageAlign: string; + heading?: string; + lead: string; + altText: string; + imageCredit: string; +} + +const FrontPageHeroBlock = (props: FrontPageHeroProps) => { + const { + id = '', + layout = 'big_image', + image, + imageAlign, + heading, + lead, + altText, + imageCredit, + } = props; + + /* + FrontPageHeroBlock has two layout options: big_image (default) and small_image. + big_image: uses browser width background image cropped to max height with content overlay + small_image: uses text block width background image uncropped with content box below + */ + + const imageSrc = + layout === 'small_image' ? image?.full?.src : image?.large?.src; + + return layout === 'small_image' ? ( + + ) : ( + + ); +}; + +export default FrontPageHeroBlock; diff --git a/components/home/HeroSmallImage.tsx b/components/home/HeroSmallImage.tsx new file mode 100644 index 00000000..5b82a8cf --- /dev/null +++ b/components/home/HeroSmallImage.tsx @@ -0,0 +1,134 @@ +import { useTheme } from 'common/theme'; +import { Col, Container } from 'reactstrap'; +import styled from 'styled-components'; +import { useTranslation } from 'common/i18n'; +import RichText from 'components/common/RichText'; + +const Hero = styled.div` + width: 100%; + position: relative; + margin-bottom: ${(props) => props.theme.spaces.s600}; +`; + +const HeroImage = styled.img` + position: relative; + width: 100%; + display: block; +`; + +const TextWidthColumn = styled(Col)` + margin-top: -${(props) => props.theme.spaces.s300}; +`; + +const MainCard = styled.div` + position: relative; + padding: ${(props) => + `${props.theme.spaces.s200} ${props.theme.spaces.s200} ${props.theme.spaces.s100}`}; + border-radius: ${(props) => props.theme.cardBorderRadius}; + background-color: ${(props) => + props.color === 'dark' + ? props.theme.brandDark + : props.theme.themeColors.white}; + color: ${(props) => + props.color === 'dark' + ? props.theme.themeColors.white + : props.theme.neutralDark}; + box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1); + z-index: 100; + + h1 { + font-size: ${(props) => props.theme.fontSizeLg}; + margin-bottom: ${(props) => props.theme.spaces.s100}; + } + + h1, + h2, + h3, + h4 { + color: ${(props) => + props.color === 'dark' + ? props.theme.themeColors.white + : props.theme.headingsColor}; + } + + a { + color: ${(props) => + props.color === 'dark' + ? props.theme.themeColors.white + : props.theme.neutralDark}; + + &:hover { + text-decoration: none; + } + } + + .lead-content { + font-size: ${(props) => props.theme.fontSizeBase}; + line-height: ${(props) => props.theme.lineHeightMd}; + font-family: ${(props) => props.theme.fontFamilyContent}; + } +`; + +const ImageCredit = styled.span` + position: absolute; + top: 0; + right: 0; + padding: 0.25rem 0.5rem; + background-color: rgba(255, 255, 255, 0.66); + font-size: ${(props) => props.theme.fontSizeSm}; + font-family: ${(props) => props.theme.fontFamilyTiny}; + + @media (min-width: ${(props) => props.theme.breakpointMd}) { + top: inherit; + bottom: 0; + } +`; + +interface HeroSmallImageProps { + id?: string; + bgImage: string; + title?: string; + lead?: string; + altText?: string; + imageCredit?: string; +} + +const HeroSmallImage = (props: HeroSmallImageProps) => { + const { id = '', bgImage, title, lead, altText = '', imageCredit } = props; + + const { t } = useTranslation(); + const theme = useTheme(); + + const showContentBox = title || lead; + + return ( + + + + {imageCredit && ( + {`${t('image-credit')}: ${imageCredit}`} + )} + {showContentBox && ( + + +

{title}

+ {lead && } +
+
+ )} +
+
+ ); +}; + +export default HeroSmallImage;