# Hover Preview: Journal

> An archive of essays with dates and reading times. Each title shows its cover image in a wide 3:2 frame.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/hover-preview-journal-demo).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/hover-preview-journal-demo
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/keyframeui/hover-preview-journal-demo-light-0e60c90c043bc30a.png
- Registry item: https://keyframeui.com/r/hover-preview-journal-demo.json
- Categories: list, image, motion
- Listed: 2026-10-14, source last changed 2026-10-15

## Install

```bash
npx shadcn@latest add https://keyframeui.com/r/hover-preview-journal-demo.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `https://keyframeui.com/r/hover-preview.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/hover-preview#hover-preview-journal-demo

## Files

### `registry/demos/hover-preview-journal-demo.tsx`

```tsx
import { HoverPreview, HoverPreviewItem } from "@/components/ui/hover-preview";

const posts = [
  {
    title: "Designing for the second visit",
    date: "Sep 18, 2026",
    minutes: 6,
    photo: "1497032628192-86f99bcd76bc",
  },
  {
    title: "Motion is a material, not a garnish",
    date: "Aug 29, 2026",
    minutes: 9,
    photo: "1557672172-298e090bd0f1",
  },
  {
    title: "Shipping a design system in six weeks",
    date: "Aug 04, 2026",
    minutes: 12,
    photo: "1519389950473-47ba0277781c",
  },
  {
    title: "A reading list for product designers",
    date: "Jul 15, 2026",
    minutes: 4,
    photo: "1481627834876-b7833e8f5570",
  },
  {
    title: "How we price fixed-scope projects",
    date: "Jun 30, 2026",
    minutes: 7,
    photo: "1499750310107-5fef28a66643",
  },
  {
    title: "Notes on writing interface copy",
    date: "Jun 02, 2026",
    minutes: 5,
    photo: "1455390582262-044cdead277a",
  },
];

const photo = (id: string, width: number, height: number) =>
  `https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=${width}&h=${height}&q=80`;

const slug = (title: string) => title.toLowerCase().replace(/[^a-z0-9]+/g, "-");

export function HoverPreviewJournalDemo() {
  return (
    <section className="w-full max-w-3xl">
      <div className="mb-4 flex items-end justify-between gap-4">
        <h3 className="text-2xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-50">Journal</h3>
        <p className="font-mono text-xs text-zinc-500 tabular-nums">{posts.length} essays</p>
      </div>

      <HoverPreview
        previewClassName="aspect-[3/2] w-64 rounded-md sm:w-80"
        className="border-t border-zinc-200 dark:border-zinc-800"
      >
        {posts.map((post) => (
          <HoverPreviewItem
            key={post.title}
            href={`#${slug(post.title)}`}
            image={photo(post.photo, 720, 480)}
            thumbnail={photo(post.photo, 120, 120)}
            className="items-baseline gap-6 border-b border-zinc-200 py-5 dark:border-zinc-800"
            thumbnailClassName="self-center"
          >
            <time className="hidden w-24 shrink-0 font-mono text-xs text-zinc-500 tabular-nums sm:block">
              {post.date}
            </time>
            <span className="flex-1 text-lg font-medium tracking-tight text-pretty text-zinc-900 sm:text-2xl dark:text-zinc-50">
              {post.title}
            </span>
            <span className="shrink-0 font-mono text-xs text-zinc-500 tabular-nums">
              {post.minutes} min
            </span>
          </HoverPreviewItem>
        ))}
      </HoverPreview>
    </section>
  );
}
```
