A closing call to action across a full-width Golden Hour scene. The sun sets as the section comes into view and the road's lights come on; describing a trip and sending it brings out the night and the moon.
registry/blocks/golden-hour-cta.tsx
"use client";
import * as React from "react";
import { useInView } from "motion/react";
import { GoldenHour } from "@/components/ui/golden-hour";
/* ── Content ─────────────────────────────────────────────────
* Everything you'd change to make the section yours: the copy,
* the field's prompt and the hours the scene is lit for on the
* way in, once it's in view and after the visitor sends it.
* ─────────────────────────────────────────────────────────── */
const EYEBROW = "Meander";
const HEADLINE = "Your next weekend starts with one sentence.";
const SUBLINE =
"Say where you'd like to wake up. Meander plans the days around the light and links every stop to where it found it.";
const FIELD_LABEL = "Describe your trip";
const PLACEHOLDER = "A slow weekend by the sea";
const BUTTON = "Plan it";
const NOTE = "Free for your first three trips. No card needed.";
const SENT = "Planning now. Your trip and its sources land in your inbox in about a minute.";
/** Hours of the day (0–24) for the scene: scrolling toward it, once it's in view, and after sending. */
const HOURS = { before: 17.6, inView: 19.1, sent: 21.8 };
/* ── Section ─────────────────────────────────────────────── */
export function GoldenHourCta() {
const ref = React.useRef<HTMLElement>(null);
const inView = useInView(ref, { amount: 0.45 });
const [trip, setTrip] = React.useState("");
const [sent, setSent] = React.useState(false);
const hour = sent ? HOURS.sent : inView ? HOURS.inView : HOURS.before;
return (
<section ref={ref} aria-labelledby="golden-hour-cta-title" className="bg-zinc-950">
<GoldenHour
time={hour}
horizon={0.64}
className="flex min-h-[38rem] flex-col items-center px-6 pt-20 pb-64 text-center text-white sm:min-h-[44rem] sm:pt-28"
>
<p className="flex items-center gap-2 text-sm font-medium text-white/80">
<MeanderMark className="size-4" />
{EYEBROW}
</p>
<h2
id="golden-hour-cta-title"
className="mt-5 max-w-[18ch] text-4xl/[1.04] font-medium tracking-[-0.035em] text-balance sm:text-6xl/[1]"
>
{HEADLINE}
</h2>
<p className="mt-5 max-w-lg text-base/7 text-pretty text-white/80 sm:text-lg/8">{SUBLINE}</p>
<div className="mt-9 w-full max-w-xl" aria-live="polite">
{sent ? (
<p className="flex min-h-14 items-center justify-center gap-2 rounded-full bg-zinc-950/25 px-6 py-3 text-sm font-medium ring-1 ring-white/25 backdrop-blur-xl">
<CheckIcon className="size-4 shrink-0" />
{SENT}
</p>
) : (
<form
onSubmit={(event) => {
event.preventDefault();
if (trip.trim()) setSent(true);
}}
className="flex h-14 items-center gap-2 rounded-full bg-zinc-950/25 p-1.5 ring-1 ring-white/25 backdrop-blur-xl transition-shadow duration-200 focus-within:ring-white/70"
>
<label htmlFor="golden-hour-cta-trip" className="sr-only">
{FIELD_LABEL}
</label>
<input
id="golden-hour-cta-trip"
value={trip}
onChange={(event) => setTrip(event.target.value)}
placeholder={PLACEHOLDER}
autoComplete="off"
className="h-full min-w-0 flex-1 bg-transparent pl-5 text-[15px] text-white outline-none placeholder:text-white/70"
/>
<button
type="submit"
className="h-full shrink-0 rounded-full bg-white px-6 text-sm font-medium text-zinc-950 transition-[background-color,scale] duration-150 ease-out hover:bg-white/90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white active:scale-[0.97]"
>
{BUTTON}
</button>
</form>
)}
</div>
<p className="mt-4 text-sm text-white/70">{NOTE}</p>
</GoldenHour>
</section>
);
}
/* ── Icons ───────────────────────────────────────────────── */
function MeanderMark({ className }: { className?: string }) {
return (
<svg viewBox="0 0 16 16" className={className} fill="none" stroke="currentColor" strokeWidth={1.6} aria-hidden>
<path d="M3 14c0-3 4-3 4-6S4 5 6 2.5M9.5 14c0-2.5 3.5-2.5 3.5-5" strokeLinecap="round" />
</svg>
);
}
function CheckIcon({ className }: { className?: string }) {
return (
<svg viewBox="0 0 16 16" className={className} fill="none" stroke="currentColor" strokeWidth={1.8} aria-hidden>
<path d="m3.5 8.5 3 3 6-7" strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}
Live preview and the components it's built with: https://keyframeui.com/blocks/cta-sections/golden-hour-cta
