shadcn.io is not affiliated with official shadcn/ui
Task List Command Menu Block for React
A to-do app's command menu shown open over the Today list: type a sentence to add a task with !1 to !3 setting its priority, tick tasks with Enter or Space, and filter Active, Done or All.
Installation
Overview
Add and tick tasks without leaving the keyboard with this task list command menu for React with Base UI. It opens from the Today list in Taskhollow, a to-do app, 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: type a sentence and the first row is the task as it will be written, with !1, !2 or !3 anywhere in it setting the priority (High, Medium or Low). Enter adds it and the menu stays open; the rows under it are the list, To do first and Done under it, struck through, and a three-way ToggleGroup filters them. Enter on a task ticks it, and Space ticks the highlighted task while the field is empty. The foot counts what is still to do, and the drawn list behind the menu shows the same tasks and the count. 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 tasks, filter and query. For to-do apps, trackers and any list that is fastest to fill by typing.
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 Today 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 a task you ticked in the copy is ticked 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 the priority get into the text?
readQuery looks for !1, !2 or !3 standing alone between spaces, takes the digit as the priority and removes the token from the title, so "Pay invoice !1" adds "Pay invoice" as High. Without a token a task is Medium. The same words search the list, with the token left out. Active tasks sort by priority, and a task already on the list (same words, any case) is refused in words instead of added twice.
Why does Space only tick when the field is empty?
The field is where you type the task, and a title has spaces in it. While it is empty there is nothing to protect, so Space ticks the highlighted task; the hint in the foot shows only then. Enter always works: on the Add row it adds, on a task it ticks. With nothing highlighted, Space says so on the status line instead of guessing.
What do Active, Done and All show, and what is the count?
Active shows the tasks still to do, Done the ticked ones (struck through), and All both groups. The foot counts the tasks still to do whatever the filter says, and the matches while you type, and it is spoken a moment after typing stops. Filtering to Done with nothing ticked shows an empty state that says what to do, in the same shell, so nothing around it moves.
What stays local, and how do I wire it?
All of it. The tasks are state in the block and the status line says that nothing is saved. In your app load START from your store, write tick and add through to it, and keep the optimistic update the block already does.
Is it accessible from the keyboard?
Yes. Type to add or search, the arrow keys move through the rows, Enter adds or ticks, Space ticks in an empty field, 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. A drawn box stands for the checkbox, and each row says "to do" or "done" after its title for a screen reader. The rows are options of a cmdk listbox; the block turns off its own fuzzy filter and lists the rows itself.
Related
- Pro
A notes app's command menu shown open as its panel: type a sentence with #tags and Enter saves it to Recent, tag chips filter the list, and a pin button or Alt P moves a note to Pinned.
- Pro
A project board's command menu shown open over four columns: move the selected card to another column with live counts, add a card with a slash and a column word, and filter the board by label.
- Pro
Basic Command Menu
Search everythingA 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.
- Pro
Actions Command Menu
Actions and keysA signing tool's document with its actions menu shown open: nine actions in four groups, a key on the five that change the document that runs them while the menu is open, and a drawn lease whose badge and signature follow.
- Pro
A team chat's command menu shown open as a dock at the bottom end of a channel: search people and channels with unread counts, see the highlighted one's last three messages, and reply from a field under the list.
- Pro
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.