Integration Grid
block / marketing
The "works with your stack" section with per-integration state — connected, connectable, coming soon, and blocked with the reason on the card — filterable by category and searchable.
- type
- block
- files
- 2
- registry deps
- button, card, input, skeleton, tabs, @automindz/empty-state, @automindz/render-link, @automindz/sso-buttons
- npm deps
- lucide-react
installs
- lib/automindz/integrations.ts
- components/automindz/integration-grid.tsx
- Integrations are data in lib/automindz/integrations.ts
- onConnect is the union: a button with it, a link without
- Awaited connect — pending on the card, failure in place with a retry
- Unavailable stays in the grid with its reason, never hidden
- Four provider marks reused; everything else is a monogram tile
Edit lib/automindz/integrations.ts, not the component; category tabs come from the order entries appear in it. onConnect is the union the whole item turns on: wire it and an available card gets a Connect button whose pending, in-place failure and retry this component owns (one connection at a time, siblings recede); leave it out and the same card becomes one anchor on its title with a stretched overlay, so a button can never nest inside a link. unavailable stays in the grid, dimmed, with unavailableReason printed on the card — hiding it makes people ask whether the integration exists. coming-soon gets no button at all rather than a dead one. Status is always a glyph plus a word. Four marks are reused from @automindz/sso-buttons (provider-icons.tsx, which is why that dependency is here); everything else draws a monogram tile from name — a registry cannot ship every vendor's trademark, so icon on an integration is the seam for the logos you have the right to display. loading draws skeletons at the real card height and holds the filter row's slot. Filtering is local state, not the URL: @automindz/filter-bar would put every facet in the address bar through useSearchParams (needing a <Suspense> boundary and a prefix per instance), which is wrong for a marketing section.
Variations
one state per section
- 01Marketing, no onConnect
- 02Connect, awaited
- 03Failure, retried in place
- 04Coming soon and unavailable
- 05Loading
- 06Empty, and matched nothing
Marketing, no onConnect
Without onConnect an available card is a link to href — one anchor on the title with a stretched overlay, so nothing interactive can nest inside it and the whole card is still a target. Filter by category or type in the box; the count under the grid is a polite live region for anyone who cannot see it shrink.
Works with the stack you already run
Identity, comms, warehouses and payments. Fourteen of them ship in the config; the list is data, not markup.
Showing 15 of 15 integrations
Connect, awaited
Press Connect on any available card: that one goes busy with a spinner and aria-busy while every other card recedes, so it stays obvious which one was clicked. When it resolves the card flips to Connected with a check and a Manage link — the component holds that until your data catches up.
Showing 15 of 15 integrations
Failure, retried in place
The first attempt on each card rejects with the handler's own message, rendered on the card that failed with the button turned into Try again. No toast: by the time a toast lands the reader has scrolled, and it cannot say which of fourteen cards it was about. The second attempt succeeds.
Coming soon and unavailable
Two states that look alike and are not. Coming soon gets no button at all rather than a greyed-out one that cannot keep its promise; unavailable stays in the grid, dimmed, with the reason written on the card — hide it and the reader assumes the integration does not exist and asks support instead.
Loading
Skeletons at the real card height — tile, title, status line, two description lines and a footer — so nothing moves when the data lands. The filter row keeps its slot as a single skeleton rather than rendering tabs over data that has not arrived.
Empty, and matched nothing
An empty integrations list is its own message, aimed at whoever installed the item rather than at the visitor. Search for something absent in the first variant above to see the other one: a different message, and a Clear filters action that actually clears them.
No integrations yet
Integrations are configured in lib/automindz/integrations.ts, or passed as the integrations prop.
Showing 0 of 0 integrations
