Integration visual
A hub and the tools wired into it. Live routes pulse, idle ones dim, and the hub opens a preview on hover.
- Database
- Repository
- Chat
- Calendar
Features
- Three layouts:
cornersfor up to four tools,orbitfor up to eight, andsidesfor a pipeline with inputs on one side and outputs on the other. - Pulses run inward or outward along live routes. Idle tools keep their route and dim.
- A preview opens over the hub on hover or focus. It takes any content, or an image or looping video.
- Respects reduced motion: the pulses, halo and springs stop, and the preview fades in.
Installation
npx shadcn@latest add https://fibo.toribryan.com/r/integration-visual.jsonimport { IntegrationVisual, type IntegrationItem } from "@/components/ui/integration-visual"It installs motion with it, for the pulses and the preview.
Usage
import { DatabaseIcon, MailIcon } from "lucide-react"
import { IntegrationVisual } from "@/components/ui/integration-visual"
export function ConnectedTools() {
return (
<IntegrationVisual
label="Connected tools"
items={[
{ title: "Database", icon: <DatabaseIcon /> },
{ title: "Email", icon: <MailIcon />, status: "idle" },
]}
/>
)
}Items fill the layout's slots in order, and any past its limit are left out.
Each title names its tile for screen readers.
Each item takes:
type IntegrationItem = {
title: string
icon: React.ReactNode
status?: "active" | "idle"
side?: "in" | "out" // sides layout only
}Anatomy
Every part the component renders, with the data-slot it carries. You pass
items, center and preview; the component builds the rest.
| Part | data-slot | Notes |
|---|---|---|
| IntegrationVisual | integration-visual | The root. Carries data-layout. |
| plate | The dots or grid, and the routes. Decorative. | |
| item | integration-visual-item | One tile per entry in items. Carries data-status. |
| hub | integration-visual-hub | Takes focus when there's a preview. |
| face | integration-visual-hub-face | Shows center. |
| preview | integration-visual-preview | Above the hub, while it's hovered or focused. |
Guidelines
- 01Choose the layout by count:
cornersfor four,orbitfor five to eight,sideswhen data flows in one side and out the other. - 02Mark tools that aren't connected yet as
idlerather than leaving them out. The diagram then shows what's possible as well as what's live. - 03Use
pulse="inward"for sources feeding the hub and"outward"for the hub sending to them. - 04Name the hub with the product, a count, or a mark in
center. Keep it to a word or a number. - 05Put it at the top of a card and let the card's text make the claim.
Examples
Media preview
Pass { src, alt } to preview for an image, an animated image, or a video
that plays muted on a loop. Media is 16:9 unless you set aspectRatio. Hover
or focus the snail.
- Database
- Repository
- Chat
- Calendar
Orbit
Up to eight tools, evenly spaced on an ellipse with straight spokes.
- Database
- Repository
- Chat
- Calendar
- Storage
Sides
A pipeline. Set side on each item to put it in the input or output column,
and pulse="outward" to run the pulses from inputs to outputs.
- Webhook
- Database
- Repository
- Chat
Idle items
Every other tool is idle: its route stays, dimmed, and carries no pulse.
- Database
- Repository, idle
- Chat
- Calendar, idle
Plates
The background prop sets the plate: dots, grid or none.
- Database
- Repository
- Chat
- Calendar
- Database
- Repository
- Chat
- Calendar
- Database
- Repository
- Chat
- Calendar
In a card
A count in the hub and the claim in the card text below it.
- Database
- Repository
- Chat
- Calendar
Do's and don'ts
- Database
- Repository
- Chat, idle
- Email, idle
- Database
- Repository
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
items | IntegrationItem[] | The tools wired into the hub. | |
center | React.ReactNode | A snail icon | What names the hub. An icon element sits in a square face; a string or number is set as text and the face widens to fit. Defaults to a snail, for syncs that take their time. |
preview | React.ReactNode | IntegrationPreviewMedia | Shown above the hub while it is hovered or focused, for looking at only. Pass any content, or { src, alt } for an image, an animated image, or a video (.mp4, .webm) that plays muted on a loop. | |
layout | "corners" | "orbit" | "sides" | "corners" | corners holds up to four, orbit and sides up to eight. Items past the limit are not drawn. |
background | "dots" | "grid" | "none" | "dots" | The plate behind the diagram. |
routes | "solid" | "dashed" | "solid" | Route stroke. |
pulse | "inward" | "outward" | "none" | "inward" | Which way the pulse travels along each active route. |
size | "sm" | "default" | "lg" | "default" | Scales the tiles and the hub. |
halo | boolean | true | A slow ring breathing out from the hub. |
label | string | "Integrations" | Accessible name for the diagram. |
It also takes the props of a div, except children. IntegrationPreviewMedia
is { src: string; alt?: string; aspectRatio?: number | string }, with
aspectRatio defaulting to "16 / 9".
Data attributes
Style parts by slot or state, for example with
[&_[data-slot=integration-visual-item]]:rounded-full.
| Attribute | Element | Present when |
|---|---|---|
data-slot="integration-visual" | The root | Always. |
data-slot="integration-visual-item" | Each tool tile | Always. |
data-slot="integration-visual-hub" | The hub, which takes focus when there's a preview | Always. |
data-slot="integration-visual-hub-face" | The face inside the hub that shows center | Always. |
data-slot="integration-visual-preview" | The preview above the hub | While the preview is open. |
data-layout | The root | Always. corners, orbit or sides. |
data-status | Each tool tile | Always. active, or idle for idle items. |
Accessibility
- 01The diagram is a labelled group, and each tool is a list item named by its title, with ", idle" added for idle ones. Set
labelto say what the diagram is. - 02Routes, pulses and the halo are decorative and hidden from assistive tech.
- 03When there's a preview the hub joins the tab order, and focusing it shows the preview the same way hovering does.
Related components
- Token flowWalks a colour token from raw value to primitive to semantic role.
- Chapter scrubberA rail of marks that swell under the pointer like the Dock, previewing the chapter at the crest.
- ReactionsLets people respond to content with an emoji in one tap.
References
- Motion, for the pulses, halo and preview springs
prefers-reduced-motion- Lucide, for the default snail
