---
title: Jelly Spiral Gallery
description: Photos on a 3D spiral that bend like jelly when you spin it.
category: Gallery
tier: pro
url: https://ui.dimaac.com/components/jelly-spiral
registry: https://api.dimaac.com/v1/ui/r/jelly-spiral.json
registry_auth: Authorization: Bearer <DiMaac licence key>
---

# Jelly Spiral Gallery

A three.js gallery that hangs photo cards on an endless 3D spiral. The wheel, a drag or a swipe turns it (or, in scroll mode, the page's own scroll), the spiral eases after your input, and the faster it turns the more every card bends sideways like jelly before it settles. Cards on the far side show their faded backs, photos fill their cards like object-fit: cover with rounded corners, and the camera steps back on narrow screens so the whole spiral fits. It reports the photo at the front for captions, turns with the arrow keys, pauses off screen, frees every WebGL resource on unmount, and holds still with no bend or idle spin when the visitor prefers reduced motion.

## Install

This is a Pro component: its source is for buyers of Pro Components, a Templates plan or All-Access, and is not on this page. It installs from the authenticated registry, with the licence key in an environment variable.

1. Merge the registry into components.json (the key is never written into the file):

```json
{
  "registries": {
    "@dimaac-pro": {
      "url": "https://api.dimaac.com/v1/ui/r/{name}.json",
      "headers": { "Authorization": "Bearer ${DIMAAC_LICENSE_KEY}" }
    }
  }
}
```

2. Put the licence key in `.env.local` (keep it out of git; never print or commit it). Ask the owner for it if it isn't set:

```bash
DIMAAC_LICENSE_KEY=your-licence-key
```

3. Add the component:

```bash
npx shadcn@latest add @dimaac-pro/jelly-spiral
```

The registry item is https://api.dimaac.com/v1/ui/r/jelly-spiral.json and answers only with `Authorization: Bearer <licence key>` (or `X-License-Key`). It answers 401 without a key, 403 for a key that isn't valid, and 402 for a key whose purchase doesn't include Pro components (see https://ui.dimaac.com/pricing).

Dependencies:

```bash
pnpm add three gsap
npm install three gsap
```

By hand:

Unlock the code on https://ui.dimaac.com/components/jelly-spiral with your licence key, then:

1. Install the packages it uses: three, gsap.
2. Copy the component file from the Code panel (once your licence key unlocks it) into components/dimaac/jelly-spiral.tsx.
3. It's styled with Tailwind v4 classes. If that folder sits outside the places Tailwind scans, add it with @source in your CSS.
4. Import it with import { JellySpiral } from "@/components/dimaac/jelly-spiral" and give its parent a size: it fills it.

## Usage

```tsx
import { JellySpiral } from "@/components/dimaac/jelly-spiral";

<JellySpiral images={images} />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `images` (required) | `(string \| JellySpiralImage)[]` | - | The photos, as URLs or { src, alt }. They repeat round the spiral when there are fewer than `count`. |
| `count` | `number` | `18` | How many cards sit on the spiral. More cards make a longer spiral. |
| `radius` | `number` | `1.8` | Distance from the spiral's centre line to each card. |
| `verticalGap` | `number` | `0.9` | Height between one card and the next. |
| `angleGap` | `number` | `0.85` | How far round the spiral each card is from the last, in radians. |
| `cardWidth` | `number` | `1.44` | Width of a card, in scene units. |
| `cardHeight` | `number` | `1.8` | Height of a card, in scene units. |
| `rounding` | `number` | `0.03` | Corner radius, as a share of the card's width. |
| `idleSpin` | `number` | `0.005` | How much the spiral turns by itself, in cards per frame (60 frames a second). |
| `scrollSensitivity` | `number` | `0.004` | How many cards one pixel of wheel, drag or scroll turns the spiral. |
| `smoothing` | `number` | `0.1` | How quickly the spiral catches up with where it should be, per frame. Lower is floatier. |
| `wobble` | `number` | `0.3` | How much the cards bend when the spiral turns fast. 0 keeps them flat. |
| `backOpacity` | `number` | `0.25` | Opacity of the cards whose back faces you, on the far side of the spiral. |
| `input` | `"wheel" \| "scroll"` | `"wheel"` | What turns the spiral. "wheel": the wheel, a drag or a swipe over the gallery (the page doesn't scroll while you do). "scroll": the scroll of `scroller`, so the page scrolls as usual. |
| `scroller` | `HTMLElement \| Window \| string \| null` | `null` | In "scroll" mode, the element (or a selector for it) whose scroll turns the spiral. The window when left out. |
| `onActiveChange` | `(index: number) => void` | - | Called with the index (in `images`) of the card at the front whenever it changes. |
| `label` | `string` | `"Photo gallery"` | Describes the gallery for screen readers. |
| `className` | `string` | `""` | Extra classes for the outer box. Give it a size (it fills it). |

## Credits

- Portrait: Shaun Duval, Lummi (https://www.lummi.ai/photo/portrait-with-neon-sunglasses-gindg), Lummi License
- Portrait: studiomiklus, Lummi (https://www.lummi.ai/photo/striking-portrait-jodiu), Lummi License
- Portrait: SHIHO, Lummi (https://www.lummi.ai/photo/mystery-portrait-cffyo), Lummi License
- Portrait: Amino, Lummi (https://www.lummi.ai/photo/vivid-portrait-on-pink-oxbow), Lummi License
- Portrait: Kuba, Lummi (https://www.lummi.ai/photo/abstract-eye-close-up-uamae), Lummi License
- Portrait: SHIHO, Lummi (https://www.lummi.ai/photo/vibrant-woman-portrait-htofy), Lummi License
- Portrait: Lloyd Creates, Lummi (https://www.lummi.ai/photo/poised-portrait-ooi9b), Lummi License
- Portrait: Steph Meade, Lummi (https://www.lummi.ai/photo/expressive-minimal-portrait-jrfyc), Lummi License
- Portrait: Dynamic Wang, Lummi (https://www.lummi.ai/photo/profile-portrait-of-woman-xyyue), Lummi License

## Source

The source of a Pro component is for buyers of Pro Components, a Templates plan or All-Access. Install it with the commands above, or unlock it on https://ui.dimaac.com/components/jelly-spiral.

## Agent prompt

```text
Add the Jelly Spiral Gallery component (<JellySpiral />) from DiMaac UI to this project. It is a Pro component, so its source needs the owner's DiMaac licence key (Pro Components, a Templates plan or All-Access).

Docs: https://ui.dimaac.com/components/jelly-spiral

1. Add the Pro registry to components.json (merge it into "registries"). Don't write the key into the file:
{
  "registries": {
    "@dimaac-pro": {
      "url": "https://api.dimaac.com/v1/ui/r/{name}.json",
      "headers": { "Authorization": "Bearer ${DIMAAC_LICENSE_KEY}" }
    }
  }
}

2. The owner puts their licence key in .env.local (keep it out of git): DIMAAC_LICENSE_KEY=your-licence-key
   Ask them for it if it isn't set. Never print it or commit it.

3. Install it with:
npx shadcn@latest add @dimaac-pro/jelly-spiral

The registry item is https://api.dimaac.com/v1/ui/r/jelly-spiral.json and wants the header "Authorization: Bearer <licence key>".

Then use it like this:
import { JellySpiral } from "@/components/dimaac/jelly-spiral";
<JellySpiral images={images} />

It imports three, gsap; the CLI installs them. It uses Tailwind v4 classes, so make sure Tailwind scans that folder.
Give its parent a size, keep light and dark mode working and keep its prefers-reduced-motion fallback.
Full index for agents: https://ui.dimaac.com/llms.txt
```
