Basinworks Drive
Storage · Basinworks
Sync shared folders and attach files to routes and depots.
KQ-1326 · INTEGRATION/HUB
A directory of integrations built from data, each with a seeded glyph and a connect switch that does not flip at once: its knob waits halfway on snap while the permissions step slides in as a sheet — from the side or the bottom on glide, or a dialog rising in the centre on snap — listing required scopes locked and the rest as checkboxes, and completes its travel when onConnect's promise lands. Connected cards read their sync (synced, syncing, paused, needing attention) with the time since the last one, and the search filters as you type: cards that stay glide to their new cells, cards that go fade and shrink on the exit ease, and returning ones rise on snap. The sheet is a modal dialog with a focus trap, Escape and focus returned to its opener; categories are a radiogroup, "/" jumps to the search and Escape clears it.
3 of 12 connected · gaugeworks metrics needs attention
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/integration-hub
| Prop | Type | Default | Description |
|---|---|---|---|
| integrations | Integration[] | defaultIntegrations | The directory: id, name, category, a line of description, the maker, the scopes it asks for (required or optional), a glyph tint and mark, and its sync while connected. |
| connected / defaultConnected | string[] | defaultIntegrationConnected | The ids that are connected. Controlled or uncontrolled. |
| onConnectedChange | (ids: string[]) => void | — | Fires when a connect or disconnect lands, with every connected id. |
| onConnect | (id: string, scopes: string[]) => void | Promise<unknown> | — | Allow and connect was pressed, with the scopes granted (required plus the optional ones left ticked). A promise holds the sheet in Connecting…; a rejection shows the error in the sheet. |
| onDisconnect | (id: string) => void | Promise<unknown> | — | Disconnect was confirmed. A promise holds the sheet until it lands. |
| onSync | (id: string) => void | Promise<unknown> | — | Sync now was pressed on a connected card. A promise keeps it syncing until it lands, then it reads synced just now. |
| query / defaultQuery | string | "" | The search text. Controlled or uncontrolled. |
| onQueryChange | (query: string) => void | — | Fires on every keystroke in the search, on Clear and on Escape. |
| category / defaultCategory | string | "all" | The category filter: "all", "connected", or a category's name in lower-case with dashes. Controlled or uncontrolled. |
| onCategoryChange | (category: string) => void | — | Fires when a category is chosen by click or arrow key. |
| grid | "cards" | "compact" | "list" | "cards" | The directory's layout: cards with a description and a sync footer, compact tiles, or a list of rows. |
| sheet | "side" | "bottom" | "center" | "side" | Where the permissions step comes from: a side sheet or a bottom sheet sliding in on glide, or a dialog rising in the centre on snap. |
| status | "dot" | "pill" | "bar" | "pill" | How a connected card reads its sync: a coloured dot with words, a tinted pill with the last sync time, or a stripe down the card's edge that pulses while it syncs. |
| now | number | Date | defaultIntegrationNow | Now, for "Last sync 4 min ago". Pass a ticking value to keep the times fresh. |
| formatAgo | (ms: number) => string | — | How long ago, from a span in ms. Defaults to just now, 4 min ago, 2 h ago, yesterday. |
| account | string | "dana@fieldline.app" | The account the permissions step says it signs in as. |
| appName | string | "Fieldline" | Your product's name in the permissions step: "Fieldline will be able to". |
| loading | boolean | false | The directory has not arrived: a skeleton of cards. |
| error | string | null | — | The directory failed to load: this message, with Try again when onRetry is given. |
| onRetry | () => void | — | Try again was pressed after an error. |
| title | string | "Integrations" | The panel's heading; also its accessible name unless label is given. |
| description | string | "Connect the tools you already use." | A line under the heading. |
| label | string | — | The panel's accessible name. Defaults to the title. |
| sound | boolean | false | A clack for each switch press and category choice, a pop for Allow and connect, Disconnect and Sync now. |
| disabled | boolean | false | Read only: nothing connects, syncs or filters. |
| className | string | — | Classes for the root. It is 560px tall with the directory scrolling inside and the sheet laid over it; pass a height class to change it. |