Fjord, 1 of 10
01 / 10 · Fjord

Inertia gallery

An endless strip of frames you push with the wheel or a drag; it coasts, snaps by intent and morphs between list and slider.

Behaviour

  • Wheel or drag adds velocity; the strip coasts, then settles by intent: a nudge returns, anything more moves at least one frame.
  • Each image is zoomed past its frame and drifts against the frame's distance from the centre (parallax).
  • Switching layout moves every frame to its new spot over 1.5s, outer frames first.
  • Arrow keys move one frame and Home / End jump to the ends while the strip has focus; Enter opens the centred frame's link.
  • Touch only takes horizontal swipes (touch-action: pan-y), so the page still scrolls on phones.
  • The frame loop runs only while something moves and pauses off screen.
  • Reduced motion: no parallax or coasting (jumps to the settled frame), layout switches crossfade, no intro.

Props

PropTypeDescription
items{ src?: string; node?: ReactNode; alt?: string; href?: string; title?: ReactNode }[]Frames. node draws instead of an image; an empty frame shows bg-muted.
layout"list" | "slider"Controlled layout. Pair with onLayoutChange.
defaultLayout"list" | "slider"default "list"Uncontrolled starting layout.
onLayoutChange(layout) => voidFires when the bar's List / Slider buttons ask for a layout.
onActiveChange(index: number) => voidFires when the centred item changes.
introbooleandefault falsePlay the squares intro the first time it scrolls into view.
frictionnumberdefault 0.97Velocity kept per 60fps frame; higher coasts further.
frameWidthnumberdefault 240Largest list frame width in px; slider frames are 2x. Both shrink to fit.
frameHeightnumberdefault 320Largest list frame height in px.
barbooleandefault trueBottom bar with title, counter and the List / Slider buttons.
labelstringdefault "Gallery"Accessible name.

Installation

npx shadcn@latest add https://purrfectui.com/r/inertia-gallery.json

How to use

import { InertiaGallery } from "@/components/ui/inertia-gallery";

<div className="h-[560px]">
  <InertiaGallery items={[{ src: "/a.jpg", alt: "A", title: "A", href: "/work/a" }, { node: <Art />, title: "B" }]} />
</div>

Source code

Loading…

Credits

Ported from poinu.vercel.app.

License

MIT. Copy it into your project and change it as you like.

0