Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Sub-Menus Sidebar Block for React

A recipe manager in a fixed-height window whose floating sidebar has sections with sub-menus, a switch between One at a time and Keep open, and arrow keys that open a sub-menu toward the end of the line and close it toward the start.

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

Decide how a menu's sub-menus behave with this sub-menus sidebar for React with Base UI. A window framed by a hairline with a plus mark on each corner holds a floating Sidebar of five meal sections, Breakfast, Lunch, Dinner, Baking and Drinks, each with a sub-menu of collections: Dinner holds Pasta, Curries and Roasts. A Segment Group over the menu sets the mode. In One at a time, opening a section closes the others, like an accordion; in Keep open, any number can stay open, with a count of how many. On a section's row the arrow toward the end of the line opens its sub-menu and the one toward the start closes it, so the menu works from the keyboard the way a tree does; from a collection the start arrow closes the section and returns to its row. The page lists the chosen collection's recipes with their times and servings. It's built from Sidebar, Collapsible, Segment Group, Badge and Guides, with a CSS entrance only. Folded to icons the rail keeps the five section icons, and pressing one unfolds it; below the medium breakpoint it is a sheet. For recipes, settings, help and any menu where the right behaviour is a choice.

FAQ

What do the two modes do?

In One at a time, afterToggle returns a list of just the section you opened, so the others close, and the status line says which: "Opened Baking. Dinner closed. 1 open." In Keep open it adds the section to the list instead. Switching to One at a time with several open keeps only the section that holds the current page, or the first open one if none does, and says what it closed. Switching to Keep open changes nothing until you open another.

How do the arrow keys work?

With focus on a section's row, the arrow toward the end of the line opens its sub-menu, and the one toward the start closes it. With focus on a collection, the start arrow closes its section and puts focus back on the section's row. In a right-to-left layout the two arrows swap, because the block reads the direction from the element. The keys are caught for the whole rail in the capture phase, because React Aria's buttons stop a key before it bubbles, and they obey the mode: in One at a time, opening with the arrow closes the others too. Enter and Space still toggle a row.

Where does the count come from?

It is the length of the list of open sections, shown under the mode switch and spoken in the status line after every change. It is never typed, so it cannot disagree with what is open.

What happens when the sidebar folds to icons?

The menu button or the rail along the edge folds it to the five section icons with tooltips, and the sub-menus and the mode switch are hidden. Pressing a section icon unfolds the rail and opens that section. The provider is set with persist={false} and shortcut={false}, so the block writes no cookie and leaves Ctrl and Command with B to the page it sits on.

What stays in the page, and how do I connect it?

Everything. The fifteen collections and their recipes are typed in SECTIONS at the top of the file, and choosing one swaps the list in the block's own state; nothing is saved. The collections are links to # whose handler shows the list instead of navigating. Each section row is a SidebarMenuButton that flips its own sub-menu: it carries its own aria-expanded and a press handler, onClick, over a controlled Collapsible, rather than being the Collapsible's trigger, because a row's tooltip and a trigger would both claim the button's id. Point the links at your routes and mark the current one with isActive and aria-current.

How does it work on a phone?

Below the medium breakpoint the sidebar is a sheet that the menu button in the top bar opens from the start edge, the right in a right-to-left layout. The mode switch and the sub-menus are inside it, and choosing a collection closes the sheet and puts focus back on the button. The status line under the page says what opened and how many sections are open.

  • Pro

    A design system's docs in a fixed-height window whose sidebar rows are split: a label that opens a section's overview and a separate chevron that opens its sub-menu, with a count of pages on each row.

  • Pro

    A framework's docs in a fixed-height window whose slim sidebar has five groups that fold from their labels, with Expand all and Collapse all, a count of open groups and a dot on a folded group that holds the current page.

  • Pro

    A CSS toolkit's docs in a fixed-height window with a floating sidebar: a rounded card inset from the window over a tinted shell, five collapsing sections of pages, and a switch to the flush rail for comparison.

  • Pro

    A help centre in a fixed-height window whose wide sidebar folds three levels deep, categories that hold topics that hold articles, with a Reveal active button that opens only the folds above the open article.

  • Pro

    A docs host in a fixed-height window whose sidebar is a numbered outline that opens the folds above the page you choose, an Auto-collapse switch that closes the rest, a breadcrumb over the page and Previous and Next buttons in the top bar.

  • Pro

    A grocery app in a fixed-height window whose inset sidebar drills down one level at a time, panel by panel up to four levels deep, with a back button, Escape and a breadcrumb that all go up.