Layout

Sidebar

Vertical navigation container with section support.

Nested Sub-Items

Add subItems to any item for nested navigation. On desktop they appear as a right-side popover; on mobile they expand as an accordion. Sub-items support href, linkComponent, icon, badge, and onClick.

'use client'

import React from 'react'
import Link from 'next/link'
import { Sidebar } from 'biibaos'
import type { SidebarLinkSection } from 'biibaos'
import { Users, FileText } from 'lucide-react'

export default function App() {
  const links: SidebarLinkSection[] = [
    {
      title: 'Management',
      items: [
        {
          label: 'Users',
          icon: <Users size={14} />,
          subItems: [
            { label: 'Team Members',        href: '/users/team'         },
            { label: 'Roles & Permissions', href: '/users/roles'        },
            { label: 'Invites',             href: '/users/invites'      },
          ],
        },
        {
          label: 'Billing',
          icon: <FileText size={14} />,
          subItems: [
            { label: 'All Invoices',        href: '/billing/invoices'   },
            { label: 'Recurring Settings',  href: '/billing/recurring'  },
          ],
        },
      ],
    },
  ]

  return (
    <Sidebar width={240} links={links} linkComponent={Link} />
  )
}

Responsive Bottom Nav

At ≤ 900 px the sidebar automatically hides and renders a macOS dock-style bottom nav from items that have a navId. Items without navId stay sidebar-only. Pass autoNav={false} to opt out.

Resize your window below 900 px to see the bottom nav appear.

Items with navId register in the dock. Items without navId stay sidebar-only.

'use client'

import React, { useState } from 'react'
import Link from 'next/link'
import { usePathname, useRouter } from 'next/navigation'
import { Sidebar } from 'biibaos'
import type { SidebarLinkSection } from 'biibaos'
import { BookOpen, Palette, Wrench } from 'lucide-react'

export default function App() {
  const pathname = usePathname()
  const router = useRouter()
  const [isOpen, setIsOpen] = useState(false)

  const links: SidebarLinkSection[] = [
    {
      title: 'Getting Started',
      items: [
        // navId → appears in the bottom dock on small screens
        { label: 'Introduction', href: '/docs',    icon: <BookOpen size={14} />, navId: 'docs',    active: pathname === '/docs'    },
        { label: 'Theming',      href: '/theming', icon: <Palette  size={14} />, navId: 'theming', active: pathname === '/theming' },
        // no navId → sidebar-only, never shown in the dock
        { label: 'Helpers',      href: '/helpers', icon: <Wrench   size={14} />,                   active: pathname === '/helpers' },
      ],
    },
  ]

  const handleNavChange = (id: string) => {
    const item = links.flatMap(s => s.items).find(i => i.navId === id)
    if (item?.href) router.push(item.href)
  }

  return (
    <Sidebar
      fixed
      stickyTop="58px"
      width={240}
      links={links}
      linkComponent={Link}
      isOpen={isOpen}
      onOpen={() => setIsOpen(true)}
      onClose={() => setIsOpen(false)}
      activeId={links.flatMap(s => s.items).find(i => i.active)?.navId}
      onNavChange={handleNavChange}
      showNavLabels
    />
  )
}

Properties

PropTypeDefaultDescription
linksSidebarLinkSection[]Declarative nav config. Pass sections with items and Sidebar renders everything — headings, icons, badges, sub-items, links.
linkComponentReact.ElementTypeDefault link component for all items (e.g. Next.js Link). Can be overridden per item via item.linkComponent.
widthnumber | string240Sidebar width in pixels or any CSS unit.
fixedbooleanRenders the sidebar as position: fixed.
stickyTopnumber | stringTop offset when using fixed layout (e.g. "58px" to clear a navbar).
isOpenbooleanControls the mobile drawer open state.
onOpen() => voidCalled when the user swipes to open the mobile drawer.
onClose() => voidCalled when the user closes the mobile drawer.
autoNavbooleantrueAt ≤ 900 px the sidebar hides and a dock-style bottom nav renders automatically. Set false to opt out.
activeIdstringThe navId of the currently active item. Keeps the bottom nav icon lit correctly.
onNavChange(id: string) => voidCalled when the user taps an item in the bottom nav. Use it to push the correct route.
showNavLabelsbooleantrueShow text labels under icons in the bottom nav.
childrenReact.ReactNodeOptional composed children (SidebarHeader, SidebarFooter, etc.). Rendered after links sections.
item.labelReact.ReactNode(SidebarLinkItem) The item label text.
item.hrefstring(SidebarLinkItem) URL to navigate to when clicked.
item.linkComponentReact.ElementType(SidebarLinkItem) Per-item link component override. Defaults to the Sidebar-level linkComponent.
item.iconReact.ReactNode(SidebarLinkItem) Icon displayed before the label.
item.activeIconReact.ReactNode(SidebarLinkItem) Alternate icon for the active state.
item.badgeReact.ReactNode(SidebarLinkItem) Badge displayed after the label.
item.activeboolean(SidebarLinkItem) Highlights the item as the current active route.
item.navIdstring(SidebarLinkItem) Registers this item in the auto bottom nav. Items without navId are sidebar-only.
item.subItemsSidebarLinkSubItem[](SidebarLinkItem) Nested items — accordion on mobile, popover on desktop. Each supports href, linkComponent, label, icon, badge, active, onClick.
item.onClick(e: React.MouseEvent) => void(SidebarLinkItem) Click handler. Fires even when href is set.