Hover Image List

A list of large headings that reveal an image on the left and shift right on hover, animated with Motion.

Installation

File Structure

hover-image-list.tsx

Usage

import { HoverImageList } from "@/components/unlumen-ui/hover-image-list";

const items = [
  { label: "Design systems", image: "/images/design.jpg" },
  { label: "Prototyping", image: "/images/proto.jpg" },
  { label: "Motion & animation", image: "/images/motion.jpg" },
];

<HoverImageList items={items} />;

API Reference

HoverImageList

PropTypeDefault
items
HoverImageListItem[]
-
imageWidth?
number
220
imageGap?
number
40
className?
string
-

HoverImageListItem

PropTypeDefault
label
string
-
image
string
-
imageAlt?
string
""

Notes

  • The image panel tracks the hovered item's vertical center using a Motion spring (stiffness: 200, damping: 18, mass: 0.6) — the image slides smoothly between items.
  • Images are aspect-square and object-cover by default. Provide square or close-to-square images for the best result.
  • The hovered item shifts 16px to the right, non-hovered items fade to opacity: 0.18 — both animated with a stiff spring (stiffness: 380, damping: 30).
  • Image transitions use AnimatePresence with mode="popLayout" — the outgoing image fades out while the incoming one fades in, with no layout jump.
  • Images use loading="lazy" and decoding="async" — but since they appear on hover, consider preloading critical images if the list is short.
  • The component uses onHoverStart / onHoverEnd from Motion — these fire on pointer enter/leave, not on focus. For keyboard accessibility, you may want to add onFocus handlers.
  • Set imageWidth and imageGap to control the layout. The image panel is flex-shrink-0 so it never collapses.

Credits

Inspired by @raul_dronca's original Design. Thanks to Raul for the initial idea!