Film strip 01
A photo framed like a frame of cine film, with the next frames peeking in above and below, a centred two-part heading and two dotted links.
Last updated
---
/**
* Film strip 01: A photo framed like a frame of cine film, with the next frames peeking in above and below, a centred two-part heading and two dotted links.
*
* @block hero
* @order 63
*/
import Section from '@/components/apogee/Section/Section.astro'
import Heading from '@/components/apogee/Heading/Heading.astro'
import Link from '@/components/apogee/Link/Link.astro'
import { srcUrl, accentRuns, type HeroContent } from '@/components/apogee/sections/_shared/spine.ts'
/** @composable */
interface Props extends HeroContent {}
const {
heading = 'A drink for *easy evenings*',
primaryAction = { label: 'Buy a case', href: '#' },
secondaryAction = { label: 'Find a stockist', href: '#' },
media = { src: 'https://picsum.photos/id/292/1800/1100', alt: '' },
} = Astro.props
const src = media && (srcUrl(media.src))
---
<!-- Always dark: a strip of film, light text on the photo. -->
<Section spacing="none" container={false} theme="dark" class="overflow-hidden">
<div class="relative flex flex-col gap-3 overflow-hidden px-3 md:px-24">
<!-- Sprocket notch on the start edge. -->
<span class="absolute start-0 top-1/2 hidden h-48 w-10 -translate-y-1/2 rounded-e-2xl border border-neutral-faded bg-page md:block" aria-hidden="true"></span>
<div class="h-10 overflow-hidden rounded-b-3xl md:h-16" aria-hidden="true">{media && <img src={src} alt="" class="size-full object-cover object-bottom opacity-60" />}</div>
<div class="relative isolate grid aspect-[4/5] place-items-center overflow-hidden rounded-3xl sm:aspect-16/10">
{media && <img src={src} alt={media.alt} loading="eager" class="absolute inset-0 -z-10 size-full object-cover" />}
<div class="absolute inset-0 -z-10 bg-[color-mix(in_oklab,var(--background-page)_45%,transparent)]" aria-hidden="true"></div>
<div class="flex flex-col items-center gap-12 px-6 text-center md:gap-20">
<Heading as="h1" size="display" class="text-balance">{accentRuns(heading).map((r) => (r.accent ? <span class="font-light italic">{r.text}</span> : r.text))}</Heading>
{(primaryAction || secondaryAction) && (
<div class="flex flex-wrap justify-center gap-x-16 gap-y-4 text-xl md:text-2xl">
{primaryAction && <Link href={primaryAction.href} color="inherit" class="decoration-dotted underline-offset-8">{primaryAction.label}</Link>}
{secondaryAction && <Link href={secondaryAction.href} color="inherit" class="decoration-dotted underline-offset-8">{secondaryAction.label}</Link>}
</div>
)}
</div>
</div>
<div class="h-10 overflow-hidden rounded-t-3xl md:h-16" aria-hidden="true">{media && <img src={src} alt="" class="size-full object-cover object-top opacity-60" />}</div>
</div>
</Section>
Show codeHide code
---
/**
* Film strip 01: A photo framed like a frame of cine film, with the next frames peeking in above and below, a centred two-part heading and two dotted links.
*
* @block hero
* @order 63
*/
import Section from '@/components/apogee/Section/Section.astro'
import Heading from '@/components/apogee/Heading/Heading.astro'
import Link from '@/components/apogee/Link/Link.astro'
import { srcUrl, accentRuns, type HeroContent } from '@/components/apogee/sections/_shared/spine.ts'
/** @composable */
interface Props extends HeroContent {}
const {
heading = 'A drink for *easy evenings*',
primaryAction = { label: 'Buy a case', href: '#' },
secondaryAction = { label: 'Find a stockist', href: '#' },
media = { src: 'https://picsum.photos/id/292/1800/1100', alt: '' },
} = Astro.props
const src = media && (srcUrl(media.src))
---
<!-- Always dark: a strip of film, light text on the photo. -->
<Section spacing="none" container={false} theme="dark" class="overflow-hidden">
<div class="relative flex flex-col gap-3 overflow-hidden px-3 md:px-24">
<!-- Sprocket notch on the start edge. -->
<span class="absolute start-0 top-1/2 hidden h-48 w-10 -translate-y-1/2 rounded-e-2xl border border-neutral-faded bg-page md:block" aria-hidden="true"></span>
<div class="h-10 overflow-hidden rounded-b-3xl md:h-16" aria-hidden="true">{media && <img src={src} alt="" class="size-full object-cover object-bottom opacity-60" />}</div>
<div class="relative isolate grid aspect-[4/5] place-items-center overflow-hidden rounded-3xl sm:aspect-16/10">
{media && <img src={src} alt={media.alt} loading="eager" class="absolute inset-0 -z-10 size-full object-cover" />}
<div class="absolute inset-0 -z-10 bg-[color-mix(in_oklab,var(--background-page)_45%,transparent)]" aria-hidden="true"></div>
<div class="flex flex-col items-center gap-12 px-6 text-center md:gap-20">
<Heading as="h1" size="display" class="text-balance">{accentRuns(heading).map((r) => (r.accent ? <span class="font-light italic">{r.text}</span> : r.text))}</Heading>
{(primaryAction || secondaryAction) && (
<div class="flex flex-wrap justify-center gap-x-16 gap-y-4 text-xl md:text-2xl">
{primaryAction && <Link href={primaryAction.href} color="inherit" class="decoration-dotted underline-offset-8">{primaryAction.label}</Link>}
{secondaryAction && <Link href={secondaryAction.href} color="inherit" class="decoration-dotted underline-offset-8">{secondaryAction.label}</Link>}
</div>
)}
</div>
</div>
<div class="h-10 overflow-hidden rounded-t-3xl md:h-16" aria-hidden="true">{media && <img src={src} alt="" class="size-full object-cover object-top opacity-60" />}</div>
</div>
</Section>Add
npx @ava-ui/apogee add hero/film-strip-01
Every piece of copy is a prop, with the sample copy as its default. Pass yours, or null to hide a part; see copy is props.