Hero updates

This commit is contained in:
Henrik Larsson 2023-08-13 22:38:58 +02:00
parent accfb6c38c
commit 671e3744db
4 changed files with 196 additions and 101 deletions

View File

@ -3,7 +3,7 @@ import Header from 'components/layout/header/header';
import { NextIntlClientProvider } from 'next-intl'; import { NextIntlClientProvider } from 'next-intl';
import { Inter } from 'next/font/google'; import { Inter } from 'next/font/google';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import { ReactNode } from 'react'; import { ReactNode, Suspense } from 'react';
import { supportedLanguages } from '../../i18n-config'; import { supportedLanguages } from '../../i18n-config';
import './globals.css'; import './globals.css';
@ -58,8 +58,12 @@ export default async function LocaleLayout({ children, params: { locale } }: Loc
<body className="flex min-h-screen flex-col"> <body className="flex min-h-screen flex-col">
<NextIntlClientProvider locale={locale} messages={messages}> <NextIntlClientProvider locale={locale} messages={messages}>
<Header locale={locale} /> <Header locale={locale} />
<main className="flex-1">{children}</main> <Suspense>
<Footer locale={locale} /> <main className="flex-1">{children}</main>
</Suspense>
<Suspense>
<Footer locale={locale} />
</Suspense>
</NextIntlClientProvider> </NextIntlClientProvider>
</body> </body>
</html> </html>

View File

@ -1,94 +1,88 @@
'use client'; 'use client';
import dynamic from 'next/dynamic'; import BlurbSection from '@/components/modules/blurb-section/blurb-section';
import FilteredProductList from '@/components/modules/filtered-product-list/filtered-product-list';
import Hero from '@/components/modules/hero'; import Hero from '@/components/modules/hero';
const BlurbSection = dynamic(() => import('@/components/modules/blurb-section/blurb-section')); import ReusableSection from '@/components/modules/reusable-section/reusable-section';
const FilteredProductList = dynamic( import Slider from '@/components/modules/slider/slider';
() => import('@/components/modules/filtered-product-list/filtered-product-list') import USPSection from '@/components/modules/usp-section/usp-section';
);
const ReusableSection = dynamic(
() => import('@/components/modules/reusable-section/reusable-section')
);
const Slider = dynamic(() => import('@/components/modules/slider/slider'));
const USPSection = dynamic(() => import('@/components/modules/usp-section/usp-section'));
import { InformationCircleIcon } from '@heroicons/react/24/outline'; import { InformationCircleIcon } from '@heroicons/react/24/outline';
import { Suspense } from 'react';
interface getContentComponentProps { // interface getContentComponentProps {
_type: string; // _type: string;
_key: number; // _key: number;
disabled: boolean; // disabled: boolean;
} // }
const getContentComponent = ({ _type, _key, disabled, ...rest }: getContentComponentProps) => { // const getContentComponent = ({ _type, _key, disabled, ...rest }: getContentComponentProps) => {
let Component: any; // let Component: any;
switch (_type) { // switch (_type) {
case 'hero': // case 'hero':
if (disabled !== true) { // if (disabled !== true) {
Component = Hero; // Component = Hero;
} else { // } else {
return; // return;
} // }
break; // break;
case 'slider': // case 'slider':
if (disabled !== true) { // if (disabled !== true) {
Component = Slider; // Component = Slider;
} else { // } else {
return; // return;
} // }
break; // break;
case 'filteredProductList': // case 'filteredProductList':
if (disabled !== true) { // if (disabled !== true) {
Component = FilteredProductList; // Component = FilteredProductList;
} else { // } else {
return; // return;
} // }
break; // break;
case 'blurbSection': // case 'blurbSection':
if (disabled !== true) { // if (disabled !== true) {
Component = BlurbSection; // Component = BlurbSection;
} else { // } else {
return; // return;
} // }
break; // break;
case 'uspSection': // case 'uspSection':
if (disabled !== true) { // if (disabled !== true) {
Component = USPSection; // Component = USPSection;
} else { // } else {
return; // return;
} // }
break; // break;
case 'reusableSection': // case 'reusableSection':
if (disabled !== true) { // if (disabled !== true) {
Component = ReusableSection; // Component = ReusableSection;
} else { // } else {
return; // return;
} // }
break; // break;
default: // default:
return ( // return (
<div // <div
className={`px-4 lg:px-8 2xl:px-16 ${ // className={`px-4 lg:px-8 2xl:px-16 ${
process.env.NODE_ENV === 'production' ? 'hidden' : '' // process.env.NODE_ENV === 'production' ? 'hidden' : ''
}`} // }`}
key={`index-${_key}`} // key={`index-${_key}`}
> // >
<span className="inline-flex items-center bg-red p-2 text-sm font-bold"> // <span className="inline-flex items-center bg-red p-2 text-sm font-bold">
<InformationCircleIcon className="mr-1" /> // <InformationCircleIcon className="mr-1" />
{`No matching component (Type: ${_type})`} // {`No matching component (Type: ${_type})`}
</span> // </span>
</div> // </div>
); // );
} // }
return Component ? ( // return Component ? (
<Component key={`${_key}`} {...rest} /> // <Component key={`${_key}`} {...rest} />
) : ( // ) : (
<div key={`${_key}`}>Something else</div> // <div key={`${_key}`}>Something else</div>
); // );
}; // };
interface dynamicContentManagerProps { interface dynamicContentManagerProps {
content: [] | any; content: [] | any;
@ -96,7 +90,89 @@ interface dynamicContentManagerProps {
const DynamicContentManager = ({ content }: dynamicContentManagerProps) => { const DynamicContentManager = ({ content }: dynamicContentManagerProps) => {
return ( return (
<div className="dynamic-content overflow-x-hidden">{content?.map(getContentComponent)}</div> <div className="dynamic-content overflow-x-hidden">
{content.map(
(
component: { _type: string; _key: number; disabled: boolean; rest: any } | any,
index: number
) => {
const { _type, _key, disabled, ...rest } = component;
let Component: any;
switch (_type) {
case 'hero':
if (disabled !== true) {
Component = Hero;
} else {
return;
}
break;
case 'slider':
if (disabled !== true) {
Component = Slider;
} else {
return;
}
break;
case 'filteredProductList':
if (disabled !== true) {
Component = FilteredProductList;
} else {
return;
}
break;
case 'blurbSection':
if (disabled !== true) {
Component = BlurbSection;
} else {
return;
}
break;
case 'uspSection':
if (disabled !== true) {
Component = USPSection;
} else {
return;
}
break;
case 'reusableSection':
if (disabled !== true) {
Component = ReusableSection;
} else {
return;
}
break;
default:
return (
<div
className={`px-4 lg:px-8 2xl:px-16 ${
process.env.NODE_ENV === 'production' ? 'hidden' : ''
}`}
key={`index-${_key}`}
>
<span className="inline-flex items-center bg-red p-2 text-sm font-bold">
<InformationCircleIcon className="mr-1" />
{`No matching component (Type: ${_type})`}
</span>
</div>
);
}
if (Component && index === 0) {
return <Component key={`${_key}`} {...rest} />;
} else if (Component) {
return (
<Suspense key={`${_key}`}>
<Component {...rest} />
</Suspense>
);
} else {
<div key={`${_key}`}>Something else</div>;
}
}
)}
</div>
); );
}; };

View File

@ -38,9 +38,9 @@ const Hero = ({ variant, title, text, label, image, link }: HeroProps) => {
image={image} image={image}
alt={image.alt} alt={image.alt}
priority={true} priority={true}
width={1200}
height={600}
className="absolute inset-0 z-10 h-full w-full object-cover" className="absolute inset-0 z-10 h-full w-full object-cover"
sizes="100vw"
fill
/> />
)} )}
<div className="absolute bottom-5 left-4 z-50 flex max-w-md flex-col items-start text-high-contrast lg:bottom-8 lg:left-8 lg:max-w-2xl 2xl:bottom-16 2xl:left-16"> <div className="absolute bottom-5 left-4 z-50 flex max-w-md flex-col items-start text-high-contrast lg:bottom-8 lg:left-8 lg:max-w-2xl 2xl:bottom-16 2xl:left-16">

View File

@ -13,6 +13,7 @@ interface SanityImageProps {
quality?: number; quality?: number;
sizes?: string; sizes?: string;
className?: string; className?: string;
fill?: boolean;
} }
const placeholderImg = '/product-img-placeholder.svg'; const placeholderImg = '/product-img-placeholder.svg';
@ -26,24 +27,38 @@ export default function SanityImage(props: SanityImageProps) {
height = 1080, height = 1080,
width = 1080, width = 1080,
sizes = '100vw', sizes = '100vw',
className className,
fill = false
} = props; } = props;
const rootClassName = cn('w-full h-auto', className); const rootClassName = cn('w-full h-auto', className);
const image = source?.asset?._rev ? ( const image = source?.asset?._rev ? (
<> <>
<Image {fill ? (
className={`${rootClassName}`} <Image
placeholder="blur" className={`${rootClassName}`}
width={width} placeholder="blur"
height={height} fill
alt={alt} alt={alt}
src={urlForImage(source).width(width).height(height).quality(quality).url()} src={urlForImage(source).quality(quality).url()}
sizes={sizes} sizes={sizes}
priority={priority} priority={priority}
blurDataURL={source.asset.metadata.lqip} blurDataURL={source.asset.metadata.lqip}
/> />
) : (
<Image
className={`${rootClassName}`}
placeholder="blur"
width={width}
height={height}
alt={alt}
src={urlForImage(source).width(width).height(height).quality(quality).url()}
sizes={sizes}
priority={priority}
blurDataURL={source.asset.metadata.lqip}
/>
)}
</> </>
) : ( ) : (
<> <>