EnterUI
DocsComponentsThemesExamplesDonation
Get Started
      • Sidebar
      • SideNav
      • NavigationRail
      • TopBar
      • SearchCommand

Default usage

  1. EnterUI
  2. /Docs
  3. /Layout and Utilities
  4. /App Layout
  5. /Navigation Surfaces
  6. /Sidebar
Updated 9 October 2026

Sidebar

Sidebar primitives with application-controlled navigation and expansion.

Sidebar defines how EnterUI handles polished product navigation: a quiet glass surface with a built-in 268px maximum width, counted sections with optional icons, nested branches, active descriptions, badges, and disabled “Soon” rows.

Collapsible sections and branches show a small disclosure chevron that rotates when expanded. Counts remain visible as compact, right-aligned pills with tabular numbers. Counts are secondary to labels; they represent the value supplied by the app. Section icons use a light frame without elevation; use consistent outline icons with meanings that match each category. Nested lists have a quiet rail. Active links use the soft aqua surface and foreground tokens in both themes, keeping the same dimensions. Inactive hover uses the lighter hover treatment. The documentation sidebar uses these shared styles directly, with its Next.js links retaining EnterUI item classes for client navigation and pending feedback.

#Default usage

The previews show two active states of the same navigation structure: a top-level onboarding page and a nested ButtonGroup page. Compose both from public Sidebar primitives; Sidebar owns the card width, section dividers, count pills, nested rail, and selected surface. The docs navigation adds routing and pending-state behavior, but its visual hierarchy is available in the default component. Do not copy .docs-sidebar__* classes or add custom styles to examples. These previews are static visual states; wire branch buttons to controlled expansion as shown below.

Active top-level page

Section icons, inline counts, spaced groups, a two-line active description, and nested component links use the Sidebar defaults.

  • Overview
  • Introduction
  • Installation
  • SolidJS Renderer
  • Theming
  • Styling Philosophy
  • Production Checklist
  • Migration & Versioning
  • Component onboardingStart with the recommended component setup and onboarding flow.
    • Button
    • ButtonGroup
    • IconButton
    • Link

Active nested page

Place the active state on the nested link while keeping its parent branch expanded.

  • Overview
  • Introduction
  • Installation
  • SolidJS Renderer
  • Theming
  • Styling Philosophy
  • Production Checklist
  • Migration & Versioning
  • Component onboarding
    • Button
    • ButtonGroup
    • IconButton
    • Link
Code
<Sidebar>
  <SidebarSection>
    <SidebarBranch variant="section" count={8} icon={<BookOpenText aria-hidden="true" size={14} />} expanded>
      Getting Started
    </SidebarBranch>
    <SidebarNav>
      <SidebarList>
        <SidebarListItem><SidebarItem href="/enter-ui/docs">Overview</SidebarItem></SidebarListItem>
        <SidebarListItem><SidebarItem href="/enter-ui/docs/introduction">Introduction</SidebarItem></SidebarListItem>
        <SidebarListItem><SidebarItem href="/enter-ui/docs/installation">Installation</SidebarItem></SidebarListItem>
        <SidebarListItem><SidebarItem href="/enter-ui/docs/solidjs">SolidJS Renderer</SidebarItem></SidebarListItem>
        <SidebarListItem><SidebarItem href="/enter-ui/docs/theming">Theming</SidebarItem></SidebarListItem>
        <SidebarListItem><SidebarItem href="/enter-ui/docs/styling-philosophy">Styling Philosophy</SidebarItem></SidebarListItem>
        <SidebarListItem><SidebarItem href="/enter-ui/docs/production-checklist">Production Checklist</SidebarItem></SidebarListItem>
        <SidebarListItem><SidebarItem href="/enter-ui/docs/migration-versioning">Migration &amp; Versioning</SidebarItem></SidebarListItem>
      </SidebarList>
    </SidebarNav>
  </SidebarSection>
  <SidebarSection>
    <SidebarBranch variant="section" count={21} icon={<Component aria-hidden="true" size={14} />} expanded>
      Foundations
    </SidebarBranch>
    <SidebarNav>
      <SidebarList>
        <SidebarListItem>
          <SidebarItem active description="Start with the recommended component setup and onboarding flow." href="/enter-ui/docs/components">Component onboarding</SidebarItem>
        </SidebarListItem>
        <SidebarListItem>
          <SidebarBranch count={4} expanded>Actions</SidebarBranch>
          <SidebarList nested>
            <SidebarListItem><SidebarItem href="/enter-ui/docs/components/button" nested>Button</SidebarItem></SidebarListItem>
            <SidebarListItem><SidebarItem href="/enter-ui/docs/components/button-group" nested>ButtonGroup</SidebarItem></SidebarListItem>
            <SidebarListItem><SidebarItem href="/enter-ui/docs/components/icon-button" nested>IconButton</SidebarItem></SidebarListItem>
            <SidebarListItem><SidebarItem href="/enter-ui/docs/components/link" nested>Link</SidebarItem></SidebarListItem>
          </SidebarList>
        </SidebarListItem>
        <SidebarListItem><SidebarBranch count={6} expanded={false}>Surfaces and Indicators</SidebarBranch></SidebarListItem>
        <SidebarListItem><SidebarBranch count={7} expanded={false}>Content</SidebarBranch></SidebarListItem>
        <SidebarListItem><SidebarBranch count={3} expanded={false}>Disclosure</SidebarBranch></SidebarListItem>
      </SidebarList>
    </SidebarNav>
  </SidebarSection>
  <SidebarSection>
    <SidebarBranch variant="section" count={34} icon={<FormInput aria-hidden="true" size={14} />} expanded={false}>Inputs</SidebarBranch>
  </SidebarSection>
  <SidebarSection>
    <SidebarBranch variant="section" count={12} icon={<CalendarDays aria-hidden="true" size={14} />} expanded={false}>Scheduling</SidebarBranch>
  </SidebarSection>
</Sidebar>

To show the nested state, move active to ButtonGroup and remove the onboarding description; keep Actions expanded so the nested links remain visible.

#Import

Code
import { BookOpenText, Component, FormInput, CalendarDays } from "lucide-react";
import {
  Sidebar,
  SidebarBranch,
  SidebarItem,
  SidebarList,
  SidebarListItem,
  SidebarNav,
  SidebarSection,
} from "@froggdesign/enter-ui-react";

#Behavior ownership

SidebarBranch renders a button and announces expanded; it does not manage state or hide its child list. The application owns open branch IDs, conditional child rendering, route matching, and automatic expansion of active ancestors. SidebarSectionTitle is a heading, not a clickable accordion trigger. Counts are supplied by the app, not calculated by Sidebar. In a workspace AppShell, keep grouped navigation vertical on narrow screens; the sidebar moves above the main content and scrolls within a bounded height. Show a concise description on the active link and retain nested lists under their branch buttons.

DocsSidebar adds recursive navigation and pending-route feedback in the web app. Neither behavior is provided by the package. Multiple branches can be open; single-open accordion behavior is not automatic. Native buttons support Enter/Space, but this is not an ARIA tree with arrow-key navigation.

Code
"use client";
import { useId, useState } from "react";
import {
  Sidebar, SidebarSection, SidebarBranch, SidebarList,
  SidebarListItem, SidebarItem,
} from "@froggdesign/enter-ui-react";

export function ProjectNavigation({ activeHref }: { activeHref: string }) {
  const listId = useId();
  const [open, setOpen] = useState(true);
  return (
    <Sidebar aria-label="Projects">
      <SidebarSection>
        <SidebarBranch variant="section" count={1} expanded={open}
          aria-controls={listId} onClick={() => setOpen((value) => !value)}>
          Projects
        </SidebarBranch>
        {open && (
          <SidebarList id={listId} nested>
            <SidebarListItem>
              <SidebarItem href="/projects/design" nested
                active={activeHref === "/projects/design"}>
                Design
              </SidebarItem>
            </SidebarListItem>
          </SidebarList>
        )}
      </SidebarSection>
    </Sidebar>
  );
}

Supply activeHref from your router. This minimal example does not auto-open ancestors when the route changes; implement that policy in the application. Mobile navigation and loading feedback also remain application responsibilities.

#Accessibility

Sidebar renders an aside. SidebarNav renders nav. Active items set aria-current="page"; disabled items set aria-disabled and prevent navigation. SidebarBranch renders a real button with aria-expanded for collapsible branches.

Sticky navigation

Opt into independent viewport scrolling in a persistent route layout.

  • API
  • Styling

#API

  • sticky: opt into a viewport-constrained sidebar below a 72px header. Its navigation scrolls independently and remains mounted when the surrounding route layout is persistent. Keep route matching and expansion state in the consumer. Leave it off inside a mobile drawer with its own scroll container.

  • SidebarSectionTitle: optional icon and count slots.

  • SidebarBranch: active, expanded, count, description, icon, and variant="default" | "section". Supply onClick and controlled child rendering for collapsible rows.

  • SidebarItem: active, disabled, badge, description, nested, and anchor props.

  • SidebarList and SidebarListItem: list structure for top-level and nested navigation.

  • Use public hrefs rather than app-internal deep imports.

#Styling

The default Sidebar owns its 268px maximum width, scales down to its container, and fills narrow screens below 600px. The workspace variant fills its AppShell slot instead. Compose the public primitives without layout wrappers or style overrides. EnterUI styles use .eui-* classes and --eui-* variables mapped from FroggDesign theme tokens.

#Workspace presentation

Use <Sidebar variant="workspace"> for navigation on the page canvas. The variant fills its AppShell slot and owns its surface and responsive height independently of AppShell.

Rows with descriptions use a compact 54px minimum; single-line links retain 40px hit areas. Section dividers are omitted in the workspace variant.

PreviousSectionHeader
NextSideNav
On this page
  • Default usage
  • Import
  • Behavior ownership
  • Accessibility
  • API
  • Styling
  • Workspace presentation