AbiirSkincare/Hydrogen/web/app/components/BrandValues.tsx

128 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {Image} from '@shopify/hydrogen';
import {AbiirEyebrow} from '~/components/AbiirEyebrow';
import {PAGE_TITLE_TYPOGRAPHY_CLASS} from '~/lib/pageTitle';
import type {BrandValueIconKey, BrandValuesCms} from '~/lib/brandValues';
import {
BRAND_VALUES_GROQ,
MOCK_BRAND_VALUES_CMS,
} from '~/lib/brandValues';
import iconFlaskSrc from '~/assets/brand-values/icon-flask.svg';
import iconLeafSrc from '~/assets/brand-values/icon-leaf.svg';
import iconShieldSrc from '~/assets/brand-values/icon-shield.svg';
import iconSparklesSrc from '~/assets/brand-values/icon-sparkles.svg';
/**
* Sanity GROQ for this module (loader + future `useQuery`):
* @see {@link BRAND_VALUES_GROQ}
*/
export {BRAND_VALUES_GROQ, MOCK_BRAND_VALUES_CMS};
export type {BrandValuesCms, BrandValueIconKey} from '~/lib/brandValues';
/** Figma 32:7186 — raster icons exported as SVG from MCP asset URLs. */
const ICON_SRC: Record<BrandValueIconKey, string> = {
leaf: iconLeafSrc,
flaskConical: iconFlaskSrc,
shield: iconShieldSrc,
sparkles: iconSparklesSrc,
};
/**
* Figma 32:7200–32:7230 — description block horizontal padding + max width per column.
*/
const DESCRIPTION_LAYOUT = [
{wrapClass: 'px-[5px]', textClass: 'max-w-[228px]'},
{wrapClass: 'px-[9px]', textClass: 'max-w-[220px]'},
{wrapClass: '', textClass: 'max-w-[238px]'},
{wrapClass: 'px-[16px]', textClass: 'max-w-[206px]'},
] as const;
export type BrandValuesProps = {
cms: BrandValuesCms;
};
export function BrandValues({cms}: BrandValuesProps) {
return (
<section
className="w-full !py-0"
style={{background: cms.sectionBackground}}
>
{/* Figma: px-[206px] py-[94px] gap-[68px] within1710 frame */}
<div className="mx-auto flex w-full max-w-[1710px] flex-col gap-6 px-6 py-16 sm:px-10 sm:py-20 lg:gap-[68px] lg:px-[206px] lg:py-[94px]">
<header className="mx-auto w-full max-w-[1298px]">
{/* Flow layout so type size isn’t fighting absolute + min-height (which only added empty gap). */}
<div className="flex flex-col items-center gap-3 text-center lg:gap-8">
<AbiirEyebrow className="mb-0" surface="light" textCase="preserve">
{cms.eyebrow}
</AbiirEyebrow>
<h2
className={`m-0 max-w-[1298px] text-center ${PAGE_TITLE_TYPOGRAPHY_CLASS}`}
style={{color: cms.titleColor, marginBottom: '-40px'}}
>
{cms.headlinePrefix}
<span
className="font-['Cormorant_Garamond',serif] font-light italic"
style={{fontWeight: 300}}
>
{cms.headlineItalic}
</span>
</h2>
</div>
</header>
<div
className="grid w-full grid-cols-1 gap-px sm:grid-cols-2 lg:grid-cols-4 lg:grid-rows-1"
style={{background: cms.gridGutterColor}}
>
{cms.values.map((value, index) => {
const layout =
index < DESCRIPTION_LAYOUT.length
? DESCRIPTION_LAYOUT[index]
: {wrapClass: '', textClass: 'max-w-[238px]'};
return (
<div
key={`${value.iconKey}-${value.title}`}
className="relative min-h-0 py-10 sm:min-h-[200px] lg:h-[269.688px] lg:py-0"
style={{background: cms.sectionBackground}}
>
<div className="flex flex-col items-center gap-[16px] px-4 text-center sm:px-6 lg:absolute lg:left-1/2 lg:top-[42.5px] lg:w-[238px] lg:-translate-x-1/2 lg:px-0">
<div
className="flex size-[52px] shrink-0 items-center justify-center px-[16px]"
style={{background: cms.iconTileBackground}}
>
<Image
alt=""
aria-hidden
className="size-[20px] object-contain object-center"
height={20}
src={ICON_SRC[value.iconKey]}
width={20}
/>
</div>
<div className="flex h-[23.375px] w-full items-center justify-center">
<h3
className="m-0 whitespace-nowrap font-['Cormorant_Garamond',serif] text-[24px] font-medium leading-[23.375px] tracking-[-0.187px]"
style={{color: cms.titleColor}}
>
{value.title}
</h3>
</div>
<div
className={`flex w-full items-center justify-center ${layout.wrapClass}`}
>
<p
className={`m-0 w-full font-['Raleway',sans-serif] text-[16px] font-medium leading-[23.698px] ${layout.textClass}`}
style={{color: cms.bodyColor}}
>
{value.description}
</p>
</div>
</div>
</div>
);
})}
</div>
</div>
</section>
);
}