Moul UIBeta
Blocks

Sidebar

A premium collapsible navigation sidebar block styled with StyleX and built with React Aria.

Sidebar

The Sidebar is a complete navigation block component designed in the style of Apple Music and Podcasts. It features collapsible groups, custom item selections, active/hover styles, glassmorphic layout options, profile/branding sections, and a responsive toggle to collapse to an icon-only view.

Preview

Sidebar Preview

Full Page

Experience the complete responsive layout component with live controls and collapsible navigation states.


Import

import {
  Sidebar,
  SidebarAside,
  SidebarMain,
  SidebarHeader,
  SidebarBrand,
  SidebarGroup,
  SidebarItem,
  SidebarFooter,
  SidebarUser,
  SidebarDivider,
} from '@moul-dev/ui';

Layout Structure

The Sidebar is built as a set of compound components for complete flexibility:

<Sidebar selectedKey={activeKey} onSelectionChange={setActiveKey}>
  <SidebarAside>
    <SidebarHeader>
      {/* Branding, search bar or logo */}
    </SidebarHeader>

    <SidebarGroup title="Group Name">
      <SidebarItem id="home" icon={<HomeIcon />}>Home</SidebarItem>
      <SidebarItem id="settings" icon={<SettingsIcon />}>Settings</SidebarItem>
    </SidebarGroup>

    <SidebarDivider />

    <SidebarFooter>
      {/* Account profile, user email, logout */}
    </SidebarFooter>
  </SidebarAside>

  <SidebarMain>
    {/* Main dashboard or route content */}
  </SidebarMain>
</Sidebar>

Features

Collapsible Groups

Wrapping navigation links in SidebarGroup automatically supports group collapsibility. When collapsible is enabled, clicking the group title toggles item visibility with a smooth grid-based transition.

Icon-Only Collapse Mode

Setting the isCollapsed prop shrinks the sidebar to a slim icon-only strip. When collapsed:

  • Text labels in SidebarItem are hidden.
  • Hovering over a collapsed item displays a premium Tooltip showing the item's label.
  • Group headers and sub-content are collapsed/hidden.

Dense Mode

Enable dense on <Sidebar> (or individual subcomponents) to render a compact navigation layout. In dense mode:

  • Item heights are reduced from 36px to 30px with tighter padding and gaps.
  • Header and footer minimum heights are reduced to 48px.
  • Group headers and dividers have tighter spacing.
  • Collapsed icons are scaled to 30px square while maintaining consistent alignment.

Mobile Floating Bottom Navigation

On mobile devices (@media (max-width: 768px)), the sidebar automatically transforms into an app-like floating bottom dock with native-feeling spring physics powered by motion (motion.dev). The architecture uses a compile-time CSS-first dual-DOM approach that renders cleanly in Server-Side Rendering (SSR) environments with zero layout shift (CLS) and zero hydration mismatch:

  • Sticky Floating Dock: Positioned centrally above the bottom safe area with glassmorphic blur and subtle elevation.
  • Scroll & Swipe Reactivity: When scrolling down or swiping upwards, the dock smoothly scales down to a compact icon bar (~0.90x) and the top bar slides out of view to maximize reading estate. Scrolling up or swiping down restores full size and labels with spring animation.
  • Active Pill Animation: Switching between items animates a smooth sliding pill background using motion's shared layout transitions (layoutId).
  • Collection Overflow & "More" Drawer: The primary items (up to maxMobileItems, default 4) are presented directly on the dock. Additional items, secondary groups, and user account profiles are consolidated into a "More" (...) trigger that opens an accessible bottom sheet <Drawer>.

Styling & Layout Variants

Supports both solid (flat background) and glass (glassmorphic translucent backdrop filter) modes out of the box using the variant prop.

Additionally, the layout prop controls the spatial hierarchy:

  • sidebar-framed (default): Sidebar renders as a floating rounded card, while the main content area inherits the transparent canvas background.
  • main-framed: Inverted canvas layout where the sidebar is flush with the screen edge using the body background, and the main workspace is framed as a rounded, elevated card with subtle borders.

API Reference

PropTypeDefaultDescription
layout'sidebar-framed' | 'main-framed' | 'default' | 'inset''sidebar-framed'Visual hierarchy mode controlling whether the sidebar or main content area is framed.
densebooleanfalseWhether to render the sidebar and its child elements in compact dense mode.
isCollapsedbooleanfalseControlled state for whether the sidebar is collapsed to icon-only.
defaultCollapsedbooleanfalseUncontrolled default state for the collapse layout.
onCollapseChange(collapsed: boolean) => void—Callback triggered when the collapse state changes.
selectedKeystring—The active/selected item ID (controlled).
defaultSelectedKeystring—The initial active item ID (uncontrolled).
onSelectionChange(key: string) => void—Callback triggered when a new item is selected.
variant'solid' | 'glass''solid'Aesthetic variant of the framed element background.
enableMobileNavbooleantrueWhether to automatically transform to a floating sticky bottom dock on mobile viewports (<= 768px).
mobileNavScaleOnScrollbooleantrueWhether the floating bottom dock scales down and top bar hides during downward scroll/swipe.
maxMobileItemsnumber4Maximum number of primary items rendered directly on the bottom dock before consolidating into the More drawer.

SidebarAside Props

PropTypeDefaultDescription
showCollapseTogglebooleantrueRenders a built-in floating chevron toggle at the bottom edge.

SidebarMain Props

Accepts standard JSX children and compile-time StyleX layout overrides via the style prop.

SidebarHeader Props

PropTypeDefaultDescription
densebooleanfalseOptional override for compact dense styling. Inherits from <Sidebar>.

SidebarBrand Props

PropTypeDefaultDescription
logoReactNode—Logo icon or badge rendered on the leading edge.
titleReactNode—Primary brand title text.
subtitleReactNode—Secondary subtitle or version text.
densebooleanfalseCompact styling override.
onPress() => void—Optional callback making the brand trigger interactive.

SidebarGroup Props

PropTypeDefaultDescription
titlestring—The label text displayed at the top of the group.
collapsiblebooleantrueWhether the group can be expanded/collapsed.
defaultExpandedbooleantrueThe initial expansion state of the group.
isExpandedboolean—Controlled expansion state.
onExpandedChange(expanded: boolean) => void—Callback triggered when group expansion state toggles.
densebooleanfalseOptional override for compact dense styling. Cascades to child items.

SidebarItem Props

PropTypeDefaultDescription
idstring—Unique key representing the item (used for selection modeling).
hrefstring—Render as a link using React Aria's Link capabilities.
iconReactNode—The SVG or custom react component rendered on the left of the label.
isSelectedboolean—Manual override to mark the item as selected.
densebooleanfalseOptional override for compact dense styling. Inherits from group/sidebar.

SidebarDivider Props

PropTypeDefaultDescription
densebooleanfalseOptional override for compact margin spacing. Inherits from <Sidebar>.

SidebarFooter Props

PropTypeDefaultDescription
showBorderbooleantrueWhether to display a divider border above the footer content.
densebooleanfalseOptional override for compact dense styling. Inherits from <Sidebar>.

SidebarUser Props

PropTypeDefaultDescription
avatarReactNode—The Avatar component or custom node rendered on the leading edge.
nameReactNode—User's display name.
descriptionReactNode—User's email, handle, or subtitle.
actionReactNode—Optional trailing action (e.g. icon button or menu trigger).
densebooleanfalseCompact styling override.
onPress() => void—Optional callback making the user profile item interactive.

On this page