# Slide Puzzle Integrations

> An integrations section where fourteen tool tiles sit in a grid of slots around the headline. They start scrambled and solve themselves like a sliding puzzle, then one slides over every few seconds; point at a tile for its name, or sweep the mouse fast to shove a row along. Under the card, three notes on how the integrations work.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/slide-puzzle-integrations).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/slide-puzzle-integrations
- Screenshot: https://shadcn.exchange/shot/keyframeui/slide-puzzle-integrations/light.png
- Registry item: https://keyframeui.com/r/slide-puzzle-integrations.json
- Categories: blocks, integrations
- Listed: 2026-11-02, source last changed 2026-11-02

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/keyframeui/slide-puzzle-integrations.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/slide-puzzle.json`

## Notes from the registry

Live preview and the components it's built with: https://keyframeui.com/blocks/integrations/slide-puzzle-integrations

## Files

### `registry/blocks/slide-puzzle-integrations.tsx`

```tsx
"use client";

import * as React from "react";

import { SlidePuzzle, type SlidePuzzleTile } from "@/components/ui/slide-puzzle";

/* ── Content ─────────────────────────────────────────────────
 * Everything you'd change to make the section yours: the copy,
 * the integrations on the tiles (a name, what it is, a link and
 * a mark) and the three notes under the card. Every name and
 * mark here is made up; swap in your own logos as `icon`.
 * ─────────────────────────────────────────────────────────── */

/** The one accent: the primary button and the focus rings. */
const ACCENT = "#ff5a1f";

const BADGE = "Integrations";
const HEADLINE = "Plugs into everything that ships your app.";
const SUBLINE =
  "Rung reads your store accounts, reviews and analytics, and posts what moved to wherever your team already talks.";
const PRIMARY_CTA = { label: "Browse 38 integrations", href: "#integrations" };
const SECONDARY_CTA = { label: "Request one", href: "#request" };

const NOTES = [
  { title: "Two-way listing sync", body: "Accept a suggested subtitle in Rung and it lands in your store listing, ready for review." },
  { title: "Alerts where you talk", body: "Move up or slip down for a keyword you care about and your team channel hears first." },
  { title: "Webhooks for the rest", body: "Every rank change as a signed event, so your own dashboards stay current." },
];

function Mark({ children }: { children: React.ReactNode }) {
  return (
    <svg viewBox="0 0 24 24" className="size-6" aria-hidden>
      {children}
    </svg>
  );
}

const TILES: SlidePuzzleTile[] = [
  {
    id: "storefront",
    label: "Storefront · App store",
    href: "#storefront",
    icon: (
      <Mark>
        <path d="M5.5 8h13l-1 11.5a1.5 1.5 0 0 1-1.5 1.4H8a1.5 1.5 0 0 1-1.5-1.4z" fill="#2563eb" />
        <path d="M9 9.5V7a3 3 0 0 1 6 0v2.5" fill="none" stroke="#60a5fa" strokeWidth="1.8" strokeLinecap="round" />
      </Mark>
    ),
  },
  {
    id: "playfield",
    label: "Playfield · Android store",
    href: "#playfield",
    icon: (
      <Mark>
        <path d="M6 4.2v15.6c0 .8.9 1.3 1.6.9l13-7.8a1 1 0 0 0 0-1.8l-13-7.8C6.9 2.9 6 3.4 6 4.2Z" fill="#10b981" />
        <path d="M6 4.2 14.2 12 6 19.8" fill="none" stroke="#a7f3d0" strokeWidth="1.4" strokeLinejoin="round" />
      </Mark>
    ),
  },
  {
    id: "chatter",
    label: "Chatter · Team chat",
    href: "#chatter",
    icon: (
      <Mark>
        <path d="M4 7a4 4 0 0 1 4-4h8a4 4 0 0 1 4 4v5.5a4 4 0 0 1-4 4h-5L6.5 20.5v-4.2A4 4 0 0 1 4 12.5z" fill="#7c3aed" />
        <path d="M8.5 8.5h7M8.5 11.5h4.5" stroke="#ddd6fe" strokeWidth="1.7" strokeLinecap="round" />
      </Mark>
    ),
  },
  {
    id: "tracklight",
    label: "Tracklight · Analytics",
    href: "#tracklight",
    icon: (
      <Mark>
        <rect x="4" y="12" width="4" height="8" rx="1.3" fill="#fdba74" />
        <rect x="10" y="7.5" width="4" height="12.5" rx="1.3" fill="#fb923c" />
        <rect x="16" y="3.5" width="4" height="16.5" rx="1.3" fill="#ff5a1f" />
      </Mark>
    ),
  },
  {
    id: "paywall-kit",
    label: "Paywall Kit · Subscriptions",
    href: "#paywall-kit",
    icon: (
      <Mark>
        <rect x="2.5" y="5" width="19" height="14" rx="3" fill="#4f46e5" />
        <rect x="2.5" y="8.4" width="19" height="2.6" fill="#312e81" />
        <rect x="5.2" y="14.2" width="5.5" height="2" rx="1" fill="#c7d2fe" />
      </Mark>
    ),
  },
  {
    id: "bugnet",
    label: "Bugnet · Crash reports",
    href: "#bugnet",
    icon: (
      <Mark>
        <ellipse cx="12" cy="13.5" rx="5.5" ry="6.5" fill="#e11d48" />
        <path d="M12 7v13M7 11H3.5M20.5 11H17M7 16H4M20 16h-3M9 5l1.5 2M15 5l-1.5 2" stroke="#e11d48" strokeWidth="1.6" strokeLinecap="round" />
        <path d="M12 8v11.5" stroke="#fecdd3" strokeWidth="1.3" />
      </Mark>
    ),
  },
  {
    id: "lintel",
    label: "Lintel · Issues",
    href: "#lintel",
    icon: (
      <Mark>
        <circle cx="12" cy="12" r="8.5" fill="#0ea5e9" />
        <path d="m8.2 12.2 2.6 2.6 5-5.4" fill="none" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      </Mark>
    ),
  },
  {
    id: "sheetwise",
    label: "Sheetwise · Spreadsheets",
    href: "#sheetwise",
    icon: (
      <Mark>
        <rect x="4" y="3.5" width="16" height="17" rx="2.5" fill="#16a34a" />
        <path d="M4 9.5h16M4 15h16M10 9.5v11" stroke="#bbf7d0" strokeWidth="1.4" />
      </Mark>
    ),
  },
  {
    id: "folio",
    label: "Folio · Docs",
    href: "#folio",
    icon: (
      <Mark>
        <path d="M6.5 3h7.5l4.5 4.5V19a2 2 0 0 1-2 2h-10a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z" fill="#f59e0b" />
        <path d="M14 3v4.5h4.5" fill="#fde68a" />
        <path d="M8 12h8M8 15.5h5.5" stroke="#fff" strokeWidth="1.6" strokeLinecap="round" />
      </Mark>
    ),
  },
  {
    id: "pixelboard",
    label: "Pixelboard · Design files",
    href: "#pixelboard",
    icon: (
      <Mark>
        <circle cx="8" cy="7" r="3.5" fill="#f472b6" />
        <circle cx="16" cy="7" r="3.5" fill="#db2777" />
        <circle cx="8" cy="15" r="3.5" fill="#fb923c" />
        <rect x="12.5" y="11.5" width="7" height="7" rx="2" fill="#a855f7" />
      </Mark>
    ),
  },
  {
    id: "hookline",
    label: "Hookline · Webhooks",
    href: "#hookline",
    icon: (
      <Mark>
        <path d="M9.5 6.5a3.5 3.5 0 1 1 5.6 2.8L12 14.6" fill="none" stroke="#06b6d4" strokeWidth="2.2" strokeLinecap="round" />
        <path d="M7.2 19.2a3.5 3.5 0 0 1 .2-6.9H14" fill="none" stroke="#0891b2" strokeWidth="2.2" strokeLinecap="round" />
        <path d="M16 18.8a3.5 3.5 0 0 0 2.8-5.6l-3-5.2" fill="none" stroke="#22d3ee" strokeWidth="2.2" strokeLinecap="round" />
      </Mark>
    ),
  },
  {
    id: "starboard",
    label: "Starboard · Reviews",
    href: "#starboard",
    icon: (
      <Mark>
        <path d="m12 3.2 2.6 5.3 5.8.8-4.2 4.1 1 5.8-5.2-2.7-5.2 2.7 1-5.8L3.6 9.3l5.8-.8z" fill="#facc15" stroke="#eab308" strokeWidth="1" strokeLinejoin="round" />
      </Mark>
    ),
  },
  {
    id: "atlas",
    label: "Atlas · Localization",
    href: "#atlas",
    icon: (
      <Mark>
        <circle cx="12" cy="12" r="8.5" fill="#3b82f6" />
        <path d="M3.5 12h17M12 3.5c2.4 2.4 3.5 5.2 3.5 8.5s-1.1 6.1-3.5 8.5c-2.4-2.4-3.5-5.2-3.5-8.5S9.6 5.9 12 3.5Z" fill="none" stroke="#bfdbfe" strokeWidth="1.4" />
      </Mark>
    ),
  },
  {
    id: "postbox",
    label: "Postbox · Email digest",
    href: "#postbox",
    icon: (
      <Mark>
        <rect x="3" y="5" width="18" height="14" rx="3.2" fill="#ff5a1f" />
        <path d="M6 8.6l6 4.4 6-4.4" fill="none" stroke="#fff" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
      </Mark>
    ),
  },
];

/* ── Section ─────────────────────────────────────────────── */

export function SlidePuzzleIntegrations() {
  return (
    <section
      style={{ "--accent": ACCENT } as React.CSSProperties}
      className="bg-[#f5f5f6] px-3 py-20 text-zinc-950 sm:px-4 sm:py-28 dark:bg-[#09090b] dark:text-white"
    >
      <div className="mx-auto max-w-6xl overflow-hidden rounded-[28px] bg-white shadow-[0_1px_2px_rgb(0_0_0/0.04),0_0_0_1px_rgb(0_0_0/0.05)] dark:bg-[#111113] dark:shadow-[0_0_0_1px_rgb(255_255_255/0.07)]">
        <SlidePuzzle
          tiles={TILES}
          cell={68}
          className="[--slide-puzzle-ring:var(--accent)] [--slide-puzzle-tile:#ffffff] dark:[--slide-puzzle-tile:#1b1b1f]"
        >
          <div className="flex max-w-md flex-col items-center text-center">
            <p className="inline-flex items-center gap-1.5 rounded-full bg-white px-2.5 py-1 text-xs font-medium text-zinc-700 shadow-[0_0_0_1px_rgb(0_0_0/0.08)] dark:bg-white/[0.06] dark:text-zinc-300 dark:shadow-[0_0_0_1px_rgb(255_255_255/0.1)]">
              <span className="grid grid-cols-2 gap-[2px]" aria-hidden>
                <span className="size-[5px] rounded-[1.5px] bg-(--accent)" />
                <span className="size-[5px] rounded-[1.5px] bg-zinc-300 dark:bg-zinc-600" />
                <span className="size-[5px] rounded-[1.5px] bg-zinc-300 dark:bg-zinc-600" />
                <span className="size-[5px] rounded-[1.5px] bg-zinc-300 dark:bg-zinc-600" />
              </span>
              {BADGE}
            </p>
            <h2 className="mt-5 text-[1.9rem] leading-[1.1] font-semibold tracking-[-0.035em] text-balance sm:text-[2.6rem]">{HEADLINE}</h2>
            <p className="mt-4 max-w-sm text-[15px] leading-relaxed text-pretty text-zinc-600 dark:text-zinc-400">{SUBLINE}</p>
            <div className="mt-7 flex flex-wrap items-center justify-center gap-2.5">
              <a
                href={PRIMARY_CTA.href}
                className="flex h-10 items-center gap-1 rounded-full bg-(--accent) pr-3.5 pl-4 text-sm font-semibold text-white transition-[filter,transform] duration-150 hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--accent) active:scale-[0.97]"
              >
                {PRIMARY_CTA.label}
                <Chevron className="size-3.5" />
              </a>
              <a
                href={SECONDARY_CTA.href}
                className="flex h-10 items-center rounded-full bg-white px-4 text-sm font-semibold shadow-[0_1px_2px_rgb(0_0_0/0.05),0_0_0_1px_rgb(0_0_0/0.1)] transition-colors duration-150 hover:bg-zinc-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--accent) dark:bg-white/[0.06] dark:shadow-[0_0_0_1px_rgb(255_255_255/0.12)] dark:hover:bg-white/[0.1]"
              >
                {SECONDARY_CTA.label}
              </a>
            </div>
          </div>
        </SlidePuzzle>

        <ul className="grid border-t border-zinc-950/[0.07] sm:grid-cols-3 dark:border-white/[0.07]">
          {NOTES.map((note, i) => (
            <li
              key={note.title}
              className={
                i > 0
                  ? "border-t border-zinc-950/[0.07] px-7 py-6 sm:border-t-0 sm:border-l dark:border-white/[0.07]"
                  : "px-7 py-6"
              }
            >
              <p className="text-sm font-semibold tracking-[-0.01em]">{note.title}</p>
              <p className="mt-1.5 text-sm leading-relaxed text-zinc-600 dark:text-zinc-400">{note.body}</p>
            </li>
          ))}
        </ul>
      </div>
    </section>
  );
}

function Chevron({ className }: { className?: string }) {
  return (
    <svg viewBox="0 0 16 16" className={className} fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
      <path d="m6 4 4 4-4 4" />
    </svg>
  );
}
```
