Merged in SW-1382-start-page-offers-section (pull request #1221)

SW-1382 start page offers section

* feat(SW-1382): Add InfoCard component to CardsGrid and StartPage

* feat(SW-1382): Add dynamic image positioning for InfoCard in CardsGrid

* refactor(SW-1382): Update InfoCard data transformation and prop naming

* fix(SW-1382): Add flex display to InfoCard image container


Approved-by: Christian Andolf
Approved-by: Erik Tiekstra
This commit is contained in:
Chuma Mcphoy (We Ahead)
2025-01-29 10:21:33 +00:00
parent ca42876eb8
commit b57174647f
17 changed files with 405 additions and 9 deletions

View File

@@ -1,3 +1,4 @@
import InfoCard from "@/components/ContentType/StartPage/InfoCard"
import SectionContainer from "@/components/Section/Container"
import SectionHeader from "@/components/Section/Header"
import Card from "@/components/TempDesignSystem/Card"
@@ -37,7 +38,7 @@ export default function CardsGrid({
topTitle={firstItem}
/>
<Grids.Stackable columns={columns}>
{cards_grid.cards.map((card) => {
{cards_grid.cards.map((card, index) => {
switch (card.__typename) {
case CardsGridEnum.cards.Card:
return (
@@ -55,6 +56,19 @@ export default function CardsGrid({
imageGradient
/>
)
case CardsGridEnum.cards.InfoCard:
return (
<InfoCard
key={card.system.uid}
scriptedTopTitle={card.scriptedTopTitle}
heading={card.heading}
bodyText={card.bodyText}
image={card.image}
primaryButton={card.primaryButton}
secondaryButton={card.secondaryButton}
imagePosition={index % 2 === 0 ? "right" : "left"}
/>
)
case CardsGridEnum.cards.TeaserCard:
return (
<TeaserCard

View File

@@ -0,0 +1,46 @@
import Image from "@/components/Image"
import Card from "@/components/TempDesignSystem/Card"
import styles from "./infoCard.module.css"
import type { InfoCardProps } from "@/types/components/blocks/infoCard"
export default function InfoCard({
scriptedTopTitle,
heading,
bodyText,
image,
primaryButton,
secondaryButton,
theme = "one",
imagePosition = "right",
}: InfoCardProps) {
return (
<article className={styles.container}>
{image ? (
<div
className={`${styles.imageContainer} ${styles[`image-${imagePosition}`]}`}
>
<Image
src={image.url}
alt={image.title}
sizes="(min-width: 768px) 724px, 358px"
width={358}
height={179}
focalPoint={image.focalPoint}
className={styles.image}
/>
</div>
) : null}
<Card
scriptedTopTitle={scriptedTopTitle}
heading={heading}
bodyText={bodyText}
primaryButton={primaryButton}
secondaryButton={secondaryButton}
className={styles.card}
theme={theme}
/>
</article>
)
}

View File

@@ -0,0 +1,47 @@
.container {
display: grid;
gap: var(--Spacing-x-quarter);
}
.image {
object-fit: cover;
overflow: hidden;
width: 100%;
height: 179px; /* Exact mobile height from Figma */
border-radius: var(--Corner-radius-Medium);
}
.imageContainer {
display: flex;
}
@media (min-width: 768px) {
.container:has(.imageContainer) {
gap: var(--Spacing-x2);
align-items: center;
}
.container:not(:has(.imageContainer)) {
grid-template-columns: 1fr;
}
.container:has(.image-right) {
grid-template-columns: 456px 1fr;
}
.container:has(.image-left) {
grid-template-columns: 1fr 456px;
}
.image-right {
order: 2;
}
.image-left {
order: 0;
}
.image {
height: 320px; /* Desktop height from Figma */
}
}

View File

@@ -2,6 +2,7 @@ import { Suspense } from "react"
import { getStartPage } from "@/lib/trpc/memoizedRequests"
import Blocks from "@/components/Blocks"
import Image from "@/components/Image"
import PageContainer from "@/components/PageContainer"
import Title from "@/components/TempDesignSystem/Text/Title"
@@ -15,7 +16,7 @@ export default async function StartPage() {
return null
}
const { header } = content.startPage
const { header, blocks } = content.startPage
return (
<PageContainer>
@@ -41,12 +42,15 @@ export default async function StartPage() {
/>
) : null}
</header>
<details
style={{ maxWidth: "100vw", overflow: "hidden", padding: "1rem 0" }}
>
<summary>JSON data</summary>
<pre>{JSON.stringify(content, null, 2)}</pre>
</details>
<main className={styles.main}>
<details
style={{ maxWidth: "100vw", overflow: "hidden", padding: "1rem 0" }}
>
<summary>JSON data</summary>
<pre>{JSON.stringify(content, null, 2)}</pre>
</details>
{blocks ? <Blocks blocks={blocks} /> : null}
</main>
<Suspense fallback={null}>
<TrackingSDK pageData={content.tracking} />
</Suspense>

View File

@@ -37,3 +37,12 @@
.topImage {
max-width: 100%;
}
.main {
display: grid;
width: 100%;
gap: var(--Spacing-x6);
margin: 0 auto;
max-width: var(--max-width-content);
padding: var(--Spacing-x4) 0;
}