shadcn.io is not affiliated with official shadcn/ui
Docs Tree Command Menu Block for React
An API docs host's page finder as a command menu shown open on a tree: sections open into indented pages with the arrow keys, typing flattens the tree and matches the headings inside pages, and the foot counts the open sections.
Installation
Overview
Walk a documentation site without leaving the keyboard with this docs tree command menu for React with Base UI. It opens from the API docs page of Leafbound, a host for developer documentation, whose header holds an outline field with its ⌘ K cap, and the docs page is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The menu is the catalog Command shown as a tree. Six sections are rows with a chevron; the arrow toward the end (or a click, or Enter) opens one into its indented pages and the arrow toward the start folds it, or, on a page, goes back up to its section. A band at the top says what is being read and holds Collapse all. Under the tree sit Recent and Popular pages. Type, and the tree flattens: pages and the headings inside them match every word you typed, and a heading comes with its path, "Auth › Tokens › Refreshing". The foot counts how many sections are open and, while you type, how many results there are. Choosing a page names it on the drawn page; nothing loads. 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 tree and the same query. For documentation sites, API references and knowledge bases with more than a few dozen pages.
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 docs site, 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 open sections and the text you typed in the copy are in the real 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 is the tree built from a list?
rowsFor(query, opened) is a plain function from the query and the sections you opened to a flat list of rows: each section, then its pages when it is open, then Recent and Popular. Nothing nests in the markup; a page under an open section is indented and names its section for screen readers ("Tokens, in Auth"), and a section row says whether it is open or folded. The arrow keys work while the input is empty; in a right-to-left page the keys swap, as they do in any tree.
How do the arrow keys know which row they are on?
They read the highlighted row, which the block keeps from the library. The Command is cmdk, whose highlighted value is controlled with value and onValueChange. To go back up to a section the block presses the Up arrow for you in the input, as many times as there are rows between, so the library's own highlight does the move.
What stays local, and how do I wire it up?
Everything. Choosing a page names it on the drawn docs page and the status line says nothing loaded. In your app build SECTIONS and PAGES from your site's navigation and the headings of each page (a build step can extract them), keep Recent in local storage, and in pick go to the page and its heading.
Is it accessible from the keyboard?
Yes. Type to search, the arrow keys move through the rows (and, with the input empty, open and fold the tree), Enter opens a page or toggles a section and Escape closes the menu and puts focus on the 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. Collapse all is a button above the input; it stays in the tab order even when nothing is open and then says every section is already folded.
How does it look on a phone?
The copy shown on load docks to the top of the page at full width, so the keyboard does not cover the foot; the section names stay, the section labels on Recent and Popular and the key hints go and the count stays. The real dialog keeps the Command dialog's own phone layout.
Related
- Pro
Page Stack Breadcrumb Command Menu
Pages and docsA CMS page browser as a command menu shown open as a page stack: a trail of crumbs over the list, the arrow keys go into a folder and back out, and a page closes the menu and names itself on the page list behind.
- 471Pro
Docs Search Command Menu
Search everythingA docs host's scoped search shown open under the header field: chips for All, Guides, Reference and Releases that carry how many pages match, and results with a path and one line of the page with the matched words marked.
- Pro
Help Center Command Menu
Pages and docsA messaging app's help centre as a command menu shown open beside an article pane: articles and video tutorials filter as you type, the pane shows the highlighted one's first paragraph, three headings and related reading, and a contact support row is never filtered out.
- 333Pro
Global Search Command Menu
Search everythingA company intranet's command menu shown open: one input searches pages, docs, people and tags at once, each type is a group of three matches with a row that opens it in place, and the foot counts the results by type.
- Pro
Recent Items Command Menu
Search everythingA project hub's command menu shown open on what you opened lately: Today, Yesterday and Earlier buckets before you type, recent matches first when you do, opening a row moves it to the top, and a last row clears the list.
- Pro
Command Palette FAQ
SearchA FAQ for a docs host with a working command palette: a search-field button with its shortcut opens a palette of questions by topic, and choosing one opens its row below.