App drawer rendered as an in-flow <aside> (inline mode) or a portaled modal panel (overlay mode), with header/body/footer sections, a mini collapsed rail that can persist across reloads via persistKey, and nested navigation (SidebarNav/Group/Item/Sub) with automatic active-trail expansion.
`SidebarNav` renders a <nav> landmark; `SidebarGroup` adds labelled sections, `SidebarItem` the links and `SidebarSub` collapsible branches (W3C disclosure-navigation pattern). An `active` item marks the current page and signals every ancestor sub (`data-active-trail`), so uncontrolled subs on the trail open automatically. In icon-collapse mode group labels and badges hide, item icons stay visible and uncontrolled subs close. Add `persistKey` to remember the collapsed state across reloads.
Rendering mode: in-flow <aside> or a portaled modal drawer with backdrop and focus trap.
open
boolean
—
Controlled open state.
defaultOpen
boolean
true
Initial open state when uncontrolled.
onOpenChange
(open: boolean) => void
—
Called when the open state changes.
side
"start" | "end"
"start"
Which inline edge the sidebar sits on.
width
number | string
"16rem"
Expanded width. Numbers are px.
collapsedWidth
number | string
"4rem"
Width in collapsed (mini rail) mode.
collapsed
boolean
—
Controlled mini rail mode (inline only).
defaultCollapsed
boolean
false
Initial collapsed state when uncontrolled.
onCollapsedChange
(collapsed: boolean) => void
—
Called when the collapsed state changes.
persistKey
string
—
Persists the collapsed state to storage under `zephora-sidebar:<persistKey>` and restores it on mount. The persisted value seeds the uncontrolled default; a controlled `collapsed` prop always wins.
persistStorage
"local" | "session"
"local"
Storage backing persistKey.
unstyled
boolean
false
Headless mode — skips Zephora styling.
SidebarHeader / SidebarBody / SidebarFooter props
Prop
Type
Default
Description
unstyled
boolean
false
Headless mode — skips Zephora styling.
…rest
HTMLAttributes<HTMLDivElement>
—
All native div props are forwarded. Body scrolls; header and footer stay fixed.
SidebarNav props
Prop
Type
Default
Description
aria-label
string
localized "Sidebar navigation"
Accessible name of the <nav> landmark.
unstyled
boolean
false
Headless mode — skips Zephora styling.
…rest
HTMLAttributes<HTMLElement>
—
All native nav props are forwarded. Children render inside a <ul>.
SidebarGroup props
Prop
Type
Default
Description
label
ReactNode
—
Small heading above the group; hidden in icon-collapse mode.
unstyled
boolean
false
Headless mode — skips Zephora styling.
…rest
LiHTMLAttributes<HTMLLIElement>
—
All native li props are forwarded. Children render inside a nested <ul>.
SidebarItem props
Prop
Type
Default
Description
href
string
—
Link target. Omitted while `disabled`.
icon
ReactNode
—
Leading icon; kept visible in icon-collapse mode.
active
boolean
false
Marks the current page: `aria-current="page"` + `data-active`, and signals every ancestor SidebarSub (active trail).
badge
ReactNode
—
Trailing badge (e.g. a count); hidden in icon-collapse mode.
disabled
boolean
false
Removes the href and sets aria-disabled + tabIndex=-1.