shadcn.io is not affiliated with official shadcn/ui
Quick Reply Dialog Block for Solid
A helpdesk ticket with its saved-replies dialog shown open: a searchable list of eight replies, a preview filled from the ticket, a flag and a field for each variable it cannot fill, an SMS character count and an Insert reply button that writes into the composer.
Installation
Overview
Answer the same question in seconds without sending the same words twice, with this saved-replies dialog for Solid with Ark UI. It opens from Ticket 48213 on Cairndesk, a helpdesk: the page's header holds an outline Saved replies Button, and the ticket, the customer's message and a composer, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog has a search Input, a Toggle Group of categories (All, Greetings, Billing, Shipping) and an inline Listbox of eight replies with their first lines, and beside it the preview of the chosen one already filled from the ticket: the customer's first name, the order number and the agent. A variable the ticket can't fill is flagged in the preview and gets a small field that fills it as you type, and a count says how many of an SMS's 160 characters the reply uses. Insert reply is the only Shine Button: the text is added to the composer, which is real text, after anything already there. On a phone the list and the preview take turns, with a Back button. For preview the dialog is drawn open in place when the page loads; the header button opens the real Dialog.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the dialog is a copy drawn in place over the ticket: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Saved replies button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same ReplyFields component and share the block's state, so the reply you chose in the copy is the one in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How are the variables filled?
A reply holds markers such as {{first_name}}, {{order_id}} and {{agent}}. The ticket in TICKET fills those three, so the preview reads "Hi Linnea" at once, with the filled words tinted. Any other marker, such as {{refund_amount}}, is shown dashed and named in a row under the preview that says it needs a value; typing in its field fills the preview as you type, and the row says filled. Insert reply refuses while a value is missing, names it in words and moves focus to its field.
What does the character count measure?
The length of the text as it would be sent, with a marker that has no value yet counting for nothing, against the 160 characters of one SMS. Past it the line says how far over you are and that the reply is too long for one text message but fine for email. It does not stop you: the limit is advice, and the demo sends nothing.
How do the search and the keyboard work?
The search matches names and text without regard to accents or case, and the category switch narrows the same list. An empty result says what was searched and offers Clear search in the same box, so the dialog keeps its height. Arrow Down in the search field moves into the list, Enter in the field takes the top match, and the arrow keys move between replies.
What stays local in the demo, and how do I wire it up?
Everything. The eight replies and the ticket are typed constants, and Insert reply adds the text to the composer in this page's state; nothing is sent. In your app load the replies and the ticket from your helpdesk, keep partsOf for the filling, and send the composer's text from your own send button.
How does it look on a phone?
The copy shown on load docks to the foot of the page as a bottom sheet with its buttons pinned and the content scrolling above them. The list comes first; choosing a reply swaps in the preview, focus moves to its title, and Back to the list returns to the search field. The real dialog keeps the Dialog's own phone layout, a sheet stuck to the bottom of the screen.