A travel hero that plays on its own: the open slice's strip fills like a story timer, then the next place opens. Hovering pauses it. The counter above follows along through `index` and `onIndexChange`.
@keyframeui
registry/demos/slice-gallery-hero-demo.tsx
"use client";
import * as React from "react";
import { SliceGallery, SliceGalleryItem } from "@/components/ui/slice-gallery";
const stays = [
{
place: "Kyoto",
country: "Japan",
nights: 6,
price: "€1,480",
note: "A machiya on a lane behind Yasaka, breakfast in the garden.",
photo: "1493976040374-85c8e12f0c0e",
accent: "#f6b38e",
},
{
place: "Banff",
country: "Canada",
nights: 5,
price: "€1,320",
note: "A lake cabin with canoes at the dock and no signal at all.",
photo: "1493246507139-91e8fad9978e",
accent: "#8fd3e6",
},
{
place: "Vík",
country: "Iceland",
nights: 4,
price: "€1,150",
note: "Black sand, a grey sea and a turf-roofed guesthouse above it.",
photo: "1500043357865-c6b8827edf10",
accent: "#d3dbe2",
},
{
place: "Lisbon",
country: "Portugal",
nights: 4,
price: "€890",
note: "Tiled rooms in Alfama, a short tram ride from the river.",
photo: "1536663815808-535e2280d2c2",
accent: "#ffcf8a",
},
{
place: "Big Sur",
country: "USA",
nights: 5,
price: "€1,690",
note: "Redwoods above the cove and the Pacific under the deck.",
photo: "1510414842594-a61c69b5ae57",
accent: "#8fe0c9",
},
];
const photo = (id: string) =>
`https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=1100&h=1000&q=80`;
const pad = (n: number) => String(n).padStart(2, "0");
export function SliceGalleryHeroDemo() {
const [index, setIndex] = React.useState(0);
const stay = stays[index];
return (
<section className="w-full max-w-5xl">
<div className="mb-8 grid gap-6 sm:grid-cols-[1fr_auto] sm:items-end">
<div>
<p className="font-mono text-xs tracking-widest text-zinc-500 uppercase">
Small stays, slow trips
</p>
<h2 className="mt-3 text-4xl font-semibold tracking-tight text-balance text-zinc-900 sm:text-5xl dark:text-zinc-50">
Go somewhere quiet.
</h2>
<p className="mt-3 max-w-md text-pretty text-zinc-600 dark:text-zinc-400">
Five places we keep going back to, each with one house we'd book again.
</p>
</div>
<div className="flex items-center gap-5">
<p aria-live="polite" className="font-mono text-xs text-zinc-500 tabular-nums">
{pad(index + 1)} / {pad(stays.length)}
<span className="ml-2 text-zinc-900 dark:text-zinc-100">{stay.place}</span>
</p>
<a
href="#plan"
className="rounded-full bg-zinc-900 px-5 py-2.5 text-sm font-medium text-white transition-colors outline-none hover:bg-zinc-700 focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-300 dark:focus-visible:ring-offset-zinc-950"
>
Plan a trip
</a>
</div>
</div>
<SliceGallery
index={index}
onIndexChange={setIndex}
autoPlay={5000}
className="h-[34rem] sm:h-[30rem]"
>
{stays.map((item) => (
<SliceGalleryItem
key={item.place}
title={item.place}
label={item.country}
image={photo(item.photo)}
accent={item.accent}
>
<p className="max-w-xs text-[15px] leading-snug text-pretty text-white/90">{item.note}</p>
<p className="mt-3 flex items-baseline gap-2 text-sm text-white/70">
<span>{item.nights} nights from</span>
<span className="text-lg font-medium text-white">{item.price}</span>
</p>
</SliceGalleryItem>
))}
</SliceGallery>
</section>
);
}
Live preview, examples and props: https://keyframeui.com/components/slice-gallery#slice-gallery-hero-demo























