Sidebar Primitive

A composable Core layout primitive for physical side placement, controlled or uncontrolled collapse, accessible toggling, and tokenized regions.

Overview and decision boundary

Use Sidebar Primitive for a persistent collapsible page region while keeping routes, navigation data, menus, permissions, and persistence in consumer code.

Do not add route matching, navigation schemas, persistence, authorization, or account behavior to Core Sidebar.

Installation and imports

Install the editable registry source, or use the matching package entrypoint when the product keeps Nerio as a workspace dependency.

pnpm dlx nerio add sidebar-primitiveimport { SidebarContent, SidebarFooter, SidebarHeader, SidebarInset } from '@nerio-ui/ui';import { Sidebar, SidebarProvider, SidebarRail, SidebarTrigger } from '@nerio-ui/ui/client';

Usage

import { SidebarContent, SidebarFooter, SidebarHeader, SidebarInset } from '@nerio-ui/ui';import { Sidebar, SidebarProvider, SidebarRail, SidebarTrigger } from '@nerio-ui/ui/client';<SidebarProvider defaultExpanded side="left">  <Sidebar aria-label="Workspace sidebar">    <SidebarHeader>Workspace</SidebarHeader>    <SidebarContent>      <nav aria-label="Workspace">...</nav>    </SidebarContent>    <SidebarFooter>...</SidebarFooter>    <SidebarRail label="Toggle workspace sidebar" />  </Sidebar>  <SidebarInset>    <SidebarTrigger label="Toggle workspace sidebar" />    ...  </SidebarInset></SidebarProvider>

Variants

VariantPurpose
side: left | rightSide: left | right is part of the public component contract.
direction: ltr | rtlDirection: ltr | rtl is part of the public component contract.
controlledControlled is part of the public component contract.
uncontrolledUncontrolled is part of the public component contract.
comfortable densityComfortable density is part of the public component contract.
compact densityCompact density is part of the public component contract.

Anatomy

SlotPurpose
sidebar-providerSidebar Provider slot exposed through data-slot="sidebar-provider".
sidebarComplementary aside with physical side and state data.
sidebar-innerSidebar Inner slot exposed through data-slot="sidebar-inner".
sidebar-headerSidebar Header slot exposed through data-slot="sidebar-header".
sidebar-contentSidebar Content slot exposed through data-slot="sidebar-content".
sidebar-footerSidebar Footer slot exposed through data-slot="sidebar-footer".
sidebar-railSidebar Rail slot exposed through data-slot="sidebar-rail".
sidebar-insetSidebar Inset slot exposed through data-slot="sidebar-inset".
sidebar-triggerSidebar Trigger slot exposed through data-slot="sidebar-trigger".

States

StatePurpose
ExpandedAll static regions and consumer content are available.
CollapsedInner content is inert, hidden, and removed from keyboard interaction.
Controlledexpanded and onExpandedChange let consumers own state and persistence.

Motion

  • Width and content visibility use the Sidebar transition tokens.
  • Reduced-motion preference removes the visible transition without changing state behavior.

Accessibility

  • Sidebar renders complementary aside semantics by default; place a labelled navigation landmark inside SidebarContent when the content is navigation.
  • SidebarTrigger and SidebarRail require a localized label and expose aria-expanded plus a stable aria-controls relationship.
  • SidebarRail is vertically centered and occupies only --n-sidebar-rail-hit-area so adjacent Sidebar and SidebarInset content remains pointer reachable.
  • SidebarContent forwards an HTMLDivElement ref, while SidebarInset preserves stable HTMLElement refs for its explicit div or main root.
  • Collapsed Sidebar content is inert, hidden, and removed from pointer and keyboard interaction while SidebarRail remains reachable.
  • State changes keep focus on the external trigger or rail and do not add roving focus or Arrow-key behavior to consumer navigation.
  • Physical left and right placement, explicit text direction, reduced motion, forced colors, compact density, and safe-area padding are supported.
  • Persistence and mobile behavior remain consumer-owned; compose Sheet explicitly for mobile navigation so only one interactive tree is rendered.

API

PropPurpose
SidebarProviderdefaultExpanded, expanded, onExpandedChange, side, direction, and optional sidebarId.
SidebarClient root that reflects provider state through data-state and data-side.
SidebarHeader / SidebarContent / SidebarFooter / SidebarInsetServer-safe layout regions with native props, stable refs, and an exact div contract for SidebarContent.
SidebarTrigger / SidebarRailNamed toggle controls with stable focus and ARIA relationships.
useSidebarExposes expanded, setExpanded, toggle, side, direction, and sidebarId.

Implementation contract

ContractValue
Registry itemsidebar-primitive installs 8 source files into the configured components directory.
Base UINo interactive primitive required.
Registry dependenciesNone.
Package dependencies@nerio-ui/adapters, clsx, react, tailwind-merge, tailwindcss

Styling contract

ContractValue
AuthoringComplete, statically detectable Tailwind CSS v4 recipes own component visuals.
ValuesSemantic and component --n-* variables remain the canonical customization layer.
OverridesCustomizable slots merge consumer className values with tailwindCn so conflicting utilities resolve deterministically.
Residual CSSOnly shared keyframes and scoped no-Preflight compatibility rules remain; there is no parallel visual selector layer.

Design notes

  • Persistence is consumer-owned. Read storage before choosing controlled state and write from onExpandedChange.
  • For mobile, render the shared navigation data inside Sheet instead of turning Sidebar into an AppShell.
  • AppSidebar, workspace switching, nested navigation, route matching, account menus, badges, and permissions remain Pro or consumer responsibilities.

Do / do not

Do

Use for a neutral persistent layout region that composes consumer-owned content.

Use controlled state when a product needs localStorage or cookie persistence.

Do not

Do not add route matching, navigation schemas, persistence, authorization, or account behavior to Core Sidebar.

Do not render desktop Sidebar and mobile Sheet as two simultaneously focusable trees.

Tokens

These are the primary customization points. Override semantic or component tokens instead of changing component source.

TokenPurpose
--n-sidebar-widthPublic customization point for this component contract.
--n-sidebar-collapsed-widthPublic customization point for this component contract.
--n-sidebar-inset-gapPublic customization point for this component contract.
--n-sidebar-region-paddingPublic customization point for this component contract.
--n-sidebar-rail-hit-areaPublic customization point for this component contract.
--n-sidebar-transition-durationPublic customization point for this component contract.
--n-sidebar-transition-easingPublic customization point for this component contract.
--n-sidebar-backgroundPublic customization point for this component contract.
--n-sidebar-foregroundPublic customization point for this component contract.
--n-sidebar-borderPublic customization point for this component contract.
--n-sidebar-control-backgroundPublic customization point for this component contract.
--n-sidebar-control-background-hoverPublic customization point for this component contract.
--n-sidebar-control-foregroundPublic customization point for this component contract.
--n-motion-hover-durationPublic customization point for this component contract.
--n-motion-hover-easingPublic customization point for this component contract.
--n-focus-ringPublic customization point for this component contract.