@molecule/app-sidebar-layout-react
v1.0.1
Published
Vertical sidebar app shell: brand block + vertical NavLinks + user-menu slot, with React Router Outlet for nested routes
Downloads
135
Readme
@molecule/app-sidebar-layout-react
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Vertical sidebar app shell layout.
Exports <SidebarLayout> plus the SidebarLayoutProps and
SidebarNavItem types — fixed-width left sidebar with brand link,
vertical nav links, and bottom user-menu / theme-toggle slots; the main
area on the right scrolls and renders React Router's <Outlet /> for
nested routes.
Quick Start
import { SidebarLayout } from '@molecule/app-sidebar-layout-react'
import type { SidebarNavItem } from '@molecule/app-sidebar-layout-react'
const NAV: SidebarNavItem[] = [
{ key: 'dashboard', to: '/dashboard', icon: 'dashboard', label: 'Dashboard' },
{ key: 'projects', to: '/projects', icon: 'folder', label: 'Projects' },
{ key: 'settings', to: '/settings', icon: 'settings', label: 'Settings' },
]
function AppShell() {
return <SidebarLayout appName="Acme App" navItems={NAV} />
}Mount it as a LAYOUT ROUTE so child routes render in the main area:
a parent route with element={<AppShell />} and your pages as child
routes.
Type
feature
Installation
npm install @molecule/app-sidebar-layout-react @molecule/app-react @molecule/app-ui react react-router
npm install -D @types/reactAPI
Interfaces
SidebarLayoutProps
Props accepted by the {@link SidebarLayout} component.
interface SidebarLayoutProps {
/** Brand text shown at the top of the sidebar (typically the app name). */
appName: string
/** Path the brand link navigates to. Defaults to `'/'`. */
logoTo?: string
/** Vertical nav items rendered in the sidebar. */
navItems: ReadonlyArray<SidebarNavItem>
/** Slot rendered at the bottom of the sidebar (typically a `<UserMenu />`). */
userMenu?: ReactNode
/** Optional slot rendered next to the user menu (typically a `<ThemeToggle />`). */
themeToggle?: ReactNode
/** Aria-label for the primary <nav>. */
navAriaLabel?: string
/**
* Sidebar width — a stack-agnostic preset (`'sm'` | `'md'` | `'lg'`) or an
* exact pixel `number`. Applied via inline style so no Tailwind width utility
* couples consumers to the styling library. Defaults to `'md'` (240px).
*/
sidebarWidth?: SidebarWidth
/**
* Legacy sidebar-width prop retained only for backward compatibility.
*
* @deprecated Use {@link SidebarLayoutProps.sidebarWidth} instead. A raw
* Tailwind width utility (`'w-60'`, `'w-64'`) coupled consumers to Tailwind.
* Still accepted for backward compatibility: a `w-<n>` value is PARSED to a
* pixel width and applied via inline style (never re-emitted as a class), so
* old callers keep working without reintroducing the coupling. `sidebarWidth`
* takes precedence when both are supplied.
*/
sidebarWidthClass?: string
/** Extra classes on the outer wrapper. */
className?: string
/** `data-mol-id` for AI-agent selectors. */
dataMolId?: string
}SidebarNavItem
Describes a single item in the sidebar's vertical navigation list.
interface SidebarNavItem {
/** Route path the link goes to. */
to: string
/** Stable key — used for React keys and i18n key suffix. */
key: string
/** Material symbol icon name. */
icon?: string
/** Visible label. Apps that route this through `t(...)` should pass the resolved string. */
label: string
}Types
SidebarWidth
Semantic sidebar width. Mapped to a fixed pixel width internally and applied via inline style (a width is one of the "specific values" a styling-agnostic ClassMap cannot express as a swappable token) so the sidebar renders the same regardless of which ClassMap bond is active — no Tailwind width utility leaks into consumer code.
sm→ 208px,md→ 240px (default),lg→ 256px.- Pass a raw
numberfor an exact pixel width.
type SidebarWidth = 'sm' | 'md' | 'lg' | numberFunctions
SidebarLayout(props)
Vertical sidebar shell with brand + vertical nav + bottom user-menu slot.
function SidebarLayout({
appName,
logoTo = '/',
navItems,
userMenu,
themeToggle,
navAriaLabel = 'Primary navigation',
sidebarWidth,
sidebarWidthClass,
className,
dataMolId,
}: SidebarLayoutProps): ReactElement<unknown, string | JSXElementConstructor<any>>props— Component props.
Injection Notes
Requirements
Peer dependencies:
@molecule/app-react^1.0.1@molecule/app-ui^1.0.1react^18.0.0 || ^19.0.0react-router^7.0.0 || ^8.0.0
Runtime Dependencies
@molecule/app-react@molecule/app-uireactreact-routerRouter required: calls
useLocation()and renders<Outlet />— it throws outside a react-router<Router>, and the main area stays empty unless it is a layout route with child routes.Fully ClassMap-driven: every layout/surface/border/text/state class is resolved through
getClassMap()(cm.pageShell,cm.page,cm.surface,cm.borderR,cm.bgPrimarySubtle/cm.textPrimaryfor the active item,cm.textMuted/cm.linkfor the rest, …), so swapping the ClassMap bond restyles the whole shell — no raw Tailwind/Material-3 utility class is baked in. The sidebar WIDTH is the one "specific value" a styling-agnostic ClassMap can't express, so it is applied via inline style: use the stack-agnosticsidebarWidthprop ('sm'|'md'|'lg'|pixelnumber), NOT a Tailwind width utility. The oldsidebarWidthClassprop is@deprecated— still accepted, but itsw-<n>value is parsed to pixels (never re-emitted as a class).iconvalues are Material Symbols ligature names rendered with thematerial-symbols-outlinedfont class — the one documented icon-font exception (a font ligature the consumer supplies as data, not a hardcoded chrome glyph). Without the Material Symbols font loaded, the raw icon NAME shows as text — omiticonwhen the font is not shipped.Active-nav highlighting picks the longest prefix-match of the current path; same-path clicks get a
#topfragment appended (same behavior as@molecule/app-safe-link-react).navAriaLabeldefaults to English "Primary navigation" — pass a translated string in localized apps (navlabels are plain strings; translate them upstream).Requires a bonded ClassMap. Sibling:
@molecule/app-shell-layout-reactis the top header/footer shell (router-free).
