stellify/ui

Components

Sidebar

A collapsible navigation sidebar component with keyboard shortcut, persistent state, and arrow-key navigation.

Preview

Main content area

Usage

<st-sidebar class="border-r bg-card text-foreground">
  <header>
    <a href="/" class="nav-item">
      <svg><!-- logo --></svg>
      <span>App name</span>
    </a>
  </header>

  <nav>
    <div class="nav-section-label">Platform</div>
    <ul>
      <li>
        <a href="/dashboard" class="nav-item">
          <svg><!-- icon --></svg>
          <span>Dashboard</span>
        </a>
      </li>
    </ul>
  </nav>

  <footer>
    <st-menu placement="top-start">
      <button data-menu-trigger type="button">
        <span><!-- avatar --></span>
        <span>User name</span>
      </button>
      <div data-menu-content role="menu" hidden>
        <!-- menu items -->
      </div>
    </st-menu>
  </footer>
</st-sidebar>

Class Hooks

The component recognises these conventional class names on descendants:

Class Purpose
.nav-item Navigation entries. In rail mode, text labels hide and icons centre. The icon must be the first child.
.nav-section-label Section headings like "Platform" or "Settings". Hidden in rail mode.

Toggle Button

Any element with the data-sidebar-toggle attribute will toggle the sidebar when clicked:

<button type="button" data-sidebar-toggle>Toggle sidebar</button>

If the sidebar has an id, use aria-controls for explicit pairing.

Keyboard Shortcuts

Key Action
⌘B / Ctrl+B Toggle sidebar state from anywhere on the page
/ Move focus between .nav-item elements

CSS Variables

Variable Default Purpose
--st-sidebar-width 16rem Expanded width
--st-sidebar-rail-width 4rem Collapsed width
--st-sidebar-duration 200ms Transition duration

What You No Longer Need

The component handles these behaviours automatically:

  • Width classes like w-64, data-[state=rail]:w-16
  • Transition classes like transition-[width], duration-200
  • Flex direction or overflow on the sidebar itself
  • Per-element collapse classes (sidebar-rail:hidden, etc.)