Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Feedback Command Menu Block for Vue

A product page's command menu shown open under its Feedback button: choose Bug, Idea or Praise, write it with a severity for bugs, and add it to a Recent feedback list with an Open, Planned or Shipped word.

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

Collect feedback from wherever the reader is with this feedback command menu for Vue with Ark UI. It opens from the product page in Feedloft, a feedback board, whose header holds an outline field with its ⌘ K cap, and the page is drawn under a soft scrim inside a hairline frame with a plus mark on each corner, its Feedback button at the end of the bar and the menu hanging below it. The menu is the catalog Command in two steps. The first lists Bug, Idea and Praise, and the board's Recent feedback, each item with its kind, an Open, Planned or Shipped word and its votes; choosing a recent item adds your vote, once. The second is a form in the same shell: a bug asks for its severity (Low, Medium or High) with a ToggleGroup, then a message of at least ten characters with a count. Ctrl or ⌘ Enter, or Send, adds it to the top of Recent feedback as Open. 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 step, message and query. For product pages, docs and any app that wants feedback in two keystrokes.

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 page's Feedback button, 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 message written 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.

What are the two steps?

The list is step one: three kinds to send and the recent items, searchable. Choosing a kind opens step two in the same shell, so the menu keeps its size. The form has a band with Back, a severity slot, the message and a footer with Send. The severity slot keeps its height for every kind: a bug shows the switch, an idea or praise shows a sentence saying it takes none, so the message never jumps.

What does it check, and what does a send do?

A message needs at least ten characters. A shorter one is refused in a line of its own under the field, which says how many you have, and the field is marked invalid. A valid one is added to the top of Recent feedback with its first line as the title, the status Open and one vote, which is yours; the menu goes back to the list and the status line says it was added and that nothing was sent.

How do the votes work?

Choosing a recent item adds one vote and marks the row "you voted"; choosing it again says you already did, so a row can't be inflated. Your own new item starts at one vote for the same reason. The status words are typed data: Open, Planned or Shipped.

What stays local, and how do I wire it?

All of it. The board and the votes are state in the block and the status line says nothing is sent. In your app load START from your feedback API, post from send and pick, and take the status words from your tracker.

Is it accessible from the keyboard?

Yes. Type to search, the arrow keys move through the rows, Enter chooses, and Escape steps back from the form, then closes the menu with focus on the field. In the form Enter writes a new line and Ctrl or ⌘ Enter sends. Ctrl or ⌘ K opens the dialog while focus is inside the block, and only then. The rows are options of a combobox and the first is highlighted when it opens.