Peek Carousel
InteractiveAn Apple-style peek carousel where the active slide springs to center at full scale while the previous/next slides peek in at the edges, scaled to ~0.86 and dimmed; navigate by arrows, dots, drag (with velocity-projected snap), or wheel. Under prefers-reduced-motion it degrades to a plain CSS scroll-snap scroller with no scaling or inertia, keeping the same arrows, dots, keyboard, and labelling.
Inspired by Skiper UI — Apple / Dia carousel (pattern) — independently built, not affiliated. Attribution policy
Installation
npx shadcn@latest add https://parable-three.vercel.app/r/peek-carousel.jsonRuns the shadcn CLI — the component source is copied intocomponents/parable/peek-carousel.tsx. You own it from there.
Usage
The exact code rendering the preview above.
<div className="w-full max-w-[440px] px-2">
<PeekCarousel
peek={34}
aria-label="Featured releases"
items={[
<div key="a" className="flex h-48 flex-col justify-end rounded-2xl bg-gradient-to-br from-[#8b5cf6] to-[#ec4899] p-5 shadow-lg shadow-black/40">
<span className="text-[11px] font-medium uppercase tracking-widest text-white/70">Vol. 01</span>
<span className="text-xl font-semibold text-white">Prism Drift</span>
</div>,
<div key="b" className="flex h-48 flex-col justify-end rounded-2xl bg-gradient-to-br from-[#ec4899] to-[#f5a623] p-5 shadow-lg shadow-black/40">
<span className="text-[11px] font-medium uppercase tracking-widest text-white/70">Vol. 02</span>
<span className="text-xl font-semibold text-white">Ember Fold</span>
</div>,
<div key="c" className="flex h-48 flex-col justify-end rounded-2xl bg-gradient-to-br from-[#22d3ee] to-[#8b5cf6] p-5 shadow-lg shadow-black/40">
<span className="text-[11px] font-medium uppercase tracking-widest text-white/70">Vol. 03</span>
<span className="text-xl font-semibold text-white">Signal Bloom</span>
</div>,
<div key="d" className="flex h-48 flex-col justify-end rounded-2xl bg-gradient-to-br from-[#f5a623] to-[#22d3ee] p-5 shadow-lg shadow-black/40">
<span className="text-[11px] font-medium uppercase tracking-widest text-white/70">Vol. 04</span>
<span className="text-xl font-semibold text-white">Halo Cast</span>
</div>,
]}
/>
</div>Props
PeekCarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange">
| Prop | Type | Default | Description |
|---|---|---|---|
| items* | React.ReactNode[] | — | Slides to display. Each is centred in turn with its neighbours peeking. |
| loop | boolean | false | Wrap navigation at the ends — next from the last slide returns to the first. |
| onIndexChange | (index: number) => void | — | Fires with the new active index whenever it changes. |
| peek | number | 48 | How many px of each neighbouring slide peeks past the edge. |
| accent | string | "#8b5cf6" | Accent for arrows, the active dot, and focus rings. Mirrors `--pb-violet`. |
npm dependencies
- motion
- lucide-react