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.
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/uiUsage
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
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultOpen | enum | true | — |
| open | enum | — | — |
| onOpenChange | (open: boolean) => void | — | — |
Sidebar
| Prop | Type | Default | Description |
|---|---|---|---|
| side | enum | left | Which side of the viewport the sidebar appears on. |
| variant | enum | sidebar | Visual style variant of the sidebar. - `sidebar`: Standard sidebar with border separator - `floating`: Rounded corners, shadow, slight inset - `inset`: Background extends under sidebar area |
| collapsible | enum | none | Controls 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
| Prop | Type | Default | Description |
|---|---|---|---|
| render | enum | — | Allows 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. |
| isActive | enum | false | — |
| tooltip | enum | — | — |
| variant | enum | default | — |
| size | enum | default | — |