Slice Gallery

Tall photo slices that share one width. The one you open widens into a full card while the others squeeze to make room; its title swings upright and the details slide up from under it.

  • Gallery
  • Hover
  • Layout

Uses motion, clsx, tailwind-merge

Inspired by State of AI in Design

Open in ChatGPTOpen in Claude

Installation

Add the component on its own with the CLI, or copy the file in by hand.

The CLI writes components/ui/slice-gallery.tsx and installs motion, clsx and tailwind-merge. It needs the @keyframeui registry in components.json; add it once per project.

npx shadcn@latest add @keyframeui/slice-gallery

Examples

Finished sections built with Slice Gallery. Each one installs whole, with the component included.

Props

childrenRequired

TypeReact.ReactNode

The slices, as SliceGalleryItems.

defaultIndex

TypenumberDefault0

The slice that starts open.

index

Typenumber

The open slice. Set it with onIndexChange to control the gallery from outside.

onIndexChange

Type(index: number) => void

Called when a slice opens, by hover, tap, scrub, keys or autoplay.

grow

TypenumberDefault5

How many times longer the open slice is than a closed one.

gap

TypenumberDefault8

Space between slices, in px.

openOn

Type"hover" | "click"Default"hover"

hover opens the slice under the pointer once it slows down, and the slice under a finger dragged across the row. click waits for a click or tap.

autoPlay

Typenumber

Opens the next slice every this many ms, with the open slice's strip filling as its timer. Pauses while the pointer or keyboard focus is inside or the gallery is off screen. Off for reduced motion.

orientation

Type"auto" | "horizontal" | "vertical"Default"auto"

auto puts the slices side by side and stacks them when the gallery is narrower than 36rem.

className

Typestring

Classes for the gallery. Set its height here; the default is h-[30rem].

item.titleRequired

TypeReact.ReactNode

SliceGalleryItem: one short line. It runs up the edge of a closed slice and swings upright when the slice opens.

item.imageRequired

Typestring

SliceGalleryItem: photo URL. It's cut to the open slice's size, so a closed slice shows a strip from its middle and opening it just widens the window.

item.alt

TypestringDefault""

SliceGalleryItem: alt text for the photo. Leave it empty when the title says it all.

item.label

TypeReact.ReactNode

SliceGalleryItem: small text in the top corner, like a year or a city. Moves to the end of the title row when stacked.

item.accent

TypestringDefault"#ffffff"

SliceGalleryItem: the color the strip on top warms to when the slice opens.

item.children

TypeReact.ReactNode

SliceGalleryItem: details that slide up under the title when the slice opens.

item.imageClassName

Typestring

SliceGalleryItem: classes for the photo. The slice is a group/slice with data-state="open" or "closed", so grayscale group-data-[state=open]/slice:grayscale-0 colors only the open one.

item.className

Typestring

SliceGalleryItem: classes for the slice, like its corner radius or background.