# Ripple image (goodtabs UI)

An image that takes a soft refractive ripple from the pointer, then settles.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/ripple-image.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/ripple-image`

## Usage

```tsx
import { RippleImage } from "@/components/ui/ripple-image"

<RippleImage src="/photo.jpg" alt="What the photo shows" className="rounded-lg" />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| src | `string` |  | The image. Same origin, or served with CORS headers. |
| alt | `string` |  | Alt text for the real image, which stays in the DOM. |
| depth | `number` | `16` | How far a ripple bends the image at its peak, in CSS pixels. |
| idle | `number` | `0` | Seconds between soft drops while no pointer is over the image. 0 turns them off. |

## When to use

- One large image on a landing page that should answer the pointer
- A case study or portfolio cover, where the image is the point
- Beside short copy, with no controls on top of the image

## When not to use

- On a grid of thumbnails, since each one holds a WebGL context on a desktop
- On charts, screenshots or anything people need to read exactly
- As the only way to convey information, because touch users never see it

## Notes for agents

- It defaults to a 3:2 box. Pass aspect-auto and a height to fill something else, and the shader crops the same way as object-cover
- A real img with its alt is always in the DOM. On touch and under reduced motion no canvas mounts, so it is simply that image
- The image must be same origin or send CORS headers. If the texture cannot load the canvas stays clear and the plain image shows
- It installs components/ui/shader-canvas.tsx, and the canvas is aria-hidden. It uses no GSAP

## The maths

- Each ring is a sine inside a Gaussian envelope, sin(3.2x) × e^(-x²), which gives a soft ring with no hard front.
- Strength decays as e^(-2.4t), so a ripple is at 12 percent after 0.88s and under 1 percent when it is dropped at 2.2s.
- Eight slots with a 110ms gap mean a slot is reused at 0.88s at the earliest, too faint for the swap to show.
- Idle drops step by the golden angle, 2.39996 radians, which never lands twice in the same place.

Docs: https://ui.goodtabs.co/components/ripple-image