Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Reply Templates Command Menu Block for React

A help desk's reply library as a command menu shown open over a ticket: choosing a reply with slots turns the menu into a short form, a textarea previews the filled reply, and Enter inserts it.

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

Answer a ticket from a library of replies without retyping them with this reply templates command menu for React with Base UI. It opens from the reply box of Ticket 2041 in Stencilloft, a help-desk macro library, whose header holds an outline field with its ⌘ K cap, and the ticket is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The menu is the catalog Command: six replies in three groups, each with a line on what it does and how many slots it has. Choosing one turns the menu into a short form in the same shell: a field for each slot in the reply (the customer's name, an order number, a date, an amount), and under them a Textarea that fills as you type and is yours to edit. Enter in a slot inserts the reply and closes the menu, but not while a slot is still open: it says which one and puts focus there. The drawn reply box behind the menu mirrors the text as it is written and keeps it once it is inserted, and Escape steps back to the list before it closes. 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 replies, step and text. For help desks, shared inboxes and any team that answers the same questions every day.

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 under a picture of the ticket, 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 the reply you were filling in the copy is the one the dialog opens with. 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 do the slots work?

Each reply is a text with {name}-style slots and a list of which ones it has. The form shows a field per slot, and the Textarea shows the reply with every slot you have filled replaced by what you typed; a slot still empty keeps its braces, so you can see what is left. The values carry over from one reply to the next, so the customer's name is typed once.

What happens when I edit the reply by hand?

The text is yours from then on: the slot fields stop rewriting it, a line under the Textarea says so, and Reset takes the template back. Inserting does not look at the fields at all, only at the text: a reply that still has an open {slot} in it is refused with the name of the slot, and focus goes to that field (or to the reply if there is none).

What does Enter do, and where does the reply go?

Enter in any slot field inserts the reply into the drawn reply box and closes the menu, with focus on the field in the header and a status line that says nothing was sent. In the reply itself Enter makes a new line, so Ctrl or ⌘ Enter inserts from there. Escape in the form goes back to the list without inserting; Escape in the list closes the menu.

What stays local, and how do I wire it?

All of it. The replies, the values and the reply box are state in the block; nothing is sent, saved or copied. In your app load MACROS from the team's library, send reply from your composer's own submit in insert, and keep the slot names you accept in SLOTS.

Is it accessible from the keyboard?

Yes. Type to search the replies by title, what they do or their words, the arrow keys move through them, Enter picks one, and Tab moves between the slot fields, the reply and Insert; Escape goes back and then closes. 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. A refusal is spoken on the status line as well as shown in the foot of the form.

  • Pro

    A notes editor's formatting menu shown open over a note: a real textarea with a sample sits above seven rows that format its selection or insert a block, and a preview and a mono line show the result.

  • Pro

    A support inbox's quick edit as a command menu shown open under a ticket's header: pick a field, edit it in the right control, see Before and After, and Enter saves into the record card.

  • Pro

    A code editor's snippet library as a command menu shown open over the editor: a language switch, a pane that follows the highlighted snippet with highlighted code and Copy, and Enter inserts it into the buffer.

  • Pro

    A team chat's emoji menu shown open over its composer: names and shortcodes, a skin-tone switch for hands and people, and Enter adds an emoji to the message under the list while the menu stays open.

  • Pro

    A webmail app's command menu shown open over the Inbox: start a new email, reply or forward the open message in a To, Subject and message form inside the menu, or jump to a folder, and Ctrl or Command Enter sends into the Sent count.

  • Pro

    Basic Command Menu

    Search everything

    A team workspace's home page with its command menu shown open: eleven pages in three groups, a shortcut on the five most used, matches marked, an empty state that says what to try and a foot with the key hints and a spoken count.