Integration Connect Grid
A React component where integration cards drop into a grid in sequence, then flip one by one to a connected state with a drawn checkmark. Autoplay it as a showcase, or let users click to connect and await async authorization.
An integration grid for marketing pages and settings screens alike. When the grid scrolls into view, the cards drop in one after another with a slight tilt and a small landing bounce. From there it can autoplay — every so often the next card moves to "connecting" and then "connected", its border fades to the accent color and a checkmark draws itself in — or hand control to the user: clicking Connect calls the onConnect you provide, shows a spinner while a returned Promise is pending, and reverts with a shake if it fails. Once everything is connected, a summary row ("已連接 N 項服務" — "N services connected") appears at the bottom with a rolling number. The connected list supports controlled and uncontrolled modes.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add integration-connect-grid.enPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<IntegrationConnectGrid/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
Installation
npx webberui@latest add https://webberui.com/r/integration-connect-grid.en.jsonOr, once registries are configured in components.json, install it as @webberui/integration-connect-grid.
Usage
import { Calendar, HardDrive, Mail } from "lucide-react";
import { IntegrationConnectGrid } from "@/components/ui/integration-connect-grid";
const items = [
{ id: "drive", name: "Cloud Drive", description: "Sync shared folders and attachments", icon: <HardDrive /> },
{ id: "calendar", name: "Calendar Sync", description: "Meetings land on the team calendar", icon: <Calendar /> },
{ id: "mail", name: "Email", description: "Turn inbox threads into tasks", icon: <Mail /> },
];
// Marketing page: autoplay
<IntegrationConnectGrid items={items} autoConnect />
// Settings page: users click to connect
<IntegrationConnectGrid
items={items}
onConnect={async (id) => {
// Run your authorization flow; throwing reverts the card with a shake
await connectIntegration(id);
}}
onConnectedChange={(ids) => console.log(ids)}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | IntegrationConnectItem[] | — | Integration services to display |
connected | string[] | — | Controlled list of connected ids; when omitted the component manages it internally (uncontrolled) |
defaultConnected | string[] | [] | Initial connected ids in uncontrolled mode |
onConnectedChange | (connected: string[]) => void | — | Called when the connected list changes, with the full new id list |
onConnect | (id: string) => Promise<void> | void | — | Called when the user clicks Connect; if it returns a Promise a spinner shows while pending, and a rejection reverts to disconnected with a shake |
autoConnect | boolean | false | After the entrance finishes, connect each card in order automatically |
interval | number | 650 | Delay between cards in auto-connect mode (ms) |
columns | number | 3 | Column count on wide screens; phones always use at most 2 columns |
showSummary | boolean | true | Show a summary row at the bottom once everything is connected |
accent | string | — | Accent color for the connected state; defaults to --wb-integration-connect-accent (#10b981) |
className | string | — | Passed through to the outermost container |
IntegrationConnectItem
| Field | Type | Default | Description |
|---|---|---|---|
id | string | — | Unique id; appears in the connected array and the onConnect argument |
name | string | — | Service name |
description | string | — | One-line description, truncated with an ellipsis when too long |
icon | ReactNode | — | Icon shown at the top-left of the card; falls back to a generic plug icon |
How it works
- The entrance is triggered by an IntersectionObserver (plays once): each card drops from
y: -40,rotate: -4°and opacity 0 on a spring (stiffness 420, damping 24, mass 0.8) with a small landing bounce, staggered by--wb-integration-connect-stagger(default90ms). - Auto-connect starts only after the last card has landed. Every
intervalit moves the next unconnected card to "connecting", holds for 400ms, then switches it to "connected". - On connect, the border fades to
--wb-integration-connect-accentover--wb-integration-connect-duration(default300ms), the checkmark draws in over the same duration, and the card scales to 1.02 and back. - When
onConnectreturns a Promise, the button is disabled and shows a spinner while pending; a rejection or thrown error reverts the card with a horizontal shake, ready to click again. WithoutonConnect, or when it returns synchronously, the card connects immediately. - Columns use CSS grid:
columnson wide screens, at most 2 below thesmbreakpoint. The summary row reserves a fixed height so it does not push the layout below when it appears.
Accessibility
- The grid is
role="list"and each card isrole="listitem", labelled by the service name througharia-labelledby - The Connect button is a native
button; it setsaria-busyand is disabled while authorization is pending, and is described by the service name viaaria-describedby - State changes are announced in an
aria-live="polite"region, e.g. "Calendar Sync connected" or "Invoicing failed to connect, please try again" - The connected state does not rely on color alone: a checkmark and the "Connected" label are shown too. After connecting from the button, focus moves to that card instead of falling back to the top of the page
- When the user has reduce motion enabled, cards appear immediately, states switch instantly, the checkmark is not drawn, and there is no shake or scale
Prompt Showcase
A self-playing prompt box React component for marketing pages. A glowing pill types out a prompt, a fake cursor glides in and clicks send, and a result card pops up, on loop, pausing on hover.
Pain Point Orbit
As you type into the input, surrounding pain-point cards crowd inward one by one; on submit they scatter away — a marketing visual for the pain of fragmented tools.