# Hero Grid Cells Reveal — Tailwind Hero Section

> A hero on a spreadsheet-like grid where cells light up in rings that ripple out from the headline, and individual cells glow under the pointer.

- Category: [Hero Sections](https://pixelpapa.com/components/heroes.md)
- Tags: hero, grid, cells, wave, background
- Dependencies: lucide-react, motion (plus React and Tailwind CSS v4)
- Last updated: 2026-11-13
- Live preview: https://pixelpapa.com/components/heroes/hero-grid-cells-reveal

## Install

```bash
npx shadcn@latest add "https://pixelpapa.com/r/hero-grid-cells-reveal.json"
```

The file is written to `components/pixelpapa/hero-grid-cells-reveal.tsx`. To install manually, run `npm install lucide-react motion` and copy the source below into your project. It imports `cn` from `@/lib/utils`, which every shadcn project has.

## Source

```tsx
"use client";

import { ArrowRight } from "lucide-react";
import { motion } from "motion/react";
import { useMemo } from "react";

type HeroGridCellsRevealProps = {
  columns?: number;
  rows?: number;
  /** Seconds between waves. */
  period?: number;
};

const ease = [0.22, 1, 0.36, 1] as const;
const CELL = 60;

export default function HeroGridCellsReveal({ columns = 24, rows = 12, period = 5 }: HeroGridCellsRevealProps) {
  const cells = useMemo(() => {
    const cx = (columns - 1) / 2;
    const cy = (rows - 1) / 2;
    return Array.from({ length: columns * rows }, (_, i) => {
      const dist = Math.hypot((i % columns) - cx, Math.floor(i / columns) - cy);
      // Cheap deterministic hash: roughly one cell in seven uses the accent colour.
      const accent = (i * 2654435761) % 7 === 0;
      return { delay: (dist * 0.34 - period).toFixed(2), accent };
    });
  }, [columns, rows, period]);

  return (
    <section className="relative isolate flex min-h-[700px] items-center justify-center overflow-hidden bg-background px-6 py-28">
      <style>{`
        @keyframes pp-hero-grid-cells-reveal-wave {
          0%, 34%, 100% { background-color: transparent; }
          12% { background-color: var(--pp-cell); }
        }
      `}</style>
      <div
        aria-hidden
        className="absolute top-1/2 left-1/2 -z-10 grid -translate-x-1/2 -translate-y-1/2 border-t border-l border-foreground/10 [mask-image:radial-gradient(ellipse_at_center,black_35%,transparent_78%)]"
        style={{ width: columns * CELL, gridTemplateColumns: `repeat(${columns}, 1fr)` }}
      >
        {cells.map((cell, i) => (
          <span
            key={i}
            className="aspect-square border-r border-b border-foreground/10 transition-colors duration-700 hover:bg-primary/30 hover:duration-0 motion-reduce:!animate-none"
            style={{
              ["--pp-cell" as string]: `color-mix(in oklch, ${cell.accent ? "var(--chart-2)" : "var(--primary)"} ${cell.accent ? 55 : 38}%, transparent)`,
              animation: `pp-hero-grid-cells-reveal-wave ${period}s linear ${cell.delay}s infinite`,
            }}
          />
        ))}
      </div>
      {/* Soft pocket so the type never fights the grid; pointer-events pass through to the cells. */}
      <div aria-hidden className="pointer-events-none absolute inset-0 -z-10 [background:radial-gradient(ellipse_34%_40%_at_50%_50%,var(--background)_38%,transparent)]" />

      <motion.div
        initial="hidden"
        animate="shown"
        transition={{ staggerChildren: 0.09 }}
        className="pointer-events-none mx-auto max-w-2xl text-center [&_a]:pointer-events-auto"
      >
        {[
          <p key="k" className="inline-flex items-center gap-2 rounded-md border border-border bg-card px-2.5 py-1 font-mono text-xs text-muted-foreground">
            <span className="text-primary">=</span>SUM(everything!A:Z)
          </p>,
          <h1 key="h" className="mt-6 text-5xl font-semibold tracking-tight text-balance text-foreground sm:text-7xl">
            A spreadsheet with a database inside
          </h1>,
          <p key="p" className="mx-auto mt-5 max-w-lg text-lg text-muted-foreground">
            Gridwork looks like the sheet your team already knows and computes ten million rows like the warehouse they wish they had.
          </p>,
          <div key="c" className="mt-8 flex flex-wrap justify-center gap-3">
            <a href="#" className="group inline-flex h-11 items-center gap-2 rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground shadow-lg shadow-primary/25">
              Import a CSV
              <ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
            </a>
            <a href="#" className="inline-flex h-11 items-center rounded-lg border border-border bg-card px-6 text-sm font-medium text-foreground hover:bg-muted">
              Open a sample sheet
            </a>
          </div>,
        ].map((node, i) => (
          <motion.div
            key={i}
            variants={{
              hidden: { opacity: 0, y: 22, filter: "blur(8px)" },
              shown: { opacity: 1, y: 0, filter: "blur(0px)", transition: { duration: 0.8, ease } },
            }}
          >
            {node}
          </motion.div>
        ))}
      </motion.div>
    </section>
  );
}
```

## AI prompt

```text
Add the "Hero Grid Cells Reveal" component from PixelPapa UI to this project.

What it is: A hero on a spreadsheet-like grid where cells light up in rings that ripple out from the headline, and individual cells glow under the pointer.
Category: Hero Sections. Depends on: lucide-react, motion.

1. Install it with the shadcn CLI:
   npx shadcn@latest add "https://pixelpapa.com/r/hero-grid-cells-reveal.json"
   (If the CLI is unavailable, fetch that URL, write files[0].content to components/pixelpapa/hero-grid-cells-reveal.tsx and install the listed dependencies.)
2. Import it from "@/components/pixelpapa/hero-grid-cells-reveal" and place it where I describe below.
3. Keep its animation timings and accessibility attributes. Replace the demo copy and data with content that fits my product, and use my existing theme tokens (bg-background, text-foreground, bg-primary, border-border) rather than hard-coded colours.

Where to use it: <describe the page and position here>
```

## More hero sections

- [Hero Before After Toggle](https://pixelpapa.com/components/heroes/hero-before-after-toggle.md) (Pro): A hero with a Before / After switch: the same nine request cards spring from a scattered pile into three labelled, colour-coded lanes and back.
- [Hero Cursor Spotlight](https://pixelpapa.com/components/heroes/hero-cursor-spotlight.md) (Pro): An always-dark hero where a soft light trails the pointer and reveals a hidden grid of service nodes; it wanders on its own until you move.
- [Hero Dashboard Lift](https://pixelpapa.com/components/heroes/hero-dashboard-lift.md): Centered headline over a product window that tilts flat as you scroll, with staggered entrance.
- [Hero Drifting Card Rows](https://pixelpapa.com/components/heroes/hero-drifting-card-rows.md) (Pro): Three tilted rows of small UI cards drift in opposite directions behind a headline that sits in a soft cleared pocket.
- [Hero Editorial Serif](https://pixelpapa.com/components/heroes/hero-editorial-serif.md) (Pro): A magazine-style opener: an oversized serif headline rises line by line from behind hairlines that draw across an asymmetric grid.
- [Hero Mesh Gradient](https://pixelpapa.com/components/heroes/hero-mesh-gradient.md) (Pro): An inset poster hero filled with a slowly shifting CSS mesh of theme colours, with bottom-anchored type and a glass stat strip.
