Drag the dial through the day: the sun climbs and sets, the light along the ridges turns from white to gold, and the road's lights come on after dusk. "Your time" jumps to your own clock.
registry/demos/golden-hour-demo.tsx
"use client";
import * as React from "react";
import { GoldenHour } from "@/components/ui/golden-hour";
// The light through a day, for the dial's track: night, dawn, morning, noon,
// afternoon, golden hour, dusk and night again, each at its hour.
const DAY = [
[0, "#1a1f4a"],
[5, "#262a5c"],
[6.2, "#c47c9c"],
[7.2, "#ffd3a0"],
[9.5, "#9cc3ee"],
[12.5, "#78aef0"],
[15.5, "#c9c6e0"],
[17.6, "#f68a48"],
[18.6, "#de4a62"],
[19.6, "#4a2f72"],
[21.2, "#1a1f4a"],
[24, "#1a1f4a"],
] as const;
const TRACK = `linear-gradient(90deg, ${DAY.map(([hour, color]) => `${color} ${((hour / 24) * 100).toFixed(1)}%`).join(", ")})`;
function clockLabel(hour: number) {
const minutes = Math.round((hour % 24) * 60) % (24 * 60);
const h = Math.floor(minutes / 60);
const m = minutes % 60;
return `${((h + 11) % 12) + 1}:${String(m).padStart(2, "0")} ${h < 12 ? "AM" : "PM"}`;
}
function lightLabel(hour: number) {
if (hour < 5) return "Night";
if (hour < 6.6) return "Dawn";
if (hour < 8) return "Sunrise";
if (hour < 11) return "Morning";
if (hour < 14) return "Midday";
if (hour < 17) return "Afternoon";
if (hour < 18.3) return "Golden hour";
if (hour < 19) return "Sunset";
if (hour < 20.2) return "Dusk";
return "Night";
}
export function GoldenHourDemo() {
const [hour, setHour] = React.useState(17.6);
const label = `${clockLabel(hour)} · ${lightLabel(hour)}`;
return (
<div className="w-full max-w-3xl">
<GoldenHour time={hour} className="aspect-[4/5] w-full rounded-3xl sm:aspect-[16/10]">
<p className="absolute top-4 left-4 flex items-center gap-2 rounded-full bg-zinc-950/30 py-1.5 pr-3.5 pl-2 text-xs font-medium text-white ring-1 ring-white/15 backdrop-blur-xl">
<span aria-hidden className="size-4 rounded-full bg-gradient-to-b from-amber-200 to-orange-400 shadow-[0_0_12px_rgba(255,190,110,0.8)]" />
<span className="tabular-nums">{label}</span>
</p>
</GoldenHour>
<div className="mt-5 flex items-center gap-4 px-1">
<label htmlFor="golden-hour-dial" className="sr-only">
Time of day
</label>
<div className="flex-1">
<input
id="golden-hour-dial"
type="range"
min={0}
max={24}
step={0.05}
value={hour}
aria-valuetext={label}
onChange={(event) => setHour(Number(event.target.value))}
style={{ backgroundImage: TRACK }}
className="block h-2 w-full cursor-pointer appearance-none rounded-full outline-offset-4 focus-visible:outline-2 focus-visible:outline-zinc-950 dark:focus-visible:outline-white [&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-zinc-950/20 [&::-webkit-slider-thumb]:size-5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-zinc-950/20 [&::-webkit-slider-thumb]:shadow-[0_1px_6px_rgba(0,0,0,0.35)]"
/>
<div aria-hidden className="mt-2 flex justify-between text-[11px] text-zinc-500 tabular-nums dark:text-zinc-400">
<span>12 AM</span>
<span>6 AM</span>
<span>Noon</span>
<span>6 PM</span>
<span>12 AM</span>
</div>
</div>
<button
type="button"
onClick={() => {
const now = new Date();
setHour(now.getHours() + now.getMinutes() / 60);
}}
className="-mt-5 shrink-0 rounded-full px-3 py-1.5 text-xs font-medium text-zinc-700 ring-1 ring-zinc-950/10 transition-[background-color,scale] duration-150 ease-out hover:bg-zinc-950/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-950 active:scale-[0.97] dark:text-zinc-200 dark:ring-white/15 dark:hover:bg-white/10 dark:focus-visible:outline-white"
>
Your time
</button>
</div>
</div>
);
}
Live preview, examples and props: https://keyframeui.com/components/golden-hour#golden-hour-demo