shadcn.io is not affiliated with official shadcn/ui
Integrations Command Menu Block for Radix UI
An integrations hub's command menu shown open as its catalog: category chips filter twelve services, each with a lettermark tile and a switch, and a connected service moves up into a Connected group.
Installation
Overview
Find and connect a service from the keyboard with this integrations command menu for React with Radix UI. It opens from the Integrations page of Plugmoor, an integrations hub, whose header holds an outline field with its ⌘ K cap, and the hub is drawn under a soft scrim inside a hairline frame with a plus mark on each corner, the menu standing in the middle of it. The menu is the catalog Command over twelve services in four categories, Messaging, Storage, Payments and Analytics, each row a two-letter tile, the service's name, what it does and a drawn switch. A ToggleGroup of chips above the field (All and the four categories) narrows the list and scrolls sideways on a phone. Enter marks the highlighted service connected, and so does Space while the field is empty; its row moves up into a Connected group at once, the foot counts "3 connected", and the status line says no account was linked. The drawn hub behind it fills the tiles of the connected services. For preview the menu is drawn open in place when the page loads; the field, or Ctrl or ⌘ K while focus is in the block, opens the real command dialog with the same services, category and query. For integration catalogs, marketplaces and settings pages that connect other tools.
FAQ
Why is the menu already open, and what do I keep?
So you can see it without a click. On load the menu is the Command drawn inline over a picture of the hub, in a plain shell that is not modal, so nothing is trapped, hidden or focused and the page around the preview keeps working. The header's field opens the real command dialog, modal, with its focus trap, Escape and focus return, and the inline copy stays closed until a reload. Both show the same Palette and share the block's state, so a service you connected in the copy is there in the dialog. In your app keep the dialog and drop the copy: the "in-place" state, the scrim with its shell and the Escape and blur effects.
How does a row move into Connected?
The rows are a function of the services: connected ones first under the Connected heading, the rest under Available, each in the data's own order. Pressing a row flips its connected flag and the next render puts it in the other group; the highlight stays on the same service. The list is keyed by the chip and the connected ids, so it re-lays out cleanly instead of animating through the old positions.
What do the chips filter, and does the count change?
They filter the list by category, together with the search: a query looks through the name, what the service does, a few hidden words and its category. The foot counts the services connected overall, whatever the chip says, and the matches while you type, and an empty result says what to try. One chip is always chosen, so the list is never unexplained.
Why are the services lettermarks, not logos?
Real services are named in text with a two-letter tile, never a logo or a brand colour: a logo is a trademark you need the owner's terms for. The tile is aria-hidden and the name beside it is what is read. The code marks the slot where you drop in a logo you have the right to use.
What stays local, and how do I wire it?
All of it, and the status line says so: "Marked Slack connected, no account was linked". The services are typed data and the switch only flips a flag in the block. In your app start the provider's OAuth flow from flip, show the pending state on the row while it runs, and only move the row into Connected when the provider confirms.
Is it accessible from the keyboard?
Yes. The chips are toggle buttons above the field. Type to search, the arrow keys move through the rows, Enter connects or disconnects, and Space does too while the field is empty. Escape closes the menu with focus on the field; Ctrl or ⌘ K opens the dialog while focus is inside the block, and only then. The rows are options of a cmdk listbox; the block turns off its own fuzzy filter and lists the rows itself.