GitHub

Sidebar

A flexible sidebar layout system for building application navigation, ready for CMS integration. Features clean hover effects with left border indicators and translate animations.

CMSPayload CMS Integration

The sidebar navigation can be driven by CMS content, allowing editors to manage navigation items, labels, and structure without code changes.

CMS Demo

See how content editors can configure sidebar navigation:

Loading...
CMS ConfigurationSimulates Payload CMS navigation fields with localization

Payload CMS Example

// In your Payload CMS config
import { CollectionConfig } from "payload/types"

export const SiteSettings: CollectionConfig = {
  slug: "site-settings",
  fields: [
    {
      name: "navigation",
      type: "array",
      fields: [
        { name: "label", type: "text", localized: true, required: true },
        { name: "href", type: "text", required: true },
        {
          name: "icon",
          type: "select",
          options: [
            { label: "Home", value: "home" },
            { label: "Users", value: "users" },
            { label: "Settings", value: "settings" },
          ],
        },
      ],
    },
  ],
}

Rendering CMS Navigation

import {
  Sidebar,
  SidebarContent,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
} from "@mordecai-design-system/ui"
import Link from "next/link"
import { Home, Users, Settings } from "lucide-react"

const icons = { home: Home, users: Users, settings: Settings }

export function AppLayout({ navigation, children }) {
  return (
    <SidebarProvider>
      <Sidebar>
        <SidebarContent>
          <SidebarMenu>
            {navigation.map((item) => {
              const Icon = icons[item.icon]
              return (
                <SidebarMenuItem key={item.href}>
                  <SidebarMenuButton render={<Link href={item.href} />}>
                    {Icon && <Icon className="size-4" />}
                    <span>{item.label}</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
              )
            })}
          </SidebarMenu>
        </SidebarContent>
      </Sidebar>
      <main>{children}</main>
    </SidebarProvider>
  )
}

Basic Usage

Loading...
SidebarA basic sidebar with navigation groups

Installation

pnpm add @corew500/ui

Usage

import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarHeader,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
  SidebarInset,
} from "@mordecai-design-system/ui"
<SidebarProvider>
  <Sidebar>
    <SidebarHeader>Logo</SidebarHeader>
    <SidebarContent>
      <SidebarGroup>
        <SidebarGroupLabel>Section</SidebarGroupLabel>
        <SidebarGroupContent>
          <SidebarMenu>
            <SidebarMenuItem>
              <SidebarMenuButton>Item</SidebarMenuButton>
            </SidebarMenuItem>
          </SidebarMenu>
        </SidebarGroupContent>
      </SidebarGroup>
    </SidebarContent>
  </Sidebar>
  <SidebarInset>
    Your page content
  </SidebarInset>
</SidebarProvider>

Component Hierarchy

The sidebar requires a specific component structure:

SidebarProvider
├── Sidebar
│   ├── SidebarHeader (optional)
│   ├── SidebarContent
│   │   └── SidebarGroup
│   │       ├── SidebarGroupLabel
│   │       └── SidebarGroupContent
│   │           └── SidebarMenu
│   │               └── SidebarMenuItem
│   │                   └── SidebarMenuButton
│   └── SidebarFooter (optional)
└── SidebarInset (main content area)

Variants & Features

Click items to see active states and different styling options.

Loading...

Menu Button Variants

// Default - translate-x hover with left border indicator
<SidebarMenuButton>Dashboard</SidebarMenuButton>

// Highlight - background hover effect (for special items)
<SidebarMenuButton variant="highlight">Settings</SidebarMenuButton>

With Badges

<SidebarMenuButton>
  <Bell className="size-4" />
  <span>Notifications</span>
  <SidebarMenuBadge>12</SidebarMenuBadge>
</SidebarMenuButton>

Active State

<SidebarMenuButton isActive>
  <Home className="size-4" />
  <span>Dashboard</span>
</SidebarMenuButton>

With Links

Use the render prop to render as a link:

import Link from "next/link"

<SidebarMenuButton render={<Link href="/dashboard" />}>
  Dashboard
</SidebarMenuButton>

Collapsible Modes

The sidebar supports three collapsible modes:

// None (default) - Always visible
<Sidebar collapsible="none">...</Sidebar>

// Icon - Collapses to icon-only mode
<Sidebar collapsible="icon">...</Sidebar>

// Offcanvas - Slides over content (mobile-style)
<Sidebar collapsible="offcanvas">...</Sidebar>

Props

SidebarProvider

PropTypeDefaultDescription
defaultOpenenumtrue
openenum
onOpenChange(open: boolean) => void

Sidebar

PropTypeDefaultDescription
sideenumleftWhich side of the viewport the sidebar appears on.
variantenumsidebarVisual style variant of the sidebar. - `sidebar`: Standard sidebar with border separator - `floating`: Rounded corners, shadow, slight inset - `inset`: Background extends under sidebar area
collapsibleenumnoneControls how the sidebar collapses: - `none` (default): Sidebar is always visible, never collapses - `icon`: Sidebar collapses to icon-only width, content shifts - `offcanvas`: Sidebar slides over content (like a drawer), use for mobile-style overlays

SidebarMenuButton

PropTypeDefaultDescription
renderenumAllows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
isActiveenumfalse
tooltipenum
variantenumdefault
sizeenumdefault