GitHub

Sidebar List

Providerless grouped-row primitives for embedded domain sidebars and File Viewer rail content.

SidebarList* primitives provide sidebar row grammar without SidebarProvider. Use them when a component needs grouped rows, active states, disabled states, and sidebar tokens, but does not own app navigation, persistence, mobile sheet projection, or global shortcuts.

SegmentSidebar and AttachmentSidebar use this layer internally.

Installation

pnpm dlx shadcn@latest add @retab/sidebar-list

Example

This example shows the primitive row grammar directly: root, header, content, groups, labels, menu items, active rows, disabled rows, and separators.

Document workspace
Providerless grouped rows for embedded rails.
Inbox
Archive

Usage

import {
  SidebarListButton,
  SidebarListContent,
  SidebarListGroup,
  SidebarListGroupContent,
  SidebarListGroupLabel,
  SidebarListHeader,
  SidebarListMenu,
  SidebarListMenuItem,
  SidebarListRoot,
} from "@/components/ui/sidebar-list";
 
export function Example() {
  return (
    <SidebarListRoot width="18rem">
      <SidebarListHeader>Attachments</SidebarListHeader>
      <SidebarListContent>
        <SidebarListGroup>
          <SidebarListGroupLabel>Files</SidebarListGroupLabel>
          <SidebarListGroupContent>
            <SidebarListMenu>
              <SidebarListMenuItem>
                <SidebarListButton isActive>contract.pdf</SidebarListButton>
              </SidebarListMenuItem>
            </SidebarListMenu>
          </SidebarListGroupContent>
        </SidebarListGroup>
      </SidebarListContent>
    </SidebarListRoot>
  );
}

Use SidebarList* inside FileViewerSidebar only as content grammar. The enclosing FileViewerSidebar still owns placement, width, collapse behavior, and the accessible rail label.

<FileViewerSidebar aria-label="Document workspace" width="20rem">
  <SidebarListRoot width="20rem">
    <SidebarListHeader>Workspace</SidebarListHeader>
    <SidebarListContent>
      <SidebarListGroup>
        <SidebarListGroupLabel>Sources</SidebarListGroupLabel>
        <SidebarListGroupContent>
          <SidebarListMenu>
            {items.map((item) => (
              <SidebarListMenuItem key={item.id}>
                <SidebarListButton
                  isActive={activeId === item.id}
                  onClick={() => setActiveId(item.id)}
                >
                  {item.label}
                </SidebarListButton>
              </SidebarListMenuItem>
            ))}
          </SidebarListMenu>
        </SidebarListGroupContent>
      </SidebarListGroup>
    </SidebarListContent>
  </SidebarListRoot>
</FileViewerSidebar>

Button Rendering

SidebarListButton renders a button by default and sets type="button" for native button output. Use asChild or render when the row should be another element:

<SidebarListButton asChild isActive>
  <a href="/docs/components/file-viewer">File viewer</a>
</SidebarListButton>

Do Not Use For

  • app navigation;
  • mobile sidebar sheets;
  • global sidebar shortcuts;
  • PDF thumbnail virtualization;
  • file-viewer spatial placement.

API Reference

ComponentBase propsNotes
SidebarListRootReact.ComponentProps<"div">Accepts width?: string.
SidebarListHeaderReact.ComponentProps<"div">Header area above scrollable content.
SidebarListContentReact.ComponentProps<"div">Scrollable grouped-row area.
SidebarListGroupReact.ComponentProps<"div">One logical section.
SidebarListGroupLabelReact.ComponentProps<"div">Section label row.
SidebarListGroupContentReact.ComponentProps<"div">Wrapper around one group's rows.
SidebarListMenuReact.ComponentProps<"ul">List container.
SidebarListMenuItemReact.ComponentProps<"li">List item wrapper.
SidebarListButtonuseRender.ComponentProps<"button">Adds isActive, variant, size, asChild.
SidebarListSeparatorSeparator propsSeparator aligned to sidebar inset.

SidebarListButton supports the sidebar row variants from sidebarRowButtonVariants: variant="default" | "outline" and size="default" | "sm" | "lg".

Source

sidebar-list.tsx