Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Deploy and Rollback Command Menu Block for React

A deploy platform's command menu shown open over the Builds list: Quick deploy to Staging or Production and Recent deployments to roll back to, where Enter arms a row for four seconds and a second Enter confirms.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Deploy or roll back without a mis-click with this deploy command menu for React with Base UI. It opens from the Builds list in Ferrymark, a deploy platform, whose header holds an outline field with its ⌘ K cap, and the list is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The menu is the catalog Command: Quick deploy offers the newest build for Staging and for Production, and Recent deployments lists the builds that have been live, with their commit message, author and a fixed time. Pressing Enter on a deploy arms it: the row reads Press ↵ again with a four-second countdown, and a second Enter deploys, moving the Live and Staging markers on the Builds list behind the menu. A build that is not live offers Roll back to its hash the same way. Phones hide the hash. For the 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 builds. For release tools, ops consoles and any action that should not fire on one key.

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 Builds list, 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 an armed row in the copy is still 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 arming work?

The first Enter on a deploy or a rollback stores that row's value and a count of four seconds. A one-second timer counts it down and shows the seconds on the row and in the foot; the status line speaks the arming once and the timeout once, not every second. The second Enter on the same row within the time confirms it. Pressing Enter on another row arms that one instead, and Escape, or letting the time run out, disarms.

What can be rolled back, and what changes on the page?

Recent deployments lists the builds that have been live in Production. The one that is live now says so and cannot be chosen again; every other one offers Roll back to its hash. Deploying the newest build to Production adds it to that list and makes it the live one. The Builds list behind the menu moves its Production and Staging markers to match, so you can see where each environment stands.

What stays local, and how do I wire it?

All of it. The builds, the two environments and the history are state in the block, and the status line says "Simulated: nothing was deployed". In your app call your deploy API from confirm, keep the arming exactly as it is, and replace BUILDS with your builds.

What does a phone show?

The menu docks to the top of the stage and the hash and the action text at each row's end are hidden. The row keeps its label and its second line, and when a row is armed it shows a badge with the countdown, so the confirm is never hidden.

Is it accessible from the keyboard?

Type to filter by commit word, author or hash, the arrow keys move through the rows, Enter arms and then confirms, and Escape closes the menu with focus back on the header's 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.