Merged in feat/SW-2266-campaign-hero (pull request #2344)

Feat/SW-2266 campaign hero

Approved-by: Erik Tiekstra
This commit is contained in:
Matilda Landström
2025-06-18 13:35:38 +00:00
parent db0e92ff12
commit 61317e0c94
14 changed files with 329 additions and 14 deletions
@@ -0,0 +1,86 @@
.content {
border-radius: var(--Corner-radius-Large);
transform: translateY(-170px);
margin: 0 auto -170px;
width: 90%;
padding: var(--Space-x3);
display: grid;
gap: var(--Space-x2);
}
.imageContainer {
overflow: hidden;
width: 100%;
height: 478px;
position: relative;
border-radius: var(--Corner-radius-Large);
}
.benefitList {
display: grid;
list-style-type: none;
gap: var(--Space-x05);
}
.benefitList > li {
display: flex;
gap: var(--Space-x1);
align-items: center;
}
.peach {
.content {
background-color: var(--Surface-Brand-Accent-Default);
}
.heading {
color: var(--Text-Brand-OnAccent-Heading);
}
.text {
color: var(--Text-Brand-OnPrimary-1-Default);
}
.benefitList > li {
color: var(--Surface-Brand-Primary-1-OnSurface-Accent-Secondary);
}
}
.burgundy {
.content {
background-color: var(--Surface-Brand-Primary-3-Default);
}
.heading {
color: var(--Text-Brand-OnPrimary-3-Accent);
}
.benefitList > li,
.text {
color: var(--Text-Brand-OnPrimary-3-Default);
}
}
@media screen and (min-width: 768px) {
.content {
position: relative;
width: 100%;
transform: none;
border-radius: 0;
margin: 0;
align-content: center;
}
.hero {
border-radius: var(--Corner-radius-Large);
display: grid;
grid-template-columns: repeat(3, 1fr);
overflow: hidden;
}
.imageContainer {
grid-column: span 2;
position: relative;
border-radius: 0;
}
}
@@ -0,0 +1,99 @@
/* eslint-disable formatjs/no-literal-string-in-jsx */
import { Divider } from "@scandic-hotels/design-system/Divider"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import ButtonLink from "@/components/ButtonLink"
import Image from "@/components/Image"
import { variants } from "./variants"
import styles from "./hero.module.css"
import type { HeroProps } from "./types"
export default async function CampaignHero({
image,
heading,
benefits,
rate_text,
button,
theme,
}: HeroProps) {
const classNames = variants({
theme,
})
return (
<header className={classNames}>
{image ? (
<div className={styles.imageContainer}>
<Image
src={image.url}
alt={image.meta.alt || image.meta.caption || ""}
className={styles.image}
fill
sizes="(min-width: 768px) 413px, 100vw"
focalPoint={image.focalPoint}
/>
</div>
) : null}
<div className={styles.content}>
<Typography variant="Title/xs" className={styles.heading}>
<h2>{heading}</h2>
</Typography>
{benefits?.length ? (
<ul className={styles.benefitList}>
{benefits.map((benefit) => (
<li key={benefit}>
<MaterialIcon
icon="check_circle"
color="CurrentColor"
size={20}
/>
<Typography
variant="Body/Paragraph/mdRegular"
className={styles.text}
>
<span>{benefit}</span>
</Typography>
</li>
))}
</ul>
) : null}
<Divider
color={
theme === "Peach"
? "Surface/Brand/Primary 1/OnSurface/Accent Secondary"
: "white"
}
/>
{rate_text ? (
<span className={styles.heading}>
{rate_text.bold_text ? (
<Typography variant="Title/Subtitle/lg">
<span>{rate_text.bold_text}</span>
</Typography>
) : null}
{rate_text.bold_text && rate_text.text ? " " : null}
{rate_text.text ? (
<Typography variant="Tag/sm">
<span>{rate_text.text}</span>
</Typography>
) : null}
</span>
) : null}
{button.link ? (
<ButtonLink
variant="Secondary"
color={theme === "Peach" ? "Primary" : "Inverted"}
href={button.link.url}
typography="Body/Paragraph/mdBold"
size="Medium"
>
{button.cta}
</ButtonLink>
) : null}
</div>
</header>
)
}
@@ -0,0 +1,9 @@
import type { VariantProps } from "class-variance-authority"
import type { Hero } from "@/types/trpc/routers/contentstack/campaignPage"
import type { variants } from "./variants"
export interface HeroProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof variants>,
Omit<Hero, "theme"> {}
@@ -0,0 +1,17 @@
import { cva } from "class-variance-authority"
import styles from "./hero.module.css"
const config = {
variants: {
theme: {
Peach: styles.peach,
Burgundy: styles.burgundy,
},
},
defaultVariants: {
theme: "Peach",
},
} as const
export const variants = cva(styles.hero, config)
@@ -6,16 +6,6 @@
margin: 0 auto;
}
.hero {
/* Temporary styles until we add the hero */
width: 100%;
height: 478px;
display: flex;
justify-content: center;
align-items: center;
background-color: var(--Surface-Brand-Accent-Default);
}
.intro {
display: grid;
gap: var(--Space-x5);
@@ -8,6 +8,7 @@ import { getCampaignPage } from "@/lib/trpc/memoizedRequests"
import Blocks from "./Blocks"
import CampaignPageSkeleton from "./CampaignPageSkeleton"
import CampaignHero from "./Hero"
import styles from "./campaignPage.module.css"
@@ -19,14 +20,13 @@ export default async function CampaignPage() {
}
const { campaignPage } = pageData
const { heading, subheading, preamble, blocks } = campaignPage
const { heading, subheading, preamble, blocks, hero } = campaignPage
return (
<>
<Suspense fallback={<CampaignPageSkeleton />}>
<div className={styles.pageContainer}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<div className={styles.hero}>---PLACE FOR THE HERO---</div>
<CampaignHero {...hero} />
<div className={styles.intro}>
<div className={styles.headingWrapper}>
<Typography variant="Title/lg">