Hover Feature Cards

A responsive grid of feature cards where a description panel slides in from below on hover, with spring animation and optional image support.

Installation

File Structure

hover-feature-cards.tsx

Usage

import {
  HoverFeatureCards,
  type HoverFeatureCard,
} from "@/components/unlumen-ui/hover-feature-cards";
import Link from "next/link";

const items: HoverFeatureCard[] = [
  {
    name: "Components",
    description:
      "Real components, not just primitives. Ready to use and customize.",
    href: "/components",
    img: "/blocks.png",
    imgLight: "/blocks-light.png",
    imgClassName: "absolute -bottom-10 left-1/2 -translate-x-1/2",
    imgWidth: 320,
    containerClassName: "h-full rounded-3xl",
    fadeBottom: true,
  },
  {
    name: "Refined UI",
    description: "Polished UI system, focused on aesthetics and smooth UX.",
    href: "/docs/ui",
    img: "/refined-ui.png",
    imgWidth: 200,
    containerClassName: "h-full rounded-3xl",
  },
];

export default function Example() {
  return (
    <HoverFeatureCards
      items={items}
      renderLink={(href, children) => <Link href={href}>{children}</Link>}
    />
  );
}

API Reference

HoverFeatureCards

items
HoverFeatureCard[]

Array of feature card data objects.

renderLink?
(href: string, children: React.ReactNode) => React.ReactNode

Optional render prop to wrap linked cards. Receives the href and card children. Use this to inject Next.js Link or any router link.

className?
string

Extra classes applied to the grid wrapper.

HoverFeatureCard (item shape)

name
string

Card title displayed inside the illustration area.

description
string

Text shown in the slide-in panel on hover.

href?
string

Optional link target. When omitted the card is non-interactive.

img?
string

Image URL shown in dark mode (or always when imgLight is not set).

imgLight?
string

Image URL shown in light mode.

imgClassName?
string

Extra classes applied to the image element.

imgWidth?
number

Intrinsic width of the image in pixels.

containerClassName?
string

Extra classes applied to the illustration container.

fadeBottom?
boolean

When true, a gradient fades the bottom of the illustration area into the card background.

soon?
boolean

When true, renders a 'Coming soon' badge and disables hover interaction.

Notes

  • The description panel slides up via Motion variant propagation: the parent motion.div owns the rest/hover variants, and the panel inherits them automatically.
  • Cards without an href receive cursor-not-allowed and reduced opacity, with whileTap scale disabled.
  • Use renderLink to decouple the component from any specific router — pass next/link, react-router, or a plain <a> tag.

Credits

Built by leo.

Keep in mind

Most components on this site are inspired by or recreated from existing work across the web. I'm not here to take credit; just to learn, experiment, and sometimes push things a bit further. If something looks familiar and I forgot to mention you, reach out and I'll fix that right away.